| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- 팀프로젝트
- react
- 알고리즘
- HTML기초
- 정렬
- CSS
- js
- 프로그래머스
- javascript
- 정글
- html
- 그래프
- BFS
- 프론트앤드
- 코딩테스트
- c언어
- 그리디
- Python
- Git
- DFS
- 백준
- Mini-React
- 개발자
- 코딩
- 크래프톤 정글
- frontend
- 프론트엔드
- 혼자 공부해서 개발까지
- 해시
- 알고리즘 기초
- Today
- Total
민혁이의 IT스토리
실시간 AI 번역 영상통화 본문
"지난번 WebRTC 학습 경험을 바탕으로, 이번 팀 프로젝트에서 'AI 실시간 번역 영상통화 서비스' 개발을 맡게 되었습니다. 제 역할은 핵심 기능인 실시간 미디어 전송 파트였습니다.
개발 도중 팀원들과 흥미로운 아이디어가 나왔습니다. '단순히 번역만 보여주는 게 아니라, AI 음성(TTS)이 발화자의 입모양에 맞춰 나오는, 마치 애니메이션 더빙 같은 경험을 주면 어떨까?'
아이디어는 좋았지만, 기술적으로는 큰 난관이었습니다. 실시간성을 생명으로 하는 WebRTC에서 '싱크(Sync)'를 맞춘다는 건 정반대의 접근이 필요했기 때문입니다. 오늘은 이 '더빙 같은 영상통화'를 구현하기 위해 제가 고민했던 흔적과, 의도된 지연(Intentional Delay) 및 Simulcast를 활용한 해결 과정을 공유하려 합니다.
WebRTC의 속도 vs AI의 처리 시간
WebRTC의 지상 과제는 Low Latency(저지연)입니다. 보통 0.5초 미만의 딜레이를 목표로 하죠. 하지만 AI가 음성을 듣고(STT), 번역하고(Translation), 다시 음성으로 만드는(TTS) 과정은 필연적으로 시간이 걸립니다. 테스트 결과 약 1.5초에서 2초가 소요되었습니다.
아무런 조치 없이 이 둘을 연결하면 이런 상황이 벌어집니다.
- 0.0초: 상대방이 "안녕하세요"라고 말함 (영상 도착)
- ... (어색한 침묵)
- 1.8초: 번역된 AI 음성 "Hello" 도착
화면 속 상대방의 입은 이미 다 움직이고 멈췄는데, 2초 뒤에 목소리가 들리는 이른바 복화술 현상이 발생했습니다. 이는 우리가 목표로 했던 애니메이션 더빙과는 거리가 멀었습니다.
해결 전략: 역발상 (Intentional Delay)
해결책: 영상을 AI 속도에 맞춰 '기다리게' 하자
우리는 결단을 내려야 했습니다. AI 처리 속도를 0.1초로 줄이는 건 불가능했습니다. 그렇다면 남은 방법은 하나, "영상이 도착해도 바로 보여주지 않고, AI 목소리가 준비될 때까지 붙잡아두는 것"이었습니다.
이를 위해 커스텀 버퍼(Custom Buffer) 로직을 설계했습니다.
- 기존: 영상 패킷 도착 → 즉시 렌더링 (<video> 태그)
- 변경: 영상 패킷 도착 → 큐(Queue)에 저장 → 번역 완료 신호 대기 → 싱크 맞춰서 재생
물론, 실시간 통화에서 2초의 딜레이는 치명적일 수 있습니다. 하지만 우리는 '빠른 소통'보다 '정확하고 몰입감 있는 소통'이 더 중요하다고 판단했습니다. 또한, 사용자가 이 딜레이를 '렉(Lag)'으로 느끼지 않도록 "번역 중..."이라는 시각적 UI와 오디오 더킹(원본 소리를 작게 깔아줌) 기술을 UX적으로 보완했습니다.
기술적 방어: 시뮬캐스트 (Simulcast)
딜레이를 줬기 때문에 화질까지 나빠지면 안 된다는 논리로 Simulcast를 연결합니다.
2초의 딜레이를 줬는데 영상마저 버벅거린다면 사용자는 바로 이탈할 것입니다. 특히 송신자가 고화질(720p) 영상을 보낼 때, 수신자의 네트워크가 좋지 않다면 영상이 멈추는(Freezing) 현상이 발생합니다.
이를 해결하기 위해 Simulcast(시뮬캐스트) 기술을 적용했습니다.
- 개념: 송신자가 고화질(High), 중화질(Mid), 저화질(Low) 3개의 비디오 스트림을 동시에 보냅니다.
- 작동: SFU(미디어 서버)가 수신자의 네트워크 상태를 실시간으로 감시하다가, 대역폭이 부족해지면 자동으로 저화질 스트림으로 갈아아탑니다.
이를 통해 2초의 딜레이가 있더라도, 영상 자체는 절대 멈추지 않고 매끄럽게 재생되도록 안정성을 확보했습니다.
구현 코드
핵심 구현 코드 (React + WebRTC)
실제 구현에서 가장 중요했던 부분은 Simulcast 송출 설정과 수신 측의 버퍼링 처리였습니다.
Simulcast 인코딩 설정:
// useMeetingConnection.ts (핵심 구현 요약)
import {
MeetingSessionConfiguration,
VideoPriorityBasedPolicy,
ConsoleLogger,
LogLevel
} from 'amazon-chime-sdk-js';
// 1. Chime SDK 세션 설정 생성
const meetingSessionConfiguration = new MeetingSessionConfiguration(
{ MeetingId: sessionInfo.chimeMeetingId, ... },
{ AttendeeId: attendee.attendeeId, ... }
);
// 2. Simulcast 활성화 (핵심!)
// 이 옵션 하나로 High/Medium/Low 멀티 스트림 송출이 자동 설정됩니다.
meetingSessionConfiguration.enableSimulcastForUnifiedPlanChromiumBasedBrowsers = true;
// 3. 스마트 다운링크 정책 (VideoPriorityBasedPolicy) 설정
// 서버 사이드 트래픽 최적화를 위해 클라이언트의 수신 정책을 정의합니다.
// Active Speaker에게 대역폭을 우선 할당하고, 작은 타일은 저화질로 받습니다.
const logger = new ConsoleLogger('MeetingLogger', LogLevel.INFO);
const videoDownlinkPolicy = new VideoPriorityBasedPolicy(logger);
meetingSessionConfiguration.videoDownlinkBandwidthPolicy = videoDownlinkPolicy;
// 4. 회의 입장
await meetingManager.join(meetingSessionConfiguration);
await meetingManager.start();
코드의 의미: "수백 줄에 달하는 WebRTC의 RTCPeerConnection 및 Transceiver 설정을 직접 작성하는 대신, AWS Chime SDK의 MeetingSessionConfiguration을 통해 단 몇 줄로 엔터프라이즈급 Simulcast 아키텍처를 구현했습니다."
배운점
이번 프로젝트를 통해 "WebRTC = 무조건 Low Latency"라는 고정관념을 깰 수 있었습니다. 기술의 정답은 정해져 있지 않습니다. 서비스의 목적이 '단순한 정보 전달'이냐 '몰입감 있는 소통'이냐에 따라, 때로는 기술적 금기(Latency 늘리기)가 최고의 해결책이 될 수 있음을 배웠습니다.
앞으로는 AI 모델 경량화를 통해 이 '의도된 지연' 시간을 2초에서 1초, 0.5초로 줄여나가는 것이 저희 팀의 다음 과제입니다.
'web' 카테고리의 다른 글
| [Redis] 하드 디스크 말고 메모리에 저장한다고? Redis 완벽 정리 (0) | 2026.01.05 |
|---|---|
| 폴더 구조 그대로 업로드하기: FileSystem API 활용법 (0) | 2025.12.29 |
| WebRTC 화상회의, 아무나 들어오게 할 건가요? (0) | 2025.12.27 |
| [WebRTC] - SFU 알아보기 (0) | 2025.12.22 |
| 웹서버 인증서 (0) | 2025.11.12 |