YouTube 视频翻译中文:基于 Whisper + FFmpeg 的自动化流水线实战
一、背景
YouTube 视频翻译中文,本质上是将外语视频通过语音识别(ASR)、文本翻译(NMT)、语音合成(TTS)三个环节处理后,重新合成为中文版本。每一个环节都有成熟的开源工具链支持,按正确的流程串联起来,就能搭建一条可复用的自动化流水线。
本文以一段 10 分钟的英文教程视频为例,用 Python 脚本和命令行工具完整走通四个阶段:音频提取 → 语音转文字 → 字幕翻译 → 配音合成。文末会讨论几个实践中容易踩坑的技术细节。
二、整体流程
一条完整的视频翻译流水线由以下四个模块串联:
原始视频.mp4
│
▼
[1] 音频分离 (FFmpeg) ──→ audio.wav
│
▼
[2] 语音识别 (Whisper) ──→ original.srt(原文时间轴字幕)
│
▼
[3] 文本翻译 (DeepL / GPT) ──→ chinese.srt(中文时间轴字幕)
│
▼
[4] 语音合成 (Edge-TTS / ElevenLabs) ──→ dub.mp3
│
▼
[5] 视频合成 (FFmpeg) ──→ output_chinese.mp4
每个模块的输出都是下一个模块的输入,中间产物(SRT 字幕、WAV 音频)都可以单独检查和修正,不需要因为某一步出错就从头重跑。
三、Step 1:音频分离
先将视频中的音轨提取为 16kHz 单声道 WAV,这是 Whisper 模型要求的输入格式。
ffmpeg -i input.mp4 -vn -acodec pcm_s16le -ar 16000 -ac 1 audio.wav
参数说明:
-vn:丢弃视频流,只保留音频-acodec pcm_s16le:输出未压缩 PCM,避免二次有损编码-ar 16000 -ac 1:16kHz 采样率 + 单声道,Whisper 内部会重采样,但提前做好可以减少文件体积
如果原视频音轨是多声道的(常见于访谈类内容),建议先 downmix 到单声道再处理,否则 Whisper 的识别准确率会下降。
四、Step 2:语音识别(ASR)
使用 OpenAI Whisper 将音频转为带时间戳的文本。Whisper 是目前开源领域综合表现最好的 ASR 模型,支持 99 种语言,中文识别准确率在 large-v3 模型下可达 95% 以上。
4.1 安装
pip install openai-whisper
Whisper 依赖 FFmpeg,需确保系统已安装(macOS: brew install ffmpeg,Linux: apt install ffmpeg)。
4.2 转写脚本
import whisper
import sys
model = whisper.load_model("large-v3") # 首次运行会下载模型(~3GB)
result = model.transcribe(
"audio.wav",
language="en", # 指定源语言可提升准确率
task="transcribe", # transcribe=原文, translate=直接译成英文
verbose=True
)
# 打印转写结果
for segment in result["segments"]:
start = segment["start"]
end = segment["end"]
text = segment["text"].strip()
print(f"[{start:.2f}s - {end:.2f}s] {text}")
4.3 导出 SRT 字幕
def format_timestamp(seconds):
"""将秒数转为 SRT 时间戳格式 HH:MM:SS,mmm"""
h = int(seconds // 3600)
m = int((seconds % 3600) // 60)
s = int(seconds % 60)
ms = int((seconds % 1) * 1000)
return f"{h:02}:{m:02}:{s:02},{ms:03}"
with open("original.srt", "w", encoding="utf-8") as f:
for i, seg in enumerate(result["segments"], 1):
start = format_timestamp(seg["start"])
end = format_timestamp(seg["end"])
f.write(f"{i}\n{start} --> {end}\n{seg['text'].strip()}\n\n")
print(f"导出完成,共 {len(result['segments'])} 条字幕")
4.4 模型选型
| 模型 | 参数量 | 显存需求 | 英文准确率 | 多语言准确率 | 适用场景 |
|---|---|---|---|---|---|
| tiny | 39M | ~1GB | ~85% | ~70% | 快速测试 |
| base | 74M | ~1GB | ~90% | ~78% | 简单英文内容 |
| small | 244M | ~2GB | ~93% | ~83% | 日常使用 |
| medium | 769M | ~5GB | ~95% | ~88% | 专业内容 |
| large-v3 | 1.55B | ~10GB | ~97% | ~93% | 生产环境 |
如果本地没有 GPU,可以使用 medium 模型跑 CPU(10 分钟音频约 15-20 分钟处理时间),或者使用 Google Colab 的免费 T4 GPU 跑 large-v3。
五、Step 3:字幕翻译
拿到原文 SRT 字幕后,需要翻译成中文。翻译引擎的选择直接影响最终质量——逐句翻译容易丢失上下文,导致同一术语在不同位置被翻译成不同的词。
5.1 解析 SRT 文件
import re
def parse_srt(filepath):
"""解析 SRT 文件,返回字幕列表"""
with open(filepath, "r", encoding="utf-8") as f:
content = f.read()
pattern = re.compile(
r"(\d+)\n(\d{2}:\d{2}:\d{2},\d{3}) --> (\d{2}:\d{2}:\d{2},\d{3})\n(.*?)\n\n",
re.DOTALL
)
subtitles = []
for match in pattern.finditer(content):
subtitles.append({
"index": int(match.group(1)),
"start": match.group(2),
"end": match.group(3),
"text": match.group(4).replace("\n", " ").strip()
})
return subtitles
5.2 使用 DeepL API 翻译
import deepl
import time
translator = deepl.Translator("YOUR_DEEPL_API_KEY")
subtitles = parse_srt("original.srt")
with open("chinese.srt", "w", encoding="utf-8") as f:
for sub in subtitles:
result = translator.translate_text(
sub["text"],
source_lang="EN",
target_lang="ZH"
)
f.write(f"{sub['index']}\n{sub['start']} --> {sub['end']}\n{result.text}\n\n")
time.sleep(0.1) # DeepL 免费 API 限速
print("翻译完成")
5.3 使用 OpenAI GPT-4o 翻译(带上下文)
对于术语较多的技术类视频,用 GPT-4o 配合上下文窗口翻译效果更好。做法是将连续 5-10 条字幕打包成一次请求,让模型看到前后文:
from openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY")
def translate_batch(subtitle_batch):
"""将多条字幕合并为一次翻译请求"""
texts = [s["text"] for s in subtitle_batch]
joined = "\n---\n".join(texts)
response = client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "system",
"content": (
"将以下英文视频字幕翻译为简体中文。要求:"
"1. 保持口语化,适合配音朗读;"
"2. 用分隔符 '---' 保持原文分段;"
"3. 专业术语翻译保持一致;"
"4. 中文每句不超过25字(配音时长限制)"
)
}, {
"role": "user",
"content": joined
}],
temperature=0.3
)
translated = response.choices[0].message.content.split("\n---\n")
return [t.strip() for t in translated]
5.4 在中文字幕中保留时间轴
翻译完成后,中文文本可能比原文长或短。SRT 格式中每条字幕的建议显示时长为 1-6 秒、每行不超过 40 个字符。如果某条中文字幕过长,可以手动拆分成两条;如果过短(如原文为 “OK”),可以和相邻字幕合并:
def adjust_timeline(subtitles, max_chars_per_line=25):
"""对于过长的中文字幕,自动拆分并调整时间轴"""
adjusted = []
for sub in subtitles:
text = sub["text"]
if len(text) <= max_chars_per_line:
adjusted.append(sub)
continue
# 按标点拆分
parts = re.split(r"([,。!?,.!?])", text)
mid = len(text) // 2
# 简化处理:过长句子对半拆分
half_duration = (time_to_seconds(sub["end"]) - time_to_seconds(sub["start"])) / 2
mid_time = time_to_seconds(sub["start"]) + half_duration
adjusted.append({
"index": len(adjusted) + 1,
"start": sub["start"],
"end": format_timestamp(mid_time),
"text": text[:mid]
})
adjusted.append({
"index": len(adjusted) + 1,
"start": format_timestamp(mid_time),
"end": sub["end"],
"text": text[mid:]
})
return adjusted
六、Step 4:语音合成(TTS)
有了中文字幕文本后,将其送入 TTS 引擎生成配音。以下是两种方案。
6.1 方案 A:Edge-TTS(免费,适合原型验证)
微软 Edge 浏览器内置的 TTS 引擎有免费的 Python 接口,中文语音自然度不错:
pip install edge-tts
import asyncio
import edge_tts
async def generate_dub():
# 从 SRT 中提取纯文本
subtitles = parse_srt("chinese.srt")
full_text = " ".join([s["text"] for s in subtitles])
communicate = edge_tts.Communicate(
full_text,
voice="zh-CN-XiaoxiaoNeural" # 女声,还有其他音色可选
)
await communicate.save("dub.mp3")
asyncio.run(generate_dub())
常用中文音色:zh-CN-XiaoxiaoNeural(女声-活泼)、zh-CN-YunxiNeural(男声-沉稳)、zh-CN-XiaoyiNeural(女声-温柔)。Edge-TTS 的缺点是单次最长 10 分钟文本,超过需要分段。
6.2 方案 B:ElevenLabs(付费,质量更高)
如果需要更自然的语调和情感表达,ElevenLabs 的多语言模型效果更好:
from elevenlabs import generate, save, set_api_key
set_api_key("YOUR_API_KEY")
subtitles = parse_srt("chinese.srt")
full_text = " ".join([s["text"] for s in subtitles])
audio = generate(
text=full_text,
voice="Chris",
model="eleven_multilingual_v2"
)
save(audio, "dub.mp3")
对于非实时需求,也可以将文本按段落拆分后逐段生成,再拼接——分段生成可以更好地控制每个段落的语调和节奏。
七、Step 5:视频合成
最后一步:用 FFmpeg 将原始视频画面、中文配音、中文字幕合成为最终视频。
7.1 替换音轨
ffmpeg -i input.mp4 -i dub.mp3 \
-c:v copy -c:a aac -b:a 192k \
-map 0:v:0 -map 1:a:0 \
-shortest output.mp4
7.2 嵌入硬字幕
如果目标平台(抖音、小红书等)不支持外挂字幕,需要将字幕烧录到视频画面中:
ffmpeg -i output.mp4 -vf \
"subtitles=chinese.srt:force_style='FontName=Microsoft YaHei,FontSize=20,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,Outline=1,Shadow=1,MarginV=30'" \
-c:a copy final_output.mp4
force_style 中几个关键参数:
FontSize=20:1080p 视频建议 18-24,720p 建议 14-18MarginV=30:字幕距底部距离,避免被播放器进度条遮挡Outline=1:文字描边,确保浅色画面下字幕可读
7.3 批量处理脚本
将以上全部流程整合为一个脚本,放入 input/ 目录的视频会被自动处理:
#!/bin/bash
# batch_translate.sh — 批量视频翻译脚本
INPUT_DIR="./input"
OUTPUT_DIR="./output"
mkdir -p "$OUTPUT_DIR"
for video in "$INPUT_DIR"/*.mp4; do
filename=$(basename "$video" .mp4)
echo "处理: $filename"
# Step 1: 提取音频
ffmpeg -y -i "$video" -vn -acodec pcm_s16le -ar 16000 -ac 1 temp_audio.wav
# Step 2: ASR
python transcribe.py temp_audio.wav "$filename"
# Step 3: 翻译
python translate.py "${filename}.srt"
# Step 4: TTS
python synthesize.py "${filename}_chinese.srt"
# Step 5: 合成
ffmpeg -y -i "$video" -i "${filename}_dub.mp3" \
-c:v copy -c:a aac -b:a 192k -map 0:v:0 -map 1:a:0 -shortest \
"$OUTPUT_DIR/${filename}_chinese.mp4"
echo "完成: ${filename}_chinese.mp4"
done
# 清理临时文件
rm -f temp_audio.wav
八、实践中的技术问题
8.1 中英文时长不匹配
英文翻译成中文后,文本长度通常会缩短 20-30%(因为中文信息密度更高)。这会导致配音时长短于原视频,出现"话说完了画面还在播"的情况。
两个解决思路:
- 在翻译阶段扩充:以上文 GPT-4o prompt 中的"中文每句不超过 25 字"为例,可以适当放宽到 30 字,让模型在保持语义的前提下增加自然的语气词和过渡表达
- 在合成阶段拉伸:FFmpeg 的
atempo滤镜可以微调音频速度,atempo=0.9将语速放慢 10%,能让中文配音更从容。不过 atempo 范围仅 0.5-2.0,超出需要用链式滤镜
# 将配音速度放慢 10%
ffmpeg -i dub.mp3 -filter:a "atempo=0.9" dub_slower.mp3
8.2 数字和时间格式的本地化
英文中的 “1,000 dollars” → 中文应为 “1000 美元”,“5:30 PM” → “下午 5 点 30 分”。翻译 API 通常不会自动处理这些转换,需要在翻译后处理时手动替换。
一个简单的正则后处理:
import re
def localize_chinese_text(text):
"""将英文数字格式转为中文习惯"""
# $100 → 100 美元
text = re.sub(r'\$(\d+(?:\.\d+)?)', r'\1 美元', text)
# 1,000 → 1000
text = re.sub(r'(\d+),(\d{3})', r'\1\2', text)
# °F → 华氏度
text = text.replace('°F', ' 华氏度')
return text
8.3 长视频的分段处理
超过 30 分钟的讲座类视频,一次性送入 Whisper 可能触发显存不足或 API 超时。建议先用 FFmpeg 按静音区间切分为 5-10 分钟的片段:
# 按静音检测切分(静音超过 2 秒处切割)
ffmpeg -i long_video.mp4 -c copy -map 0 \
-segment_time 600 \
-f segment \
-reset_timestamps 1 \
chunk_%03d.mp4
每个分段独立处理后,将各段的 SRT 时间轴加上段偏移量再合并。
8.4 视频中的背景音效处理
Whisper 对带背景音乐的视频识别效果较差。如果原视频有 BGM,可以先用 Demucs 或 spleeter 分离人声和背景音:
pip install demucs
python -m demucs --two-stems=vocals audio.wav
分离后的 vocals.wav 送入 Whisper,识别准确率有明显提升。合成最终视频时,将原始 BGM 以较低音量混入中文配音,保留原片的氛围感。
九、是否需要自己搭建?
上述流水线适合以下场景:
- 需要完全控制每个环节的参数和质量
- 处理的视频量大,自己搭建比按次付费更划算
- 对翻译质量有定制化要求(比如需要指定术语表)
如果只是偶尔处理一两条视频,或者不太想维护这套脚本,市面上也有一些集成了上述流程的商业平台——比如 Cutrix、Rask.ai、Vozo 等,上传视频后自动完成 ASR → 翻译 → TTS → 合成全流程,省去了搭建和维护成本。选择自行搭建还是用现成方案,取决于你的处理量和定制化需求。
参考资料
本文代码基于 Whisper large-v3、DeepL API v2、FFmpeg 7.0 版本编写,2026 年 5 月测试通过。
更多推荐


所有评论(0)