Gemini TTS로 제품 영상에 영어·일본어·한국어 내레이션 넣기

Ofox Gemini TTS로 같은 제품 데모를 세 언어로 제작합니다. 대본 현지화, 실제 WAV 길이 측정, 언어별 타임라인 조정 과정을 MP4와 재현 코드로 확인하세요.

연한 분홍색 배경 위 종이비행기 선화와 동심원, Gemini TTS 제목이 있는 표지.

제품 데모 하나를 영어·일본어·한국어 버전으로 만들려면 대본을 현지화하고, 각 언어의 음성을 따로 생성한 뒤, 실제 파일 길이에 맞춰 타임라인을 다시 구성해야 합니다. 자막만 번역한다고 목소리까지 바뀌지는 않습니다. 문장 길이가 비슷해도 같은 장면 안에 들어간다는 보장은 없습니다.

2026년 10월 9일 Ofox에서 google/gemini-3.8-flash-tts와 Kore 음성을 사용해 일본어 WAV 5개, 한국어 WAV 5개를 생성했습니다. 영어는 앞선 영상 내레이션 튜토리얼에서 실제 생성한 다섯 파일을 재사용합니다. 이번 글은 언어별 장면 길이를 계산하고 세 개의 결과 영상을 제공하는 실습입니다. 언어나 음성 제공업체의 순위를 매기는 비교가 아닙니다.

전체 프로젝트 다운로드, 영어 MP4, 일본어 MP4, 한국어 MP4를 확인할 수 있습니다. 저장된 파일로 재구성할 때는 API를 호출하지 않습니다.

1. 현지화 범위를 먼저 정하기

입력은 Opus 제품 데모 제작 시리즈에 사용한 30초짜리 스크린샷 영상입니다. 화면은 9월 30일에 촬영한 영어 UI입니다. 이번 작업에서 Opus로 새 영상을 생성하지 않았습니다. Gemini가 소리를 생성하고, Python과 FFmpeg가 기존 화면에 배치했습니다.

따라서 결과물은 세 언어의 내레이션 버전입니다. 인터페이스까지 모두 현지화한 영상은 아닙니다. 스크린샷과 영어 제목 카드는 동일하며, 새 자막, 번역된 UI, 음성 복제, 립싱크도 포함하지 않습니다. 캠페인에 현지 언어 화면이 필요하다면 실제 지원되는 현지화 화면을 확보하는 등 별도 편집이 필요합니다. 스크린샷의 글자만 바꿔 제품이 해당 언어를 지원하는 것처럼 보이게 해서는 안 됩니다.

생성 전에 게시 조건도 확인하세요. 튜토리얼 페이지에는 34초 영상이 괜찮아도, 30초 제한이 있는 광고 지면에는 맞지 않을 수 있습니다. 이번 예제는 말을 끝까지 남기기 위해 영상을 늘립니다. 길이가 고정된 작업이라면 해당 대사를 줄여 다시 생성해야 합니다. 마지막 단어를 잘라내는 방식으로 길이를 맞추지 않습니다.

세 언어는 기획, 모델 목록, 문서 위치, API 참조 문서, 최종 확인이라는 안정적인 내용만 설명합니다. 과거 화면에 보이는 가격, 모델 수, 프로모션을 현재 제품의 약속처럼 읽지 않습니다. 화면의 촬영일은 오늘의 조건을 증명하지 않습니다.

2. 긴 문단 대신 다섯 문장으로 현지화하기

장면별 파일은 수정 범위를 줄여 줍니다. API 참조 문서 문장의 발음이 문제라면 그 문장만 새로 만들면 됩니다. 전체 내레이션을 다시 생성할 필요가 없습니다. 검토자도 의미, 말투, 화면에서 보이는 동작을 문장별로 비교할 수 있습니다.

영어 첫 문장은 “A clear product video starts with a clear brief.”입니다. 일본어는 わかりやすい製品動画は、目的を明確にすることから始まります。, 한국어는 이해하기 쉬운 제품 영상은 명확한 기획에서 시작됩니다.로 옮겼습니다. 단어를 그대로 대입하기보다 같은 작업 의미를 전달하도록 구성했습니다.

네 번째 일본어 문장은 API 참조 페이지를 예로 드는 관계를 유지합니다. この API リファレンスのように、各シーンに対応する実際のページを示します。라고 썼습니다. 한국어에서는 API 참조 문서라는 표현과 뒤의 설명으로 현재 보여 주는 대상을 밝힙니다. 원문에 없던 API 기능을 추가하지 않았습니다.

다운로드의 narration-drafts.json에 15개 문장이 모두 있습니다. 파일명은 편집 가능한 원본 대본이라는 뜻이며 미검토 상태를 뜻하지 않습니다. 일본어와 한국어 텍스트는 생성 전에 독립 AI 언어 검토를 받았습니다. 사람이 진행한 원어민 녹음이나 청취 평가가 아닙니다. 특히 글에서 “API”가 맞게 쓰였다는 사실은 생성된 소리가 어떻게 읽는지 증명하지 못합니다.

자체 제품으로 작업한다면 제품명, 약어, UI 라벨, 영어로 남겨야 할 단어를 먼저 정리하세요. 대본과 실제 소리의 검토를 구분하고, 승인한 텍스트를 해당 WAV 옆에 보관합니다. 나중에 글만 바꿨는데 오래된 녹음을 새 대사의 결과로 오해하는 일을 막을 수 있습니다.

3. 언어와 형식을 명시해 요청하기

정확한 모델 ID와 게이트웨이 호출 예제는 현재 Gemini TTS 모델 페이지에서 확인합니다. 음성 Kore, WAV, speed: 1.0은 공통으로 유지했고 언어 코드는 en-US, ja-JP, ko-KR를 각각 사용했습니다.

실제 Ofox 영어 Gemini TTS 모델 페이지에 표시된 음성 요청 예제와 파일 형식 옵션

10월 9일에 캡처한 실제 영어 화면입니다. 화면 예제의 속도는 1.1이지만 이 프로젝트의 저장된 요청은 1.0입니다. 화면은 API 호출 예제를 보여 주고, 성공한 호출은 응답 기록과 실제 음성 파일로 확인합니다.

아래는 일본어 요청 예제입니다. 한국어로 호출할 때는 승인한 한국어 텍스트와 ko-KR를 함께 넣어야 합니다. 문장만 바꾸고 일본어 코드를 남기지 마세요.

import os
from pathlib import Path
import requests

payload = {
    "model": "google/gemini-3.8-flash-tts",
    "voice": "Kore",
    "input": "次に、ドキュメントがどこにあるかを案内します。",
    "language_code": "ja-JP",
    "speed": 1.0,
    "response_format": "wav",
}
r = requests.post(
    "https://api.ofox.run/v1/audio/speech",
    headers={"Authorization": "Bearer " + os.environ["OFOX_API_KEY"]},
    json=payload,
    timeout=(15, 120),
)
r.raise_for_status()
if not r.headers.get("content-type", "").startswith("audio/"):
    raise RuntimeError("Expected audio; inspect the response")
Path("ja-line-3.wav").write_bytes(r.content)

키는 환경 변수로 전달하고 브라우저 코드나 공유 프로젝트에 넣지 않습니다. 앞선 튜토리얼의 전체 클라이언트는 미디어 도구를 확인하고 안전한 응답 정보를 저장하며, 비용이 발생할 수 있는 POST를 자동 재시도하지 않습니다. 타임아웃은 서버가 처리하지 않았다는 증거가 아닙니다. 재요청 전에 상태와 사용 내역을 확인합니다.

새 요청 10개는 모두 HTTP 200이었고, 출력은 24kHz 모노 16비트 PCM WAV였습니다. 전체 디코딩도 통과했습니다. 이는 해당 입력과 실행 날짜의 성공을 보여 줄 뿐, 다음 실행에서도 동일한 소리가 나온다는 보장은 아닙니다. 파라미터, 생성 시각, 오디오 해시를 함께 남기고 음성이나 결과가 바뀌면 다시 측정합니다.

4. 편집 전에 실제 길이 비교하기

표의 길이는 무음 구간을 포함한 WAV 전체 길이이며 단어 경계가 아닙니다. 글자 수로 추정하지 말고 ffprobe로 실제 파일을 확인하세요.

ffprobe -v error -show_entries stream=codec_name,sample_rate,channels \
  -show_entries format=duration -of json ja/line-1.wav
장면영어 WAV일본어 WAV한국어 WAV원래 장면
명확한 기획3.56초5.32초4.68초4초
모델 목록4.64초4.80초4.72초7초
문서3.44초3.80초4.28초7초
API 참조 문서4.96초6.12초6.76초7초
마무리 안내5.44초5.48초5.64초5초

첫 장면만 봐도 영어 타임라인을 그대로 쓸 수 없습니다. 일본어는 소리만 5.32초여서 원래 4초 장면을 넘습니다. 여기에 화면을 볼 여유도 필요합니다. 한국어 API 문장도 시작과 끝의 여백을 더하면 장면을 늘려야 합니다.

이 다섯 문장으로 “일본어는 항상 느리다”거나 “한국어는 언제나 더 길다”고 일반화하면 안 됩니다. 표현, 문장부호, 목소리, 출력 변동이 모두 길이에 영향을 줍니다. 여기서 얻을 수 있는 결론은 각 파일을 측정하고 해당 장면의 편집 방식을 명시적으로 정해야 한다는 것입니다.

5. 언어마다 타임라인 다시 만들기

원본 컷은 0, 4, 11, 18, 25, 30초입니다. 합성 스크립트는 다섯 장면의 순서를 유지하면서 새 길이를 계산합니다. 말하기 전 0.35초, WAV 종료 후 최소 0.65초를 확보합니다. 부족하면 그 장면의 마지막 프레임을 유지하며, 목소리를 빠르게 하거나 자르지 않습니다.

30fps 계산식은 다음과 같습니다.

scene_frames = ceil(max(original_scene_seconds, wav_seconds + 1.0) * 30)
scene_seconds = scene_frames / 30
speech_start = cumulative_scene_seconds + 0.35

정수 프레임으로 올림하므로 소수점 길이를 단순히 더한 값과 약간 다를 수 있습니다. 최종 영어는 약 32.03초, 일본어 33.97초, 한국어 34.13초입니다. 이 글의 영어 결과도 앞선 32초 파일과 바이트 단위로 같지는 않습니다. 이번에는 세 언어에 같은 장면별 규칙을 적용했습니다.

Python 3, FFmpeg, ffprobe를 설치하고 프로젝트를 푼 디렉터리에서 실행합니다.

python3 assemble_localized.py en source.mp4 rebuilt-en
python3 assemble_localized.py ja source.mp4 rebuilt-ja
python3 assemble_localized.py ko source.mp4 rebuilt-ko

각 결과 폴더에는 narrated.mp4, narration.wav, timing.json, probe.json이 생깁니다. 시간표는 원본 구간, 새 장면 길이, 추가 정지 시간, 음성 시작·종료, WAV 해시를 기록합니다. 이전 결과를 실수로 덮어쓰지 않도록 새 출력 폴더를 지정하세요.

스크린샷 데모는 짧게 마지막 프레임을 유지해도 참고 화면을 계속 보여 줄 수 있습니다. 그러나 인물이 말하는 장면, 커서 이동, 빠른 동작에 자동으로 적용할 수 있는 방법은 아닙니다. 그런 경우 해당 화면을 다시 편집하거나 생성해야 합니다. 프레임을 멈춘다고 입 모양이 다른 언어와 맞아지지는 않습니다.

6. 파일과 발음을 따로 검증하기

세 결과는 H.264 영상과 AAC 음성을 포함합니다. 로컬 검사는 스트림 길이를 계획한 타임라인과 비교하고 각 파일을 끝까지 디코딩합니다.

ffprobe -v error -show_streams -show_format -of json rebuilt-ja/narrated.mp4
ffmpeg -v error -i rebuilt-ja/narrated.mp4 -f null -

가장 긴 문장과 연장한 모든 장면을 눈으로 확인하세요. 영어 UI를 그대로 쓰므로 일본어·한국어 목소리가 작업을 설명하더라도 화면 라벨이 번역되었다고 말하면 안 됩니다. 배포 설명문에서도 같은 범위를 지켜야 합니다.

기술 검증은 발음 평가가 아닙니다. 수정한 버전을 캠페인에 사용하기 전에 “API”, 제품명, 문장 끝, 다음 장면으로 넘어가는 부분을 포함해 최종 음성을 끝까지 들으세요. 본문은 사람이 참여한 청취 평가를 보고하지 않으며, 원어민 수준이거나 다른 서비스보다 우수하다고 주장하지 않습니다. 다운로드 MP4는 실제 결과를 직접 평가할 수 있게 제공합니다.

다른 모델의 전사는 누락이 의심되는 곳을 찾는 데 도움이 되지만, 실제로 무엇을 말했는지 확정하는 근거는 아닙니다. 승인된 대본을 보존하고 불일치는 다시 들어 확인해야 합니다. 단어별 자막에는 검증한 타임스탬프를 가진 별도의 전사 또는 정렬 단계가 필요합니다. 문장별 스케줄만으로 단어 위치를 알 수는 없습니다.

7. 수정 이력과 비용을 구분해 남기기

현지화 문장 하나가 바뀌어도 새 파일을 측정한 뒤 해당 언어의 전체 타임라인을 다시 만듭니다. WAV만 덮어쓰고 오래된 해시나 시간표를 유지하지 마세요. 대본 버전, 모델 설정, 원본 촬영일, 최종 파일 해시를 작은 게시 기록으로 남기면 됩니다.

세 영상의 길이는 세 건의 청구서를 의미하지 않습니다. 영어 음성은 재사용했고, 일본어와 한국어에 새 생성 요청 10개를 사용했습니다. 최종 정산 내역과 대조하지 않았으므로 총비용이나 절감률을 제시하지 않습니다. 대량 현지화를 계획하기 전에 현재 모델의 과금 단위와 요청 기록부터 확인해야 합니다.

실패하면 게이트웨이 인증, 제공업체 할당량, 디코딩, 타임라인 오류를 구분하세요. 제공업체 할당량 응답을 곧바로 Ofox 지갑 잔액 부족으로 판단해서는 안 됩니다. 음성 생성은 성공했지만 원본이 30초가 아니거나 PCM 형식이 달라 합성이 실패했다면, 같은 소리를 계속 유료 생성하기보다 로컬 입력 조건을 고쳐야 합니다.

발음하기 어려운 용어가 있는 문장 하나로 시작해 실제 결과를 검증한 다음 전체 프로젝트로 확장하세요. 재사용할 결과물은 승인된 대본, 저장된 음성, 언어별 시간표입니다. 하나의 타임라인이 측정 없이 모든 언어에 맞는다는 약속은 아닙니다.

자주 묻는 질문

영어 타임라인을 일본어와 한국어에도 그대로 쓸 수 있나요?
초기 참고로는 쓸 수 있지만 실제 음성 길이를 측정해야 합니다. 이 예제의 첫 문장은 영어 3.56초, 일본어 5.32초, 한국어 4.68초여서 첫 장면의 연장 길이가 달랐습니다.
API 비용 없이 영상을 재현할 수 있나요?
네. 저장된 음성과 원본 영상이 포함되어 있어 FFmpeg 합성은 오프라인으로 실행됩니다. 새 음성을 생성하려면 모델 접근 권한과 사용 가능한 잔액이 있는 키가 필요합니다.
세 영상 모두 완전히 현지화된 결과인가요?
내레이션을 현지화한 영상입니다. 화면은 과거의 영어 UI를 그대로 사용하며, UI와 제목 카드 번역, 단어별 자막, 립싱크는 포함하지 않습니다.