video-dubbing: ビデオ翻訳・吹き替えと字幕同期
目的
ビデオ全体を別の言語にローカライズします:元の音声を認識、翻訳、TTSでターゲット言語の吹き替えを生成し、元のタイムスタンプを維持したまま音声トラックを合成し、翻訳されたハードサブタイトルをビデオに焼き付けます。出力はすぐに公開可能な単一ファイルのビデオで、吹き替えと字幕は自然に同期しており、手動で調整する必要はありません。
使用する場面
- ユーザーがビデオを別の言語に翻訳し、吹き替えも必要とする場合(字幕だけではありません)。
- ビデオにターゲット言語の吹き替え+同期字幕(バイリンガルまたは翻訳のみ)を追加する必要がある場合。
- トリガーワード:ビデオ翻訳、ビデオ吹き替え、翻訳字幕、外国語吹き替え生成、バイリンガル字幕、dub a video、translate a video、foreign-language voiceover。
- ASR -> 翻訳 -> TTS -> ビデオ合成のワークフロー全般。
使用すべきでない場面
- 文字起こしのみで翻訳や吹き替えが不要な場合 ->
video-minutesまたは直接 whisper を使用。 - テキストを音声に合成するだけでビデオが関係ない場合 ->
mlx-ttsを使用。 - 元のBGM/効果音を保持し、プロフェッショナルなミキシング(音声分離)が必要な場合 -> このスキルはデフォルトで Demucs を行わないため、別途処理が必要。
- ビデオに音声トラックがない、または音質が極端に悪く認識できない場合。
ワークフロー
エンドツーエンドでの実行は、オーケストレーションスクリプト <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 セグメントに対して 1 行の翻訳文を出力し、順序を厳密に維持します。まずセグメント数を数え(例: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.20 倍とします。グローバルな atempo は禁止です。
- デフォルトでは BGM/音声分離は行いません。ユーザーが要求した場合は、追加の処理が必要であることを明示的に説明する必要があります。
検証
納品前に以下の項目を確認します:
-
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 <path>] [--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— ビデオから構造化された議事録を生成します。文字起こし/要約のみが必要な場合はこちらを使用してください。