video-dubbing: 비디오 번역, 더빙 및 자막 동기화
목적
전체 비디오를 다른 언어로 로컬라이즈합니다: 원본 음성을 인식하고, 번역한 후, TTS로 대상 언어 더빙을 생성하여 원본 타임스탬프를 유지한 채 오디오 트랙을 합성하고 번역된 자막을 영상에 하드번인합니다. 최종 결과물은 바로 게시 가능한 단일 파일이며, 더빙과 자막이 자연스럽게 동기화되어 있어 추가적인 시간 조정이 필요하지 않습니다.
사용 시기
- 사용자가 비디오를 다른 언어로 번역하고 더빙(자막뿐만 아니라)을 요청하는 경우.
- 대상 언어의 더빙 + 동기화된 자막(이중 언어 또는 번역문만)이 필요한 비디오.
- 트리거 단어: 비디오 번역, 비디오 더빙, 번역 자막, 외국어 더빙 생성, 이중 언어 자막, dub a video, translate a video, foreign-language voiceover.
- 모든 ASR -> 번역 -> TTS -> 비디오 합성 워크플로우.
사용하지 말아야 할 경우
- 단순히 전사(transcribe)만 필요하고 번역이나 더빙이 필요하지 않은 경우 ->
video-minutes또는 직접 whisper를 사용하세요. - 텍스트를 오디오로만 합성하고 비디오가 필요하지 않은 경우 ->
mlx-tts를 사용하세요. - 원본 배경 음악/효과음을 유지하고 전문적인 믹싱(보컬 분리)이 필요한 경우 -> 이 스킬은 기본적으로 Demucs를 수행하지 않으므로 별도로 처리해야 합니다.
- 비디오에 오디오 트랙이 없거나 오디오 품질이 너무 낮아 인식이 불가능한 경우.
워크플로우
엔드 투 엔드(end-to-end) 방식으로는 <skill>/scripts/dub.py 오케스트레이션 스크립트를 사용하는 것을 권장합니다(## Scripts 참조). 이 스크립트는 아래 각 단계를 순차적으로 실행하며 번역 단계에서 AI 번역을 기다리기 위해 일시 중지됩니다. 수동으로 실행할 때는 다음 단계를 따르세요:
-
오디오 트랙 추출(16kHz 모노) :
ffmpeg -y -i input.mp4 -ar 16000 -ac 1 -c:a pcm_s16le audio16k.wav -
ASR 전사 (세그먼트별 정확한 타임스탬프 필요):
whisper audio16k.wav --model large-v3-turbo --language <소스 언어> --output_format srt --output_dir .audio16k.srt파일이 생성되며, 타임스탬프는 원본 비디오와 자연스럽게 정렬됩니다. 더 나은 중국어 인식을 위해 Qwen3-ASR(pip install qwen-asr)을 설치하고<skill>/scripts/qwen3_asr.py를 사용할 수 있습니다. -
자막 번역(AI가 수행) : SRT 파일을 읽고, 각 세그먼트를 번역합니다. 각 SRT 세그먼트에 대해 한 줄의 번역문을 출력하며, 순서를 엄격히 유지합니다. 먼저 세그먼트 수를 확인한 후(예: 27개 세그먼트 -> 27줄),
translated.txt파일로 저장하고 계속 진행하기 전에 줄 수가 일치하는지 확인합니다. -
더빙 생성:
python3 <skill>/scripts/dub_segments.py audio16k.srt translated.txt dubbing.wav subtitle_synced.srt --lang <대상 언어>스크립트는: 첫 번째 세그먼트를 음색 참조로 사용하여 음색 일관성을 보장합니다; 원본 타임스탬프를 유지하여 자막이 영상과 동기화되도록 합니다; 오버플로우된 슬롯의 세그먼트에만 속도 변경(atempo 0.88–1.20)을 적용합니다; 1초 미만의 인접 간격을 연결하여 청취감을 자연스럽게 만듭니다. -
더빙 오디오 트랙을 비디오에 병합:
ffmpeg -y -i input.mp4 -i dubbing.wav \ -map 0:v:0 -map 1:a:0 \ -c:v copy -c:a aac -b:a 192k -shortest output_temp.mp4그런 다음 오디오 트랙이 교체되었는지 확인합니다:
ffprobe -v error -show_entries stream=codec_type -of csv=p=0 output_temp.mp4(결과는video, audio를 표시해야 함). -
하드 자막 번인:
python3 <skill>/scripts/burn_subtitles.py output_temp.mp4 subtitle_synced.srt output_final.mp4번역된 자막을 영상에 영구적으로 렌더링합니다. -
정리(선택 사항) :
audio16k.wav,audio16k.srt,translated.txt,dubbing.wav,subtitle_synced.srt,output_temp.mp4등의 중간 결과물을 삭제합니다.
결정 규칙
- 한 번에 모든 것을 실행하려면 ->
dub.py를 사용하세요; 특정 단계(예: 이미 SRT 파일이 있는 경우)만 다시 실행하려면 ->dub.py --srt existing.srt를 사용하여 단계를 건너뜁니다. - ASR 엔진: 기본값은
--asr whisper(large-v3-turbo); 중국어 인식 품질이 중요하면 ->--asr qwen3. - 하드 자막이 필요하지 않은 경우 ->
dub.py --no-burn(오디오 트랙 병합까지만 수행). - 대상 언어는
--target-lang으로 결정됩니다(기본값zh);dub_segments.py의 TTS 언어는--lang으로 결정됩니다. - 번역은 반드시 AI가 수행해야 하며 SRT 세그먼트와 엄격히 1:1이어야 합니다. 줄 수가 일치하지 않으면 스크립트가 오류와 함께 종료되며, 이를 무시해서는 안 됩니다.
- 자막이 나타나지 않거나 중국어가 네모 상자로 표시되는 경우 ->
burn_subtitles.py(moviepy 렌더링, 자동으로 중국어 글꼴 찾음)를 사용하고, ffmpeg의subtitles=(libass가 없으면 자동으로 실패)에 의존하지 마십시오. - 더빙 길이가 슬롯을 초과하는 경우 -> 스크립트의 분할 atempo에 의존하고 전체 오디오 트랙에 대해 전역 속도 변경을 수행하지 마십시오.
제약 조건
- 타임스탬프는 반드시 ASR 원본 결과를 재사용해야 하며, 더빙에 대해 ASR을 다시 수행하여 시간을 얻지 마십시오.
- 번역문 줄 수는 반드시 SRT 세그먼트 수와 같아야 합니다(1:1). 그렇지 않으면 중단합니다.
- 오디오 트랙 병합은 반드시 명시적으로
-map 0:v:0 -map 1:a:0을 사용해야 하며, 그렇지 않으면 원본 오디오 트랙이 유지됩니다. - ASR은 반드시
large-v3-turbo(또는turbo)를 사용해야 하며,base/tiny로 다운그레이드하지 마십시오. - 속도 변경은 세그먼트 수준에서만 수행되며, 범위는 0.88–1.20x입니다. 전역 atempo는 금지됩니다.
- 기본적으로 배경 음악/보컬 분리는 수행되지 않습니다. 사용자가 요청할 때는 별도 처리가 필요함을 명시적으로 알려야 합니다.
검증
전달하기 전에 다음 항목을 확인하세요:
-
translated.txt의 줄 수가 SRT 세그먼트 수와 완전히 일치합니다. -
dubbing.wav와subtitle_synced.srt가 모두 생성되었습니다. -
ffprobe가 최종 비디오에 video와 audio 스트림이 모두 포함되어 있으며, 오디오가 실제로 교체되었음을 표시합니다. - 자막이 영상에 하드번인되었으며(외부 소프트 자막 아님), 중국어에 네모 상자가 없습니다.
- 몇몇 임의 지점에서 더빙과 영상의 타임스탬프 정렬을 샘플링하여 확인했습니다.
- 사용자가 제공한 원본 파일이 삭제되지 않았습니다.
출력
- 결과물: 대상 언어 더빙과 하드 자막이 포함된 로컬라이즈된 비디오 파일(기본값
output_final.mp4,dub.py사용 시<비디오명>_<대상 언어>.mp4).subtitle_synced.srt는 보존할 수 있습니다. - 완료 조건: 오디오 트랙이 교체되고, 자막이 번인되었으며, 샘플링 지점에서 오디오와 영상이 동기화되고, ffprobe 검증을 통과했습니다.
- 증거: 최종 파일 경로; SRT 세그먼트 수와 번역문 줄 수; ffprobe의 스트림 목록; 샘플링된 동기화 시간 지점.
참고 자료
필요할 때만 로드하고 미리 모두 읽지는 마십시오:
references/pipeline-design.md— 파이프라인 동작(타임스탬프 유지 이유, 분할 속도 변경, 기본 보컬 분리 미수행, 산출물 및 종속성 목록)을 설명하거나 조정해야 할 때 읽습니다.references/troubleshooting.md— 실제 오류, 오디오-비디오 동기화 불일치, 자막 미표시 또는 중국어 네모 상자 문제가 발생할 때 읽습니다.
스크립트
<skill>/scripts/dub.py— 엔드 투 엔드 오케스트레이션. 사용법:python3 <skill>/scripts/dub.py input.mp4 --source-lang en --target-lang zh [--asr whisper|qwen3] [--srt existing.srt] [-o out.mp4] [--font-size 28] [--no-burn] [--keep-temp]. 번역 단계에 도달하면to_translate.txt파일을 생성하고 AI가translated.txt로 번역하도록 요청한 다음 계속 실행됩니다. 최종 비디오 경로와 자막 경로를 반환합니다.<skill>/scripts/dub_segments.py— 분할 TTS 더빙 + 타임스탬프 정렬. 사용법:python3 <skill>/scripts/dub_segments.py original.srt translated.txt out_dub.wav out_synced.srt [--lang zh] [--min-atempo 0.88] [--max-atempo 1.20] [--gap-bridge 1.0] [--keep-temp]. 정렬된dubbing.wav와subtitle_synced.srt를 반환합니다. 번역문 줄 수가 일치하지 않으면 종료 코드 1로 중단됩니다.<skill>/scripts/burn_subtitles.py— moviepy를 사용하여 하드 자막 번인. 사용법:python3 <skill>/scripts/burn_subtitles.py input.mp4 subtitles.srt output.mp4 [--font <경로>] [--font-size 28]. 자막이 번인된 비디오를 반환합니다.--font가 생략되면 자동으로 중국어 글꼴을 감지합니다.<skill>/scripts/qwen3_asr.py— whisper 호환 Qwen3-ASR CLI, 중국어 인식 성능 우수. 사용법:python3 <skill>/scripts/qwen3_asr.py audio.wav [--model 0.6B|1.7B] [--language zh] [-f srt|vtt|txt|json|tsv|all] [-o 출력 디렉토리] [--device cuda:0|mps|cpu] [--dtype float16|bfloat16|float32]. 지정된 형식의 자막/텍스트 파일을 반환합니다. 모델 별칭:turbo/tiny/base/small -> Qwen3-ASR-0.6B,medium/large -> Qwen3-ASR-1.7B.
문제 해결
- 더빙이 교체되지 않음 / 원본 음성 그대로임 -> ffmpeg 병합 시
-map 0:v:0 -map 1:a:0이 누락되었습니다. - 자막이 나타나지 않거나 중국어가 네모 상자로 표시됨 ->
burn_subtitles.py를 사용하고--font로 중국어 글꼴을 지정하십시오. - 번역문 줄 수가 SRT 세그먼트 수와 일치하지 않음 -> 스크립트가 오류와 함께 종료되므로 먼저 1:1로 맞추십시오.
- 전체 오류 목록은
references/troubleshooting.md를 참조하십시오.
관련 스킬
mlx-tts— 하위mlx_audio.tts.generate를 제공하며, 이 스킬의 더빙 구성 요소가 이에 의존합니다.video-minutes— 비디오를 구조화된 요약으로 변환합니다. 전사/요약만 필요한 경우 이 스킬을 대신 사용하십시오.