원본 비디오의 영어 보컬을 중국어 더빙으로 교체하는 작업으로, 동일 시간 축을 유지합니다. 즉, 비디오의 시간 조정이 전혀 없으며 모든 프레임이 원래 타임스탬프를 그대로 유지하고, 더빙된 릴리스는 원본 비디오와 정확히 동일한 길이를 가집니다. 각 큐의 합성 오디오는 해당 큐의 원래 윈도우(큐 시작 → 다음 큐 시작)에 맞춰지며, 각 큐마다 다른 atempo가 적용됩니다. 더 빠르거나 느린 합성 모두 해당 윈도우 내에 배치됩니다. 결과는 두 번째 릴리스로, 동일한 화면 속도에 중국어 오디오와 이중 언어(중국어+영어) 자막이 하드코딩되어 제공됩니다.
이 스킬은 CLI가 처리할 수 없는 두 가지 창의적인 부분, 즉 더빙을 위한 번역(자막 조각이 아닌 문자 예산에 맞춰 완전한 문장 작성)과 품질 게이트 실행(길이 게이트, 콜드 리뷰, 귀 게이트, 번-인 후 리뷰)을 담당합니다. 결정론적 실행(Demucs, IndexTTS2, 어셈블리, 리타임, ffmpeg)은 cook CLI의 cook dub 하위 명령어로 처리됩니다. 모든 스테이지 스크립트는 cook 패키지 내(stages/dub/)에 있으며, 아래의 모든 호출은 cook 명령어입니다. pip install -U video-cook 한 번으로 모든 것을 업그레이드할 수 있습니다.
이 스킬을 사용해야 하는 경우
다음이 이미 준비된 비디오가 있는 경우:
- 원본 비디오 파일(
<output-root>/raw/<name>.raw.mp4) — 영어 보컬이 포함된 원본 파일. video-subtitle에서 생성된 이중 언어 자막 실행 — 특히transcript/<name>.en.full.srt(whisperX 조각에서 병합된 완전한 문장의 영어 대본)와transcript/translations.txt.
중국어 더빙 릴리스를 원합니다. 아직 이러한 파일이 없다면 먼저 video-download를 실행한 다음 video-subtitle을 실행하세요. 이 스킬은 해당 출력을 읽습니다.
생성되는 결과물
세 가지 결과물이 제공됩니다: cooked/<name>.dubbed.mp4(원본 비디오 변경 없음, 중국어 더빙, 하드코딩된 이중 언어 자막 — 원본과 동일한 길이), cloud-srt/zh.dub.srt + en.dub.srt(업로드 자막). 나머지는 모두 dubbed/ 디렉토리의 작업 파일입니다. 아래 주석이 달린 트리는 모든 파일을 설명합니다.
6단계의 검사를 통과해야 실행이 완료된 것입니다.
디렉토리 구조
이 스킬은 dubbed/(작업 디렉토리)를 추가하고 최종 결과물을 cooked/ 및 cloud-srt/에 씁니다:
<output-root>/
├── raw/ ← video-download에서 생성 (이 스킬이 읽음)
│ └── <name>.raw.mp4
├── transcript/ ← video-subtitle에서 생성 (이 스킬이 읽고 추가)
│ ├── <name>.en.full.srt ← 완전한 문장의 영어 (더빙 대본 소스)
│ ├── translations_dub.txt ← 이 스킬이 작성: 큐당 한 줄의 중국어
│ └── <name>.zh.dub.srt ← 이 스킬이 작성
├── cooked/ ← 최종 비디오 저장 위치
│ ├── <name>.cooked.bar.mp4 ← video-subtitle에서 생성 (변경 없음)
│ └── <name>.dubbed.mp4 ← 이 스킬의 결과물
├── cloud-srt/ ← 업로드 자막 저장 위치
│ ├── zh.srt / en.srt ← video-subtitle에서 생성 (변경 없음)
│ └── zh.dub.srt / en.dub.srt ← 이 스킬의 업로드 자막
└── dubbed/ ← 이 스킬의 작업 디렉토리
├── _reference/
│ └── ref.wav
└── _full/
├── _segments/ ← 큐별 IndexTTS2 캐시
├── dub.wav ← 원래 클록의 더빙
├── dubbing.srt ← 작업 파일 (중국어, 단축 전)
├── dubbing.short.srt ← 작업 파일 (중국어, 단축 출력)
├── dubbing.merged.srt ← 작업 파일 (중국어, 단축 후; cloud-srt로 복사)
├── dubbing.en.srt ← 작업 파일 (완전한 문장 영어)
├── dubbing.en.short.srt / dubbing.en.merged.srt ← 단축 및 병합-단축 출력
├── dubbing.bilingual.srt ← 작업 파일 (이중 언어 통합; 번인 대상)
├── dubbing.cooked.ass ← 작업 파일 (ASS 출력, burn.ass로 복사)
└── burn.ass ← 실제로 번인되는 ASS
규칙: dubbed/는 작업 디렉토리이고, cooked/<name>.dubbed.mp4 및 cloud-srt/{zh,en}.dub.srt가 결과물입니다. raw/, transcript/<name>.zh.srt, cooked/<name>.cooked.mp4, cloud-srt/{zh,en}.srt는 건드리지 마십시오. 이들은 video-subtitle에 속합니다. 이 스킬이 중간에 실패하더라도 이중 언어 요리된 결과물은 그대로 유지됩니다.
파이프라인
창의적인 작업 후 두 단계가 있습니다: 합성(synth) 후 어셈블(assemble), cook을 통해 실행:
cook dub synth <root> <name> --python <indextts-venv>/Scripts/python.exe
cook dub assemble <root> <name> --python <indextts-venv>/Scripts/python.exe [--keep-subs]
# 또는 둘 다:
cook dub full <root> <name> --python <indextts-venv>/Scripts/python.exe
아래 단계에서는 각 단계가 내부적으로 수행하는 작업을 설명합니다(출력을 확인하고 실패를 진단할 수 있도록). cook dub <stage> 명령어는 실행 방법입니다.
0단계 — 환경 확인
두 개의 Python 환경이 사용되며, 이를 혼동하는 것이 이 단계에서 방지하려는 주요 실패 모드입니다:
- cook의 환경 (시스템 Python 또는
~/.venvs/video-tools/) —cookCLI가 위치한 곳으로, 자막 파이프라인을 위한 whisperX/yt-dlp/torch가 포함되어 있습니다. - IndexTTS2의 환경 (
~/Git/index-tts/.venv) — 별도의 venv로indextts,torch,demucs,whisperx를 보유합니다(더빙 파이프라인은 업스트림의 lockfile 위에 마지막 두 개를 추가합니다). 이러한 종속성은 무겁고 의도적으로 격리되어 있습니다. cook의 환경에 설치하려고 시도하지 마십시오.
cook은 --python을 통해 각 더빙 단계를 IndexTTS2 venv의 하위 프로세스로 실행하므로 from indextts import ...가 해당 환경에서 해결됩니다. 이 스킬의 모든 cook dub 명령어는 --python <indextts-venv>/Scripts/python.exe를 사용합니다. venv 경로를 한 번 확인하고(기본값 ~/Git/index-tts/.venv) 전체 실행 동안 재사용하십시오.
0a. 두 환경에 모두 접근 가능한지 확인:
<cook-venv>/Scripts/cook doctor # whisperX/yt-dlp/ffmpeg
<indextts-venv>/Scripts/python -c "from indextts.infer_v2_5 import IndexTTS2; import demucs, whisperx; print('ok')" # indextts (v2.5) + demucs + whisperx
0b. 단일 스레드 제약 조건. IndexTTS2는 단일 스레드로 실행되어야 합니다(OMP_NUM_THREADS=1). 그렇지 않으면 품질이 낮은 오디오가 생성됩니다. cook은 torch를 가져오기 전에 내부적으로 이를 설정하므로 직접 내보낼 필요가 없습니다.
cook의 doctor가 whisperX/yt-dlp/ffmpeg가 설치되어 있다고 보고하고, IndexTTS2 venv가 indextts(v2.5) + demucs + whisperx를 가져올 수 있으며, <indextts-venv>/Scripts/python.exe의 절대 경로를 알고 --python으로 전달할 수 있으면 완료됩니다.
1단계 — 원본 비디오에서 보컬 분리
원본 오디오는 하나의 혼합 트랙(보컬 + BGM + SFX)입니다. Demucs가 이를 분리하여 깨끗한 참조를 추출하고 나중에 BGM을 확인할 수 있도록 합니다.
cook dub separate <output-root> <name> [--model htdemucs] --python <indextts-venv>/Scripts/python.exe
Demucs는 IndexTTS2 venv에 있으므로 --python이 해당 위치를 가리킵니다. htdemucs(단일 모델, ~3GB RAM)를 사용하고 htdemucs_ft(4개 모델 번들, ~20GB RAM — 32GB 머신에서 OOM 발생)는 사용하지 마십시오. 품질은 약간 낮지만 참조 추출에는 충분합니다.
포그라운드 모드(기본값)에서는 cook이 분리된 스템을 자동으로 dubbed/vocals.wav + dubbed/no_vocals.wav로 이동합니다. --detach 모드에서는 완료 마커가 나타난 후 직접 이동해야 합니다.
dubbed/vocals.wav와 dubbed/no_vocals.wav가 모두 존재하고 지속 시간이 원본과 ±0.5초 이내로 일치하면 완료됩니다.
2단계 — 참조 클립 추출
IndexTTS2는 원래 화자의 14-30초 길이의 깨끗한 클립이 필요합니다. 최대 처음 15초만 읽으므로 전체 용량의 윈도우가 짧은 윈도우보다 좋습니다. IndexTTS2는 음색뿐만 아니라 운율도 복제합니다. 윈도우의 전달 속도가 전체 더빙의 전달 속도가 됩니다. 기본 선택기는 가장 긴 연속 음성을 선택하는데, 이는 가장 느리고 가장 신중한 구절을 선택하는 경향이 있어 종종 잘못됩니다. 스캐너를 선호합니다:
cook dub scan-reference <output-root> <name> \
[--full-band] [--python <indextts-venv>/Scripts/python.exe]
음절 비율(밀도 및 일시 정지 필터링 기준)로 고정 15초 윈도우의 순위를 매기고 상위 3개 후보를 잘라냅니다(--full-band를 사용하면 전체 대역 48k 복사본도 생성). 밀도만이 전부는 아닙니다. IndexTTS2는 윈도우의 운율도 복제하므로 후보를 생동감 기준으로도 평가해야 합니다. 윈도우당 pyin F0 표준 편차 및 반음 범위(평평한 윈도우는 평평한 더빙을 생성하며, librosa.pyin을 사용하고 무음에서 발성을 보고하는 detect_pitch_frequency는 사용하지 마십시오). 재사용하기 전에 기존 참조 파일을 인증하십시오: 재처리된 파생 파일은 화자 임베딩 및 피치 통계를 유지하지만 파형 상관 관계는 잃으므로 상관 관계가 0에 가깝다고 해서 "다른 화자"를 의미하지는 않습니다. 앵커 클립(cook dub scan-reference --score <file> --anchor <anchor.wav>)과 점수를 비교하고(동일 화자의 실제 오디오는 0.94 부근, 합성된 경우 0.66-0.76이 정상 범위) pyin 통계를 비교하십시오. 어느 쪽이든: 사용자의 귀가 항상 참조를 선택합니다 — 후보당 한 번씩 파일럿 문장을 합성하고(3a단계), 각 테이크를 소형 모델 ASR 왕복으로 사전 심사(누락된 단어는 왜곡을 나타내고, 번체 중국어 출력은 윈도우가 테이크에 번인된 악센트를 나타냄), cook dub scan-reference --score로 점수를 매긴 다음, 음량이 일치된 wav 파일을 사용자에게 전달하십시오.
dubbed/_reference/ref.wav가 존재하고, 14-30초이며, 0.3초 이상의 무음 간격이 없으면(ffmpeg -af silencedetect) 완료됩니다.
3단계 — 더빙을 위한 번역 (에이전트가 수행)
여기서 더빙이 자막과 달라집니다. translations.txt(자막 번역)를 사용하지 마십시오. 이는 문장을 분할하는 whisperX의 조각 컷을 따릅니다. 더빙은 완전한 문장이 필요하므로 중국어가 말할 때 자연스럽게 흐릅니다.
<output-root>/transcript/<name>.en.full.srt(완전한 문장의 영어 대본)를 읽으십시오. 각 큐를 직접 번역하여 transcript/translations_dub.txt에 작성하십시오. 영어 큐당 한 줄의 중국어, 줄 N = 큐 N.
문자 예산 규칙 — 더빙 번역의 핵심. 각 큐의 예산은 윈도우 초 × 정상 말하기 속도이며, 작성 전에 고정됩니다. 윈도우는 큐 시작부터 다음 큐 시작까지(윈도우 + 다음 일시 정지)이고, 속도는 가정하지 않고 측정됩니다. cook dub measure-rate를 사용하여 사용자가 선택한 파일럿에서 측정합니다(절차: 3a단계). 가정된 속도는 모든 게이트를 통과하고 몇 초의 데드 에어로 더빙됩니다. 5.0 chars/s로 가정된 45분 강의가 실제 6.93에 대해 예산이 책정되어 83개의 큐에서 2.5초 이상의 침묵이 발생하고 82개 큐 재합성 비용이 발생했습니다. 예산에 맞게 작성하십시오. 약간 초과해도 괜찮지만, 현저히 부족하면 안 됩니다. 짧은 테이크는 자연스러운 속도를 유지하고 숨 쉴 틈을 남기므로, 예산 미달 텍스트는 데드 에어를 의미하고 예산 초과 텍스트는 청취 가능한 압축을 의미합니다. 참조 또는 지속 시간 요소가 변경되면 재보정하십시오. 폐기된 참조에 대해 보정된 예산은 모든 게이트를 통과하고 여전히 데드 에어로 더빙됩니다. 화자당 길이 대역에 걸쳐 계층화된 프로브(5-10개의 일반적인 큐)를 합성하고 측정된 속도로 윈도우에 대해 대본을 다시 확인하십시오. 절차는 **REFERENCE.md → "속도 재보정"**에 있습니다. 예산을 정당하게 채우는 방법(그리고 "채우기"가 허용되지 않는 사항): REFERENCE.md → "문자 예산 채우기".
번역 원칙 (예산 외):
- 완전한 생각을 번역하고, 조각을 번역하지 마십시오. 영어는 이미 완전한 문장입니다. 중국어 큐는 하나의 완전한 생각입니다.
- 중국어 개발자가 사용하는 곳에서는 기술 용어를 영어로 유지하십시오. spec, plan, prototype, agent, token, skill, session, branch, route 등. REFERENCE.md → "용어 유지 목록" 참조.
- 화면에 표시되는 모든 것은 영어로 유지하십시오. UI 레이블, 코드, URL, 파일 이름. **REFERENCE.md → "용어 유지 목록"**의 예시.
- 표준 중국어 이름이 있는 개념은 화면에 표시되지 않을 때 번역하십시오. 실제 예는 용어 유지 목록에 있습니다.
- 줄 수는 큐 수와 같아야 합니다. 개수를 변경하는 공인된 방법은 두 파일을 함께 다시 작성하는 3a단계의
build_merge.py입니다.
그런 다음 사전 어셈블리 SRT를 생성합니다(타임스탬프는 en.full.srt에서 상속됨):
cook dub make-srt <output-root> <name>
자체 검토 — 기계적 게이트 전 두 번의 패스: 각 줄을 머리 속에서 말하는 문장으로 소리 내어 읽어보십시오(사람이 말할 법한 소리인가요?). 그런 다음 아래 용어 목록을 모든 줄에 대해 스캔하십시오(화면에 표시되는 것은 영어로 유지, 표준 개념은 중국어로). 이는 자신의 작업을 확인하는 것입니다. 아래 하위 에이전트 검토는 콜드 리드입니다.
길이 게이트 — 기계적 (순수 산술, 1초 소요):
cook dub gate <output-root> <name> --rate <measured chars/s>
각 줄을 해당 큐 윈도우에 대해 세 가지 방식으로 교차 확인합니다: 짧은 줄(≤8 음절 — IndexTTS2의 내레이션 속도 함정, 더 완전하게 다시 쓰거나 3a단계에서 병합하도록 함), 예산 누락(추정 음성이 윈도우를 크게 초과 — 텍스트를 줄여야 함 — 또는 크게 미달 — 윈도우에 데드 에어가 발생하므로 채워야 함), 커버리지 합계(Σ 추정 음성 / Σ 윈도우 — 균일하게 얇은 번역은 각 줄 검사를 통과하지만 여전히 긴 침묵으로 더빙됩니다. 건강한 범위는 90-105%). --rate는 필수입니다(측정된 값, --self-measure는 기존 테이크에서 다시 파생). 종료 코드 1은 문제가 있는 줄과 커버리지 결과를 나열합니다. 다시 작성하고 통과할 때까지 다시 실행하십시오. 예산을 초과하는 줄은 더 짧게 다시 쓰거나 cook dub merge를 사용하여 이웃 줄과 병합하여 수정합니다. atempo 압축에 맡겨서 수정하지 마십시오.
품질 게이트 — 하위 에이전트 검토(필수, 합성 전). 귀 게이트와 이 검토는 수 시간의 합성 전에 있는 유일한 게이트입니다. <name>.en.full.srt 및 translations_dub.txt에 대한 읽기 권한이 있는 하위 에이전트를 생성하고 모든 큐에 대해 다음을 확인하도록 요청하십시오:
- 번역 정확성 — 중국어가 영어를 충실하게 전달합니까? 누락된 절, 추가된 내용(영어에 없는 내용), 오역이 없어야 합니다.
- 고유 명사 철자 — 이름(사람, 제품, 회사)이 소스에서 사용된 것과 정확히 일치해야 합니다. "Claude"는 "克劳德"가 아니고, "IndexTTS"는 "索引TTS"가 아닙니다. 표준 중국어 이름이 실제로 존재하지 않는 한 그렇습니다.
- TTS 가독성 — IndexTTS2가 이것을 자연스럽게 발음할 수 있습니까? 어색한 문자 시퀀스, 고립된 푸
…
(번역을 위해 잘림)