把字幕扒成纯文本、丢给模型翻译——这一步现在几乎没有门槛。真正麻烦的是第二步:译文怎么原样贴回那条时间轴。
失败的形态很统一:前面十几条看着都对,看到一半发现中英文对不上号了,而且往前翻怎么也找不到是从哪一条开始错的。
根因:模型在重组句子
字幕的分行是按时间切的——一句话说得长,就切成两三条。而模型翻译时是按语义组织的,于是会做四类改动:
| 改动 | 场景 |
|---|---|
| 合并 | 一个英文长句被切成三条字幕,模型认为是一句话,翻成一行 |
| 拆分 | 一条长中文译成两个英文句子,模型分了两行 |
| 删行 | 只有语气词或重复内容的行被当成噪声丢掉 |
| 加行 | 顺手加了译注或解释 |
这不是模型不听话。 保留字幕的分行本身就违反语言习惯,你越强制它保留,译文质量越差——这是一个真实的取舍。
所以正确的思路不是消灭漂移,而是让漂移可检测、可定位。两条路。
路线 A:编号锚定
给每行加一个固定格式的编号,要求模型原样保留。
发出去的样子:
[001] Hello, is anyone there?
[002] I've been waiting for
[003] almost three hours now.
提示词里必须写清三条:编号原样保留、不得合并或拆分行、不得增删行。
拿回来之后必须校验——这一步不能省:
- 编号连续无缺
- 总行数一致
- 没有重复编号
- 每行都以编号开头
^\[(\d{3})\]\s*
任何一条不满足,就重发这一块。 不要手工补——在几百行里手工补编号,会引入你自己都察觉不到的偏移,而这种偏移到最后一步才会暴露。
用方括号加零填充是有理由的:它在正常字幕文本里极少出现,正则不会误伤正文;宽度固定则便于严格匹配。
路线 B:不要求行对齐
更稳的一条路:让译文自己成为一份完整的字幕,再按时间重叠合并。
为什么这样更稳:按时间配对不要求两边行数相同。一条中文对应两条英文时,两条英文会被拼到那一条中文上;反过来也能正确处理——哪怕模型合并了几行,结果依然是对的。
这恰恰是双语字幕合并不按序号配对的原因:两种语言的断句几乎从不一致,按序号对齐只要中间多一条少一条,后面全部错位,而且错得很隐蔽。
代价有两个:模型偶尔会改动时间戳格式,需要校验;被合并的那几行时间范围会取其中一条的,可能略有偏差。
几千行的长片优先选这条路。
分块:大小、上下文、术语表
不管走哪条路,长片都要分块。
每块 50 到 100 行:
- 块太大 → 输出越长,模型越容易在后半段开始合并行;校验失败时整块重来也更浪费
- 块太小 → 上下文不足,代词指代、人物性别、术语前后不一致
上下文这样给:在每块前面附上上一块最后 2 到 3 行的原文和译文,并明确标注「以下仅供参考,不要翻译、不要输出」。
术语表每一块都要重复给。模型不会记得几轮之前的约定,只在第一块给等于没给。表就写成两列:
术语对照(必须遵守):
Eleanor → 埃莉诺
the Bureau → 调查局
"cold open" → 冷开场
人名、地名、专有名词、反复出现的梗都放进去。这是长片译文质量差异最大的一个变量——同一个人名在前半部分叫「艾莉诺」后半部分叫「埃莉诺」,观感上比几句翻得生硬糟糕得多。
分块和 token 预算的更多细节,见 字幕转文字稿喂给 AI 的分块指南。
质量抽查:按长度比排序
全部翻完之后,不要从头逐条看。按「译文长度 ÷ 原文长度」排序,抽查两头:
- 比值异常大(两三倍以上)→ 模型在解释内容而不是翻译,常见于俚语、双关、专有名词
- 比值异常小→ 可能漏译,或者整行被吃掉了
前后各看二十条,能捞出大部分质量问题,成本远低于通读。
完整流程
原字幕
↓ 格式统一、去广告行、修乱码 → 字幕格式转换
干净的原轨
↓ 导出纯文本(保留时间戳) → 字幕转文字稿
待翻文本
↓ 分块 + 上下文 + 术语表 → 模型
译文
↓ 逐块校验(编号 / 时间戳格式)
译文轨
↓ 按时间重叠配对 → 双语字幕合并
双语字幕
最后一步会给出配对率和两个诊断数:整轨偏移的中位数、前后半段的快慢差。
- 配对率低 → 两轨时间轴本身对不上,多半是片源版本不同或帧率不一致
- 配对率高但内容错行 → 看有没有「副轨整体早/晚 X 秒」的提示
这两种情况都不要靠调低配对灵敏度去解决——那只会把相邻两句强行配到一起,出来的双语字幕文不对题。正确做法是先用 字幕时间轴校准 把译文轨推到原轨的时间线上。帧率不一致的成因见 23.976 和 25 是怎么来的。
一句话
别指望模型保持行数,指望你的校验能发现它没保持。 编号锚定让漂移可定位,时间配对让漂移不要紧——两条路各选一条,就不会再出现「看到一半发现对不上」。