TTS 엔진을 교체했다. API 호출은 쉬운 부분이었다.
Google Chirp 3 HD로 AI 더빙 엔진을 교체하면서 마주한 실제 문제는 음성 합성이 아니라 타이밍 정합이었다. 19개 언어 더빙 파이프라인 구축 과정.
2026년 9월 13일
Katto는 이미 AI 더빙 기능을 갖추고 있었다. 크리에이터가 짧은 클립을 선택하고 언어를 고르면 번역된 버전을 받을 수 있었다. 초기 버전은 Kokoro를 사용했고 8개 언어를 지원했다.
최근 주 음성 엔진을 Google Cloud Text-to-Speech의 Chirp 3 HD로 전환했다. 목표는 명확해 보였다. 음성 품질을 개선하고 더 많은 언어를 추가하는 것. 현재 Katto 에디터는 19개 더빙 언어와 12개의 선별된 음성을 제공한다.
마이그레이션은 대부분 API 교체 작업일 거라 예상했다.
그렇지 않았다.
자연스러운 문장을 생성하는 것은 쉽다. 그 문장을 다른 화자가 남긴 정확한 시간 공간 안에서 시작하고 끝나게 만드는 것이 실제 더빙 문제다.
원본 화자가 2.4초 동안 말하고 번역본이 3.2초가 걸린다면, 좋은 TTS 모델이라고 해서 클립을 구할 수 있는 건 아니다. 음성이 다음 문장과 겹치거나, 자막이 어긋나거나, 음성을 급하게 들릴 때까지 가속해야 한다.
TTS 요청은 시스템에서 가장 작은 부분으로 드러났다.
최종 파이프라인
캐시된 단어 타이밍
|
v
고정된 시간 슬롯을 가진 구문 세그먼트
|
v
길이를 고려한 번역
|
v
Google Chirp 3 HD, 구문 단위 합성
|
v
FFmpeg 기반 제한된 오디오 정렬
|
+----> 동일 세그먼트 기반 번역 자막
|
v
최종 MP4 리먹스
각 단계는 더 단순한 버전이 다른 방식으로 실패했기 때문에 존재한다.
원본 타이밍을 데이터로 유지
Katto는 이미 전사 파이프라인에서 단어 타임스탬프를 갖고 있다. 전체 전사본을 하나의 블록으로 번역과 TTS에 보내지 않는다. 단어를 구문으로 묶는다.
구문은 문장 부호, 0.6초 이상의 정지, 또는 6초 초과 시점에서 끝난다. 모든 세그먼트는 원본 시작과 끝 시간을 유지한다. 이 숫자들이 이후 모든 단계의 계약이 된다.
전체 전사본을 합성하면 더 부드럽게 들릴 수 있지만, 음성을 비디오 타임라인에 다시 배치하는 데 필요한 앵커가 사라진다. 구문 단위 합성은 자연스러운 음성을 위한 충분한 맥락을 보존하면서 유용한 타이밍 경계를 유지한다.
발화 길이를 고려한 번역
올바른 문어 번역이 나쁜 더빙 번역일 수 있다. 일부 언어는 같은 의미를 표현하는 데 더 많은 음절이 필요하다. 직역은 모든 뉘앙스를 보존하면서도 슬롯에 맞지 않아 사용할 수 없을 수 있다.
각 구문 그룹에 대해 Claude Haiku에게 더 짧은 구문과 더 적은 음절을 선호하는 자연스러운 구어 번역을 요청한다. 응답은 모든 소스 세그먼트 인덱스를 보존한다.
프롬프트는 오디오 시스템의 일부다. 그 역할은 언어적 정확성만이 아니다. 나중에 필요한 시간 늘림을 줄이는 것도 포함한다.
이것은 여전히 휴리스틱이다. LLM은 선택된 음성이 페이싱도 바꾸기 때문에 지속 시간을 보장할 수 없다. 오디오 레이어는 여전히 생성된 WAV를 측정한다. 대상 언어와 소스 세그먼트를 키로 사용하는 프로세스 내 캐시 덕분에 worker가 살아 있는 동안 반복 렌더링에서 번역을 재사용할 수 있다.
구문 단위 합성
각 번역된 구문은 24kHz LINEAR16 오디오로 Google Cloud Text-to-Speech REST API로 전송된다. 음성 이름은 Google이 문서화한 locale-Chirp3-HD-speaker 형식을 따른다.
Google은 Katto가 현재 노출하는 것보다 더 많은 Chirp 3 HD 로케일을 지원한다. 제품을 의도적으로 완전한 경로를 통해 연결된 19개 언어로 제한했다. UI, 로케일 매핑, 폰트, 자막, 폴백 동작을 포함한다. API가 언어를 주장한다고 해서 주변 제품이 올바르게 지원한다는 의미는 아니다.
완벽한 정렬은 결과가 듣기 불편하다면 유용하지 않다. 수학적으로 완벽한 타이밍을 쫓기 전에 명료성을 보존하는 것이 더 유용한 규칙이다.
슬롯에 음성 맞추기
합성 후 생성된 지속 시간을 원본 슬롯과 비교한다.
음성이 약간 길면 FFmpeg의 atempo 필터가 피치를 유지하면서 속도를 높인다. 가속은 1.3배로 제한한다.
이 제한이 중요하다. 초기 1.6배 제한은 더 많은 구문을 맞췄지만, 일부 음성이 부자연스럽게 급하게 들렸다.
각 조정된 구문은 마스터 트랙의 원본 오프셋에 배치된다. 짧은 구문은 자연스러운 정지를 남긴다. 긴 구문은 제한된 보정을 받는다. 이것이 모든 병리적 번역을 해결하지는 않는다. 더 유용한 규칙을 강제한다.
음성과 자막에 동일한 시계 부여
합성 응답은 오디오를 제공하지, 새로 말한 텍스트에 대한 신뢰할 수 있는 단어 타임스탬프를 제공하지 않는다. 단어 수준 타이밍을 만들어내면 자막이 정확해 보이지만 틀릴 것이다.
따라서 더빙된 클립은 음성에 사용된 것과 동일한 번역 세그먼트에서 생성된 구문 수준 자막을 사용한다. 시작과 끝 시간은 이미 오디오 배치와 일치한다.
렌더러는 대상 스크립트를 다루는 폰트도 선택한다. 라틴 폰트는 일본어, 중국어, 힌디어, 아랍어에 충분하지 않다. 인트로 타이틀과 AI 훅도 동일한 현지화 경로를 따르므로, 화면이 한 언어를 말하고 다른 언어를 표시하지 않는다.
일반적인 프로덕션 문제도 중요했다
테스트한 모든 로케일에서 모든 선별된 화자가 작동하지는 않았다. 선택한 음성을 사용할 수 없으면 Katto는 선택한 성별에 대해 알려진 기본값으로 한 번 재시도한다. 에디터의 라이브 미리보기는 동일한 Google 엔진을 호출한다. 다른 모델의 샘플은 사용자가 받지 못할 음성을 선택하게 만든다.
프로덕션 API 키는 VPS IPv4 주소로 제한되지만, VPS는 Google에 도달할 때 IPv6를 선호했다. TTS 호출이 IPv4를 통해 강제될 때까지 유효한 요청이 거부되었다. API, 키, 코드는 올바랐다. 네트워크 경로가 아니었다.
더빙은 별도의 비디오 변형을 생성한다. 번역, 합성, 자막 렌더링 또는 리먹싱이 실패하면 원본 클립은 그대로 유지된다. 초기에 지원한 8개 언어는 Google 경로가 비활성화되거나 구성되지 않은 경우 Kokoro를 폴백으로 사용할 수 있다.
변한 것과 변하지 않은 것
눈에 보이는 결과는 8개에서 19개 더빙 언어로의 확장과 선택 가능한 음성 및 라이브 미리보기였다.
더 깊은 개선은 아키텍처였다. 번역, 음성, 자막, 오버레이, 비디오 렌더링이 이제 하나의 시간 단위인 구문 세그먼트를 공유한다.
시스템은 원본 화자를 복제하거나, 립싱크를 수행하거나, 생성된 단어 타임스탬프를 만들어내지 않는다. 매우 긴 번역은 여전히 이상적인 슬롯을 초과할 수 있다. 이러한 제한은 파이프라인이 제공할 수 없는 정밀도를 주장하는 것보다 낫다.
음성 엔진을 교체한다고 생각했다. 결국 미디어 파이프라인의 거의 모든 단계 사이의 계약을 강화하게 되었다.
API 호출은 쉬운 부분이었다. 결과를 원본 타임라인에 속하게 만드는 것이 작업이었다.
Katto는 긴 비디오를 짧은 세로 클립으로 변환하고 이제 그 클립을 19개 언어로 더빙할 수 있다. 다국어 비디오를 구축하고 있다면, 음성이 급하게 들리지 않게 타이밍을 처리하는 방법을 듣고 싶다.