Communitygithub.com

renky1025/agent-skills

本地视频配音管线:抽取 16kHz 音频 → ASR 转录 → AI 翻译 → 分段 TTS → 混流 → 硬字幕烧录。时间戳锁定同步。

agent-skills 是什么?

此技能提供一条完整的视频本地化管线,支持将原始视频的语音识别、翻译为目标语言,并通过 TTS 合成配音,最终将配音与硬字幕同步合成到视频文件中。其核心优势在于严格复用 ASR 原始时间戳,确保配音与画面的精确对齐,无需二次对轴。工作流程包括:使用 ffmpeg 抽取音频并进行 16kHz 单声道转换,然后使用 Whisper 或 Qwen3-ASR 进行逐段语音识别并生成 SRT 字幕,再由 AI 逐段翻译成目标语言,接着通过 dub_segments.py 脚本基于原始 SRT 时间戳生成分段 TTS 配音和同步字幕,最后使用 ffmpeg 替换音轨并使用 moviepy 烧录硬字幕。该技能支持多种平台(如 Claude Code、Codex 等),通过 CLI 脚本和参数化设计实现端到端的自动化。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/renky1025/agent-skills/tree/main/video-dubbing

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

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 翻译。手动执行时按以下步骤:

  1. 抽音轨(16kHz 单声道): ffmpeg -y -i input.mp4 -ar 16000 -ac 1 -c:a pcm_s16le audio16k.wav

  2. 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。

  3. 翻译字幕(由 AI 完成):读 SRT,逐段翻译。每个 SRT 段输出一行译文,严格保持顺序。 先数清段数(如 27 段 -> 27 行),存为 translated.txt,继续前核对行数一致。

  4. 生成配音: python3 <skill>/scripts/dub_segments.py audio16k.srt translated.txt dubbing.wav subtitle_synced.srt --lang <目标语言> 脚本会:用首段作音色参考保证音色一致;保留原始时间戳让字幕与画面同步;只对溢出槽位的段做变速(atempo 0.88–1.20);把相邻小于 1s 的间隔桥接起来让听感自然。

  5. 合并配音音轨到视频:

    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)。

  6. 烧录硬字幕: python3 <skill>/scripts/burn_subtitles.py output_temp.mp4 subtitle_synced.srt output_final.mp4 把译文字幕永久渲染进画面。

  7. 清理(可选):删除 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 <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 — 视频转结构化纪要;只需转录/总结时改用它。

相关技能