外语素材怎么汉化?字幕翻译与双语字幕的 LLM + ffmpeg 工作流
你刷到一个海外博主的硬核教程,或者一段值得反复看的英文访谈,想转成中文双语字幕存进自己的素材库,下次做相关选题直接拉出来参考。手动一句句抄下来翻译,十分钟的内容能耗掉一下午;用机器翻译整段糊上去,时间轴对不上、术语翻得离谱,还不如不看。外语素材的汉化,卡点从来不是"能不能翻",而是"怎么翻得准、还对得上时间轴、还能批量"。这篇文章给你一条可落地的链路:本地语音识别提取字幕 → LLM 批量翻译 → ffmpeg 压制双语字幕,全程命令化、能复用。
📑 文章目录
- 一、为什么是"双语"而不是"纯中文"
- 二、字幕提取:Whisper 本地部署与批量识别
- 三、翻译:用 LLM API 批量翻译 SRT
- 四、双语压制:ffmpeg subtitles 滤镜与 ASS 样式
- 五、工程化:把三步串成一条流水线
- 常见问题 FAQ
- 总结
- 参考文献
🧠 一、为什么是"双语"而不是"纯中文"
先说一个反直觉的判断:外语素材汉化,首选做双语字幕,不要只做中文字幕。原因是素材的属性------它是"你将来要参考的东西",不是"给别人看的成片"。纯中文字幕会丢掉原文术语和语气,等你真要做到相关选题时,反而想不起人家原话怎么说的。双语字幕把原文和译文上下排,既降低阅读门槛,又保留了可追溯的原文。
另一层考量是准确率。机器翻译单独看一句,容易漏掉上下文指代;双语并排时你一眼就能发现"这句翻串了",纠错成本远低于事后回听。所以这条链路的设计目标不是"全自动零校对",而是"把重复劳动交给脚本,把判断留给眼睛"。
💡思考:既然要校对,为什么不干脆人工翻译?
🤔解答:人工翻译的瓶颈不是"翻不出",是"对着时间轴一行行敲格式太慢"。LLM 先把 90% 的活干完,你只校那 10% 别扭的地方,单位时间的产出差一个数量级。素材库里这类参考素材动辄几十上百条,没有脚本化根本攒不起来。
⚖️ 二、字幕提取:Whisper 本地部署与批量识别
如果素材本身没字幕,第一步是用 Whisper 做语音识别,输出 SRT。本地部署的好处是不用上传视频、不烧 API 额度,适合批量:
bash
# 用 whisper-cli 识别为中文 srt(模型按机器选,base/small/medium)
whisper video.mp4 --model small --language zh --output_format srt -o zh.srt
# 如果是英文原声、想要英文字幕做翻译源
whisper video.mp4 --model small --language en --output_format srt -o en.srt
--language 显式指定能避免自动检测误判;--model 在准确率和速度间权衡,英文识别 small 通常够用,专有名词多的选 medium。输出 SRT 是带时间轴的,后面翻译和压制都依赖这个时间轴,所以提取这一步千万别丢轴------很多人图省事让模型直接出 txt,结果后面要对轴,纯属给自己加活。
批量识别封装成脚本最省事:
bash
# 批量识别目录下所有 mp4 为中文 srt
for f in clips/*.mp4; do
whisper "$f" --model small --language zh --output_format srt \
-o "subs/$(basename "${f%.mp4}").srt"
done
🔧 三、翻译:用 LLM API 批量翻译 SRT
SRT 是带序号和时间轴的文本,翻译时要保留时间轴和序号,只翻正文。最稳的做法是解析 SRT,把正文逐条发给 LLM,再拼回原结构。下面用 Python + OpenAI 兼容接口示例:
python
import re, os
from openai import OpenAI
client = OpenAI(base_url="https://api.example.com/v1", api_key=os.environ["API_KEY"])
def translate(text: str, term_hint: str = "") -> str:
sys = f"你是字幕翻译,保留口语感,专业术语准确。{term_hint}"
r = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "system", "content": sys},
{"role": "user", "content": text}],
temperature=0.3)
return r.choices[0].message.content.strip()
def parse_srt(path):
raw = open(path, encoding="utf-8").read()
blocks = re.split(r"\n\s*\n", raw.strip())
out = []
for b in blocks:
lines = b.split("\n")
idx, time, body = lines[0], lines[1], "\n".join(lines[2:])
out.append((idx, time, body))
return out
for srt in ["en.srt"]:
subs = parse_srt(srt)
bodies = [b for _, _, b in subs]
with open("zh.srt", "w", encoding="utf-8") as f:
for (idx, t, b), zh in zip(subs, [translate(x) for x in bodies]):
f.write(f"{idx}\n{t}\n{zh}\n\n")
关键点:temperature 调低保证术语稳定;专业领域加 term_hint 给 LLM 投喂术语表,能显著减少"把产品名翻成一串中文"的事故。翻译源如果是英文 SRT,译文就是中文字幕;原文 SRT 保留,压制时两轨叠加就是双语。
💡思考:逐条调 API 太慢,能不能整段发?
🤔解答:可以,但风险是 LLM 回吐时把序号或时间轴打乱。折中方案是按"相邻若干条"分批发,并在 prompt 里要求"严格按条返回、不合并"。我一般用 5~10 条一批,速度和稳定性平衡点最好。
🎨 四、双语压制:ffmpeg subtitles 滤镜与 ASS 样式
有了原文 SRT(en.srt)和译文 SRT(zh.srt),压制双语用 ASS 样式最灵活。先把 SRT 转 ASS,再用 subtitles 滤镜叠两遍(上原文、下译文):
bash
# srt 转 ass(样式在 ass 里定义)
ffmpeg -i en.srt en.ass
ffmpeg -i zh.srt zh.ass
# 双语压制:主视频 + 上英下中
ffmpeg -i video.mp4 -vf \
"subtitles=en.ass:force_style='FontSize=18,MarginV=60,Alignment=2',\
subtitles=zh.ass:force_style='FontSize=20,MarginV=20,Alignment=2'" \
bilingual.mp4
force_style 里 MarginV 控制距底部距离(原文放高一点、译文放低一点,避免重叠),Alignment=2 是底部居中。ASS 样式比 SRT 强在能精细控制字号、颜色、描边、位置------做双语时这几点直接决定"看不看得清"。
如果素材来自各平台下载,请务必仅供个人学习使用,遵守原平台版权规则,外语素材的汉化版本别直接拿去二传牟利。

🗜️ 五、工程化:把三步串成一条流水线
三步各自跑通后,用一段脚本串起来,输入一个视频、输出一个双语成片:
python
def make_bilingual(video, lang="en"):
whisper(video, lang) # 1. 提取源语言字幕
translate_to_zh() # 2. LLM 翻译出中文字幕
ffmpeg_burn_subtitles(video) # 3. 双语压制
我做外语参考素材时,会批量把这类教程统一转成双语入库。把"识别→翻译→压制"固化成一个命令,外语素材库才真正攒得动------否则每条都手点,三天就放弃了。工程师对"重复三步以上的事必须脚本化"的执念,在处理素材这种高频杂活时尤其成立。
❓ 常见问题 FAQ
Q1:Whisper 识别中文不准,专有名词翻车?
模型换 medium/large;识别前用 ffmpeg 把音频抽成 16k 单声道能提一点准度:ffmpeg -i v.mp4 -ar 16000 -ac 1 a.wav。术语靠翻译阶段的 term_hint 兜底。
Q2:双语字幕两行重叠在一起?
MarginV 没拉开。原文和译文各设不同 MarginV(如 60 和 20),或把其中一轨 Alignment 改到顶部。ASS 的 MarginV 是从对应边缘往里算的像素距离。
Q3:翻译把时间轴弄乱了?
说明你让 LLM 合并了条目。保持"一条 SRT 块 = 一次翻译 = 一条返回",绝不让模型跨块合并。分批时也在 prompt 里强调"逐条返回"。
Q4:能不能不烧 API 做翻译?
可以,用本地 LLM 替代 API 调用,把 translate() 换成本地推理。准确率略低但零成本,适合非关键参考素材。
📝 总结
外语素材汉化的链路就三步:Whisper 本地提取源语言字幕(保住时间轴)→ LLM 批量翻译出中文字幕(低温度 + 术语表保准确)→ ffmpeg subtitles 滤镜叠两轨做双语压制(ASS 样式控位置)。核心心法:让脚本干重复劳动,把校对留给眼睛;永远保留原文 SRT,双语并排既好读又可追溯。把这三步固化成一个命令,你的外语参考素材库才真正攒得起来。
写这篇的私心:我自己在做的工具「影栈」,最早就是想解决"刷到的好素材散落在各处、要用时找不到"------把多平台素材统一管理,这类外语教程汉化完才有干净的归属地。后续我会在 CSDN 持续更新这款工具的实战记录,感兴趣的可以关注我的博客主页。
参考文献
- OpenAI Whisper Repository --- https://github.com/openai/whisper
- FFmpeg Filters Documentation(subtitles / ASS 样式)--- https://ffmpeg.org/ffmpeg-filters.html
- SubStation Alpha (ASS) 格式规范 --- https://www.matroska.org/technical/subtitles.html
- OpenAI API Documentation(chat completions)--- https://platform.openai.com/docs/api-reference