Install
openclaw skills install @anshanzhaoqian/video-en2zh-dub把英文视频变成中文配音视频,也支持生成中英双音轨。当用户提出"把这个视频翻译成中文/中文化/视频汉化"、"给视频配中文音/中文解说"、"提取字幕并翻译"、"英文视频转中文"、"给视频加一条中文音轨"等需求时使用。执行四步流水线,whisper 转写英文字幕、大模型翻译为中文字幕、edge-tts 合成中文配音、ffmpeg 音画合并,产出中文配音版 mp4。
openclaw skills install @anshanzhaoqian/video-en2zh-dub把英文原声视频变成中文配音视频:语音识别 → 字幕翻译 → 语音合成 → 音画合并。
前三步和第四步的封装命令都由 scripts/ 下的脚本完成,只有"字幕英译汉"需要你(大模型)亲自做。不要用自己写的临时代码片段去替代这些脚本。
先确认用户要的是"替换"还是"并存",这一句话决定步骤 4 用哪条命令。前三步在任何情况下都完全一样。
不适用:只要一份中文字幕文件却不需要配音(只跑步骤 1+2);源视频本身没有语音。
假设工作目录是 <WD>(源视频所在地),skill 安装目录为 <SKILL>。
| 路径 | 角色 |
|---|---|
<WD>/input.mp4 | 源视频(用户提供) |
<SKILL>/scripts/transcribe.py | 步骤 1:whisper 转写 → 英文字幕 |
<WD>/input.srt | 步骤 1 产物:英文字幕(步骤 2 的输入) |
<WD>/output.srt | 步骤 2 产物:中文字幕(由你翻译生成) |
<SKILL>/scripts/synthesize.py | 步骤 3:edge-tts 配音 → output.mp3 |
<WD>/output.mp3 | 步骤 3 产物:中文配音音轨 |
<WD>/output.mp4 | 最终产物:中文配音视频 |
<SKILL>/scripts/check_env.py | 环境自检(只依赖标准库) |
<SKILL>/references/pitfalls.md | 踩坑笔记,步骤报错时查阅 |
<SKILL>/references/sync-tuning.md | 音画同步优化,用户追求节奏贴合时查阅 |
<WD> 下执行,产物都落在当前目录。两个主脚本都支持 -i/-o 参数,但默认就用 input.mp4 / output.srt / output.mp3,通常不必显式传。check_env.py 报 MISS 但依赖其实装过,说明选错了解释器,换一个再试。不要在每个 Python 里都重装一遍依赖。$PY=xxx 再复用。output.mp3 时长,正常就继续,切勿盲目重跑(一次要几十分钟)。cd "<WD>"
"<PY>" "<SKILL>/scripts/check_env.py"
四项 Python 依赖、audioop、ffmpeg 与 ffprobe 全部 OK 才继续。缺什么它会给出对应的安装命令。
ffprobe 是必需的,不是可选项——pydub 解码 mp3 依赖它,有些 ffmpeg 包只带 ffmpeg.exe。
首次使用需安装依赖,分两步:
# 1. 先装 CPU 版 torch:直接装 whisper 时可能拉到数 GB 的 CUDA 包
"<PY>" -m pip install torch --index-url https://download.pytorch.org/whl/cpu
# 2. 再装其余依赖
"<PY>" -m pip install -U openai-whisper edge-tts pysrt pydub
若自检仍报缺失两项,按它的提示补装(Python 3.13+ 必装第一个):
"<PY>" -m pip install audioop-lts # Python 3.13 起标准库移除了 audioop,pydub 依赖它
"<PY>" -m pip install msvc-runtime # Windows 缺 VC++ 运行库会让 torch/whisper 导入崩溃
首次转写会下载 Whisper 模型(base 约 140MB)到 ~/.cache/whisper。
cd "<WD>"
"<PY>" "<SKILL>/scripts/transcribe.py"
base、CPU 推理。后台运行。input.srt,末行打印 完成:写出 N 条字幕 -> input.srt。-i 视频 -o 字幕 -m small(更准但更慢,长视频或专业内容可用)、-l en、--device cuda(有 N 卡时快一个量级,脚本会 fp16)。input.srt 已存在且用户没说要重做,跳过本步。记录字幕条数与末条结束时间,步骤 2 必须与之完全一致。
读取 input.srt,翻译全部文本行,其余字节原样保留,写出 output.srt(UTF-8 无 BOM,尾随换行)。
{序号}
{开始} --> {结束}
{文本}
N / 1000 × 4.5 个字。把这条当硬约束,长句要精简提炼,宁短勿长[MUSIC]、[Applause])译作 [音乐]、[掌声],不要整条删掉output.srtcd "<WD>"
"<PY>" -c "
import pysrt
a=pysrt.open('input.srt',encoding='utf-8'); b=pysrt.open('output.srt',encoding='utf-8')
print('英文条数:',len(a),' 中文条数:',len(b))
bad=[i+1 for i,(x,y) in enumerate(zip(a,b)) if str(x.start)!=str(y.start) or str(x.end)!=str(y.end)]
print('时间轴不一致:', bad if bad else '无')
empty=[i+1 for i,y in enumerate(b) if not y.text.strip()]
print('空译文:', empty if empty else '无')
"
条数相等、时间轴一致、无空译文,任一项不合格必须修正后才能进步骤 3。
cd "<WD>"
"<PY>" "<SKILL>/scripts/synthesize.py"
zh-CN-XiaoxiaoNeural 合成,按原时间轴落位,导出 output.mp3(192kbps)。--sleep 1.5,166 条约 6 分钟。--rate "+15%"(语速加快,缓解溢出)、--report(输出每条溢出统计)、--sleep 10(被限流时改保守)、--limit 20(先试跑 20 条验证链路)、--keep-temp。核验(无论任务报成功还是 failed 都要做):
ffprobe -v error -show_entries format=duration -of default=nw=1 output.mp3
时长接近「末条字幕结束 + 0.5 秒」即为成功,直接进入步骤 4。残留的 temp_audio/ 交给用户决定是否清理,不要擅自批量删除。
替换原音(丢弃英文原音轨):
cd "<WD>"
ffmpeg -y -i input.mp4 -i output.mp3 -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 output.mp4
-y 不能省:没有它,第二次运行会卡在等待「是否覆盖」的输入上。-c:v copy 不重编码视频,十几秒完成。-map 决定保留哪些流,未选中的轨道会被丢弃。双音轨并存(保留英文原声,另加一条中文轨,播放器中可切换)——务必打语言标记,否则两条轨都叫"音轨 1 / 音轨 2",用户分不清:
ffmpeg -y -i input.mp4 -i output.mp3 \
-map 0:v:0 -map 0:a:0 -map 1:a:0 \
-c:v copy -c:a aac -b:a 128k \
-metadata:s:a:0 language=eng -metadata:s:a:0 title="English" \
-metadata:s:a:1 language=zho -metadata:s:a:1 title="中文配音" \
output_dual.mp4
验轨(应见 1 条 video + 2 条 audio,语言分别为 eng / zho):
ffprobe -v error -show_entries stream=index,codec_type:stream_tags=language,title -of csv=p=0 output_dual.mp4
MP4 容器会把
title映射为name字段,ffprobe 输出里看到name=属正常,播放器读取的正是它。
配音短于视频时补静音(apad 垫到与视频等长,-shortest 在视频结束时收尾,两者必须同时给,否则 apad 会无限填充):
ffmpeg -y -i input.mp4 -i output.mp3 -map 0:v:0 -map 1:a:0 -c:v copy -c:a aac -af apad -shortest output.mp4
保留原声做背景音(中英混音):
ffmpeg -y -i input.mp4 -i output.mp3 \
-filter_complex "[0:a]volume=0.25[a0];[1:a]volume=1[a1];[a0][a1]amix=inputs=2:duration=longest[out]" \
-map 0:v:0 -map "[out]" -c:v copy -c:a aac output.mp4
完成后向用户报告视频时长、中文字幕条数、配音片段数、产物路径,并调用 present_files 展示 output.mp4。
核对 output.mp4 的音视频时长是否接近:
ffprobe -v error -show_entries format=duration -of default=nw=1 output.mp4
差值在 1 秒内属正常。若配音明显短于视频(画面还有内容却已无声),用上面的 apad 变体重做步骤 4。
遇到具体报错先看 references/pitfalls.md。高频问题速查:
| 现象 | 原因 | 处理 |
|---|---|---|
ModuleNotFoundError | 选错 Python 解释器 | 换一个 Python 重跑 check_env.py 确认 |
ModuleNotFoundError: No module named 'audioop' | Python 3.13+ 已将该模块移出标准库 | pip install audioop-lts(pydub 依赖它) |
| torch / whisper 导入时崩溃,报错含 DLL | Windows 缺 VC++ 2022 运行库 | pip install msvc-runtime |
FileNotFoundError: [WinError 2](pydub/whisper 报) | ffmpeg 不在 PATH | 安装 ffmpeg 并加入 PATH |
| pydub 解码 mp3 失败,但 ffmpeg 明明能用 | 缺 ffprobe.exe | 补一个 ffprobe 放到 PATH,与 ffmpeg 同目录 |
pip install 卡在下载几百 MB 甚至数 GB | torch 拉到了 CUDA 包 | 改装 CPU 版:pip install torch --index-url https://download.pytorch.org/whl/cpu |
PermissionError 且路径含 sslkey.log | 环境变量 SSLKEYLOGFILE 指向无写入权限路径 | 命令前 unset SSLKEYLOGFILE,或从系统环境变量里删除它 |
pip list 看得到包却 No module named | 同上,SSL 报错伪装成"没装" | 同上;不要靠重装解决 |
步骤 1 后 input.srt 为空 | 视频无音轨或语音过小 | ffmpeg -i input.mp4 确认音频流,或换大模型 |
步骤 3 报找不到 output.srt | 漏了步骤 2 | 先完成翻译并通过自检 |
| 步骤 3 大量「失败,跳过」 | edge-tts 限流/断网 | 加 --sleep 10 重跑,或稍后再试 |
| 步骤 4 卡住不动 | 缺 -y | 中断后加 -y 重跑 |
| 步骤 3 报 failed 但打印了「完成!」 | 清理临时目录被拦截 | 假失败:核验 mp3 时长,正常就继续 |
| 成片后半段没声音 | mp3 短于视频 | 用 apad 变体或混音变体 |
temp_audio/(数百个文件,易触发保护)