video-dubbing: 影片翻譯配音與字幕同步
目的
把一段影片整體在地化為另一種語言:辨識原始語音、翻譯、用 TTS 生成目標語言配音,在保持原始時間戳的前提下合成音軌並將譯文硬字幕燒進畫面。產出是可直接發布的單檔影片,配音與字幕天然同步,不需要二次對軸。
使用時機
- 用戶要求把影片翻譯成另一種語言,並要配音(不只是字幕)。
- 需要給影片加目標語言配音 + 同步字幕(雙語或純譯文)。
- 觸發詞:影片翻譯、影片配音、翻譯字幕、生成外語配音、雙語字幕、dub a video、translate a video、foreign-language voiceover。
- 任何 ASR -> 翻譯 -> TTS -> 影片合成的工作流程。
不應使用時機
- 只需轉錄、不需要翻譯或配音 -> 交給
video-minutes或直接 whisper。 - 只需把文字合成為音訊、不涉及影片 -> 交給
mlx-tts。 - 需要保留原背景音樂/音效並做專業混音(人聲分離)-> 本技能預設不做 Demucs,需另行處理。
- 影片無音軌或音質極差到無法辨識。
工作流程
端到端推薦直接用編排腳本 <skill>/scripts/dub.py(見 ## 腳本),它會依序執行下面各步並在翻譯處暫停等待 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— 影片轉結構化會議記錄;只需轉錄/總結時改用此技能。