Back to Blog

자막이 포함된 화상 통화 앱 구축

최소 50%의 사람들이 드라마나 영화를 볼 때 자막을 사용합니다. 때로는 소리가 잘 들리지 않을 때도 있고, 다른 때는 읽을 수 있는 옵션을 선호하기도 합니다. 만약 그 같은 경험을 영상 통화에도 적용할 수 있다면 어떨까요? 바로 이 가이드에서 그 방법을 구현할 것입니다.

선행 조건

  1. Flutter
  2. 아고라 개발자 계정 (Agora)
  3. 아고라의 실시간 트랜스크립션과 통신하기 위한 백엔드 서버 (이 예제 서버를 사용할 수 있습니다: this example server)

프로젝트 설정

이 가이드에서는 아고라를 이용하여 간단한 비디오 통화가 어떻게 작동하는지에 대한 기본적인 이해를 전제로 합니다.

아고라 기본 개념을 이해하지 못하신 경우, 문서 내의 Flutter 빠른 시작 가이드를 참고하시거나, Video Call with Agora Flutter 과정을 통해 더 깊이 학습하실 수 있습니다.

이 가이드의 출발점은 아고라 구축된 간단한 비디오 통화 앱으로, 여기에서 확인하실 수 있습니다.

스타터 코드에는 단 하나의 버튼이 있는 랜딩 화면이 있습니다. 이 버튼은 사용자를 통화 참여로 초대합니다. 이 통화는 test라는 단일 채널에서 발생합니다 (데모용입니다, 괜찮으시죠?). 통화 화면에는 원격 사용자의 비디오, 로컬 비디오, 그리고 통화 종료 버튼이 있습니다. 우리는 이벤트 핸들러를 사용하여 사용자를 뷰에 추가하거나 제거합니다.

Speech to Text

아고라에는 특정 채널의 통화 내용을 실시간으로 텍스트로 변환할 수 있는 'Real Time Transcription'이라는 제품이 있습니다.

Real-Time Transcription은 AI 마이크로서비스를 활용해 통화 연결 및 음성 텍스트 변환을 수행하는 RESTful API입니다. 이 변환된 텍스트는 onStreamMessage 이벤트를 통해 비디오 통화 스트림에 직접 전송됩니다. 선택적으로 클라우드 제공업체에 저장할 수도 있으며, 이 가이드에서는 해당 방법을 설명합니다.

백엔드

실시간 텍스트 변환은 비즈니스 서버에 구현되어야 합니다. 백엔드가 마이크로서비스를 관리함으로써 각 채널 내에서 실시간 텍스트 변환이 단일 인스턴스로 실행되도록 보장할 수 있습니다. 또한 텍스트 변환 서비스에 토큰을 전달해야 하므로, 백엔드에서 이를 처리하면 클라이언트 측에 토큰이 노출되지 않습니다.

우리는 이 서버를 백엔드로 사용할 것입니다. 이 서버는 두 개의 엔드포인트를 노출합니다: 하나는 트랜스크립션을 시작하기 위한 것이고, 다른 하나는 트랜스크립션을 종료하기 위한 것입니다.

실시간 트랜스크립션 시작하기

/start-transcribing/<--Channel Name-->

실시간 트랜스크립션 멈추기

/stop-transcribing/<--Channel Name-->/<--Task ID-->/<--Builder Token-->

통화 중 트랜스크립션 시작

Flutter 애플리케이션에서 네트워크 호출을 수행하려면 ‘http’ 패키지를 사용할 수 있습니다. 프론트엔드 앱과 백엔드 서버 모두에서 동일한 App ID를 사용해야 동일한 Agora 서비스에 연결할 수 있습니다. 그런 다음 API를 호출하여 트랜스크립션을 시작합니다.

call.dart 파일 내에서 다음 startTranscription 함수를 추가할 수 있습니다:

Future<void> startTranscription({required String channelName}) async {
  final response = await post(
    Uri.parse('$serverUrl/start-transcribing/$channelName'),
  );
  if (response.statusCode == 200) {
    print('Transcription Started');
    taskId = jsonDecode(response.body)['taskId'];
    builderToken = jsonDecode(response.body)['builderToken'];
  } else {
    print('Couldn\'t start the transcription : ${response.statusCode}');
  }
}

이 함수는 join 호출 메서드 직후에 호출되도록 설정되어 첫 번째 사용자가 채널에 가입하자마자 실행됩니다. 성공적인 응답의 일환으로 Task ID와 Builder Token을 받게 됩니다. 이 값들은 트랜스크립션을 중지하기 위해 필요하므로 반드시 저장해 두세요.

전사 처리가 성공적으로 시작되면 채널 내의 사용자처럼 동작합니다. 하지만 실제 사용자가 아니라 봇입니다. 이 서비스는 백엔드 서버 내에서 자체 UID를 정의합니다. 위에서 링크한 서버를 사용 중이라면 UID는 101입니다. 이 UID는 onUserJoined 이벤트에서 원격 사용자 목록에서 제외할 수 있습니다.

onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {
  if (remoteUid == 101) return;
  setState(() {
    _remoteUsers.add(remoteUid);
  });
}

트랜스크립 끝내기

우리는 시작 함수와 유사한 함수를 사용하여 실시간 전사 작업을 종료합니다. 이 함수는 stopTranscription로 명명되며, 실시간 전사 서비스를 중지하기 위해 작업 ID와 빌더 토큰을 전달해야 합니다.

우리는 콜 화면의 dispose 메서드에서 stopTranscription 메서드를 호출할 것입니다. 이로써 채널을 떠나기 전에 트랜스크립션을 중지하고 엔진 리소스를 해제합니다.

Future<void> stopTranscription() async {
  final response = await post(
    Uri.parse('$serverUrl/stop-transcribing/$taskId/$builderToken'),
  );
  if (response.statusCode == 200) {
    print('Transcription Stopped');
  } else {
    print('Couldn\'t stop the transcription : ${response.statusCode}');
  }
}

트랜스크립션 가져오기

비디오 통화 중 자막을 확인하려면 이벤트 핸들러에서 onStreamMessage 이벤트를 사용하세요.

onStreamMessage: (RtcConnection connection, int uid, int streamId,
    Uint8List message, int messageType, int messageSize) {
  print(message);
}

위 코드는 당신만이 이해할 수 있는 숫자 배열을 출력합니다. 이 숫자들은 Google의 Protocol Buffers(프로토버퍼라고도 함)를 사용하여 생성되었습니다.

프로토버퍼는 플랫폼에 독립적인 방식으로 데이터를 인코딩합니다. 이는 앱이나 소프트웨어가 자신의 언어에 따라 이 데이터를 가져오고 시리얼화할 수 있음을 의미합니다.

트랜스크립 해독하기

우리는 메시지를 해독하기 위해 Protocol Buffer를 사용할 것입니다. 이 경우, 무작위로 보이는 숫자들을 Message라는 객체로 시리얼화할 것입니다.

start: .proto 파일을 다음과 같은 내용으로 생성합니다:

syntax = "proto3";
package call_summary;
message Message {
  int32 vendor = 1;
  int32 version = 2;
  int32 seqnum = 3;
  int32 uid = 4;
  int32 flag = 5;
  int64 time = 6;
  int32 lang = 7;
  int32 starttime = 8;
  int32 offtime = 9;
  repeated Word words = 10;
}
message Word {
  string text = 1;
  int32 start_ms = 2;
  int32 duration_ms = 3;
  bool is_final = 4;
  double confidence = 5;
}

이 파일을 새로운 폴더에 넣어주세요: lib/protobuf/file.proto. 이 파일은 생성기가 Message 객체를 생성하기 위한 입력 파일입니다.

protobuf를 사용하려면 컴퓨터에 protobuf 컴파일러를 설치해야 합니다. Mac(brew install protobuf) 및 Linux(apt install -y protobuf-compiler)용 패키지 관리자를 통해 설치 가능합니다. Windows 또는 특정 버전이 필요한 경우 Prottobuf 다운로드 페이지를 확인하세요.

프로젝트 내부에 protobuf dart 패키지를 설치해야 합니다. 이를 위해 flutter pub add protobuf를 실행하세요.

이제 터미널에서 다음 명령어를 실행하세요. 동일한 lib/protobuf 폴더에 4개의 파일이 생성됩니다.

protoc --proto_path= --dart_out=. lib/protobuf/file.proto

프로토버프가 설정되었으므로, 새로운 Message 객체를 사용하여 영어로 변환된 텍스트를 가져올 수 있습니다. 이 객체에는 변환된 문장들이 포함된 words 배열이 있습니다. 새로운 단어가 들어올 때마다 현재 문장이 연결되므로 편리합니다. 또한 변수 subtitle를 가장 최신 text로 덮어쓸 수 있습니다.

onStreamMessage: (RtcConnection connection, int uid, int streamId,
    Uint8List message, int messageType, int messageSize) {
  Message text = Message.fromBuffer(message);
  setState(() {
    subtitle = text.words[0].text;
  });
},

우리는 subtitle라는 이름의 String 변수를 생성합니다. 이 변수는 화면 하단에 표시됩니다. onStreamMessage 콜백에서 새로운 단어가 가져올 때마다 해당 변수를 업데이트하고 최신 자막을 표시하기 위해 재구성을 트리거합니다.

Padding(
  padding: const EdgeInsets.all(32.0),
  child: Center(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.end,
      children: [
        Container(
          margin: const EdgeInsets.only(bottom: 10),
          padding: const EdgeInsets.all(10),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(8),
            color: Colors.white,
          ),
          child: Text(subtitle),
        ),
       //... End Call Button
      ],
    ),
  ),
),

앱 실행하기

이로써 자막이 포함된 완전한 비디오 통화가 작동합니다. 이 앱을 flutter run 명령어로 실행한 후, “test” 채널에 참여하기 위해 버튼을 클릭하면, 말할 때 화면 하단에 자막이 표시됩니다.

마치기

이로써, 채널에 누군가가 가입하자마자 실시간 자막 서비스를 트리거하는 애플리케이션을 구축했습니다. 이제 말해지는 내용을 놓치는 걱정을 할 필요가 없습니다.

완전한 코드는 여기에서 확인할 수 있습니다. 이 가이드를 기반으로 더 깊이 탐구하려면 실시간 자막 문서를 참고하세요.

읽어주셔서 감사합니다!

RTE Telehealth 2023
Join us for RTE Telehealth - a virtual webinar where we’ll explore how AI and AR/VR technologies are shaping the future of healthcare delivery.

Learn more about Agora's video and voice solutions

Ready to chat through your real-time video and voice needs? We're here to help! Current Twilio customers get up to 2 months FREE.

Complete the form, and one of our experts will be in touch.

Try Agora for Free

Sign up and start building! You don’t pay until you scale.
Try for Free