TTS 음성 내레이션 — 단어 수준 타임라인 생성은(는) 무엇을 하나요?
단어 타임라인이 있어야 캡션이 정확한 단어에 맞춰 강조되고, 장면이 올바른 음절에 맞춰 진행됩니다. 항상 VO(내레이션)를 먼저 생성하고, 실제 타임라인에 맞춰 애니메이션을 적용하세요. 절대 반대로 하지 마세요.
빠른 시작 (무료, API 키 불필요)
pip install edge-tts
python scripts/vo_gen.py --text "Pythagore. Dans un triangle rectangle…" --voice fr-FR-DeniseNeural --rate -4%
출력물 (기본 접두사 vo):
vo.mp3— 오디오 파일vo_words.json—{ words:[{text,fromMs,toMs}], captions:[{startMs,durationMs,text,tokens[]}] }captions는 최대 3단어로 그룹화된 페이지이며, 700ms 이상 간격이 있으면 페이지가 나뉩니다. 각 단어의 시간 윈도우가 포함됩니다.vo.js—window.VO_B64(base64 mp3) +window.VO_DATA(JSON). 캔버스/seek 파이프라인에 바로 사용할 수 있습니다:<script src="vo.js">로드 후decodeAudioData로 재생하고VO_DATA.captions로 캡션을 그립니다.
음성 목록 보기: python scripts/vo_gen.py --list-voices fr (지원 언어: fr, en, ja, es, de, pt, zh, ar 등)
음성 메뉴 (간단 추천)
| 언어 | 차분한 나레이터 | 활기찬 나레이터 |
|---|---|---|
| fr | fr-FR-DeniseNeural | fr-FR-HenriNeural |
| en | en-US-AriaNeural | en-US-GuyNeural |
| ja | ja-JP-NanamiNeural | ja-JP-KeitaNeural |
| es | es-ES-ElviraNeural | es-ES-AlvaroNeural |
| de | de-DE-KatjaNeural | de-DE-ConradNeural |
| pt | pt-BR-FranciscaNeural | pt-BR-AntonioNeural |
| zh | zh-CN-XiaoxiaoNeural | zh-CN-YunjianNeural |
속도 설정: --rate -4% 느리게 / +10% 빠르게. 짧은 문장일수록 단어 경계가 더 깔끔하게 생성됩니다. 문장별로 재생성하면 트랙 전체를 다시 하지 않고 잘못된 한 줄만 수정할 수 있습니다.
주의사항 (경험상 배운 점)
- edge-tts ≥ 7: 단어 경계(boundary)가 기본적으로 꺼져 있습니다 —
boundary="WordBoundary"가 필요합니다 (vo_gen.py는 이미 전달하고 있음). 버그 증상: 오디오는 정상,words가 비어 있음. - 서비스에서 HTTP 403 오류: edge-tts 버전이 현재 토큰 스킴에 너무 오래된 경우입니다 —
pip install -U edge-tts로 업데이트하세요 (시스템 설치가 잠겨 있으면 venv 사용). - 원시 스트림에서 단어 오프셋은 100나노초 단위입니다. 밀리초(ms)로 변환하려면 10⁴로 나누세요.
대안 및 업그레이드
- Kokoro (
pip install kokoro) — 로컬 신경망 TTS, 82M 파라미터, 여러 언어 지원. - Piper — 완전 오프라인, 빠름, 언어별 음성 다운로드.
- ElevenLabs — 유료, 다국어 v2;
with-timestampsAPI가 문자 수준 시간을 반환하여 캡션에 직접 사용 가능. - VOICEVOX (일본어) — 로컬 HTTP API (
localhost:50021), 음소별 타임라인 (일본어 립플랩 애니메이션에 좋음). - 기존 오디오 → faster-whisper로 단어 타임라인 생성:
pip install faster-whisper python - <<'EOF' from faster_whisper import WhisperModel; import json m = WhisperModel("small"); segs, _ = m.transcribe("track.mp3", word_timestamps=True) json.dump([w._asdict() for s in segs for w in s.words], open("words.json","w")) EOF
영상 믹싱 (빠른 참고)
음성, 배경음악, 효과음은 별도 트랙으로 유지한 후: 배경음악은 VO 아래 −18…−22 LUFS, ffmpeg sidechaincompress(트리거: VO)로 덕킹, 최종 loudnorm=I=-14:TP=-1.5:LRA=11 적용. 효과적인 캡션 스타일: 굵은 대문자, 1~3단어씩, 활성 단어는 강조 색상에 ~20% 스케일 팝, 검정 필 또는 뒤에 테두리로 대비 확보, 플랫폼 UI 영역 밖에 배치.