Communitygithub.com

subtitle-translate — 双语 ASS + 术语表

SRT / 词级 ASR JSON / 视频 → 简体中文 + 原文双语 ASS。terminology.yaml、双遍校对、注解字幕。六步固定流水线。

subtitle-translate — 双语 ASS + 术语表 是什么?

Video Localization 步骤2(抛光):ywwzwb/subtitle-translate-skill — 把毛坯字幕打成可出货双语 ASS(术语表 + 双遍 QA)。相对 9/26 haiyimei、9/24 starinzlob 的新鲜中段。

兼容平台✓Claude Code~Codex CLI~Cursor✓OpenCode
npx skills add ywwzwb/subtitle-translate-skill

在你喜欢的 AI 中提问

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

文档

字幕翻译 (Translating Subtitles)

概述

将字幕文件(SRT、带词级时间戳的 ASR JSON、或视频/音频)翻译为双语(简体中文 + 原语言) ASS 字幕。流程固定为 6 步, 必须按顺序全部执行, 不得跳过或改变顺序:

  1. 输入归一化 + ASR 转录(视频/音频; SRT 跳过; ASR 自动识别语种)
  2. 时间戳 → YAML(脚本 + 模型复核, 含分句合适性检查)
  3. 校对原文 + 时间戳二次核对(第二遍听写交叉验证; 错误/漂移直接修正到 YAML, 含分段重转修复)
  4. 分批翻译(术语表 + 注解字幕)
  5. 校对译文
  6. 合并为 ASS(脚本)

脚本位于本 skill 的 scripts/ 目录(与 SKILL.md 同级)。运行脚本时, <skill_dir> 指本 SKILL.md 所在目录。

环境与配置

  • 需要 ffmpeg、python(含 pyyaml)、以及本地 ASR 工具 q3asr(Qwen3-ASR GGUF 跨平台 CLI)。
  • 运行时解析优先级: run_transcribe.py --exe > 环境变量 TRANSCRIBE_EXE > 自动下载。默认自动下载: 按 os/arch/后端 从 ywwzwb/qwen3-asr-universal 发布版取 q3asr 二进制缓存到 ~/.cache/opencode-translate/asr/(首次联网, 之后复用)。手动指定时设 TRANSCRIBE_EXE(Linux/macOS 指向 q3asr, Windows 指向 q3asr.exe)即可, 不用改本文件。

工作目录(临时隔离)

每次翻译任务独立一个临时工作目录, 所有中间产物集中在一处, 完成后一键清理:

  1. 建目录: mkdir -p "$TEMP/opencode/<输入文件基名>"($TEMP 即系统临时目录, Windows 为 %TEMP%, 如 C:\Users\zwb\AppData\Local\Temp; 基名取输入文件名去扩展名)。
  2. 把输入文件(视频/音频/SRT)复制进该目录, 之后所有操作都在这个目录内完成。
  3. 所有中间产物(mp3、txt、srt、json、main.yaml、seg*.yaml 等)都生成在这里, 不污染输入文件所在目录。
  4. 完成后, 把最终 .ass 复制到输入文件所在目录(或用户指定位置)。
  5. 用户要清理时, 直接删除整个工作目录即可。

术语表不受影响: terminology.yaml 在 skill 目录里全局共享(见第 4 步), 不放进工作目录。

第 1 步: 输入归一化 + ASR 转录

按输入类型准备音频:

  • 视频(mkv/mp4/mov 等): 先转单声道 16kHz MP3: ffmpeg -y -i <input>.mkv -vn -map 0:a:0 -ac 1 -ar 16000 -c:a libmp3lame <input>.mp3
  • 音频(mp3/wav/m4a 等): 同样转成统一单声道 16kHz mp3, 输出命名为 <basename>.mono.mp3(如 demo.mp3 → demo.mono.mp3), 与视频路径的 <input>.mp3 区分, 避免与同名原文件冲突。
  • SRT: 跳过本步(无需归一化与 ASR), 直接进入第 2 步(时间戳 → YAML)。

若输入是音频/视频, 运行 ASR 转录(一律作用于上面归一化后的 mp3: 视频为 <input>.mp3, 音频为 <basename>.mono.mp3):

python3 <skill_dir>/scripts/run_transcribe.py <audio>.mp3 -y

若 ASR 运行时缺失, 自动从 ywwzwb/qwen3-asr-universal 最新 release 下载匹配 os/arch/后端 的 zip 到 ~/.cache/opencode-translate/asr/ 并缓存。后端自动探测: 首次运行时探测本机最优方案(cuda→vulkan→metal→cpu, 依据 nvidia-smi/vulkaninfo 是否存在), 结果保存到本 skill 目录的 config.yaml(像 terminology.yaml 一样持久共享), 后续直接复用不再探测; 跨机器时做轻量复核, 失效则重新探测。模型默认 1.7B, 与后端一起存入 config.yaml, 首次由 q3asr 自动下载到 ~/.cache/q3asr/models/(已有缓存则复用)。可用环境变量覆盖: TRANSCRIBE_BACKEND(cuda/vulkan/metal/cpu)、TRANSCRIBE_MODEL(如 1.7b/0.6b)、TRANSCRIBE_ASR_VER(默认 latest)。手动指定 TRANSCRIBE_EXE 仍为最高优先级。

  • 产出同名 <audio>.txt、<audio>.srt、<audio>.json(词级时间戳 [{text,start,end}], 秒)。
  • 分段重转用 --out 防止覆盖全片产物: run_transcribe.py 会把 .txt/.srt/.json 以输入音频名命名。对同一 mp3 做窗口重转(--seek-start)时, 若不加 --out 会覆盖全片 <audio>.json。加 --out <名字>(如 --out seg1)会把音频复制为 <名字>.mp3 再转录, 产物落到 <名字>.json 等, 全片 JSON 原样保留。
  • ASR 自动识别语种(Qwen3-ASR 支持多语言); 如需强制指定语种再传 -l <Language>。
  • 长音频: 先 ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 <audio>.mp3 得知时长, 给 bash 命令设置足够大的超时(本地 1.7B 模型约 0.05×时长 秒, 另加模型初始化)。

故障排查

  • ASR 失败(退出码非 0): run_transcribe.py 失败时已自动打印 logs/latest.log 尾部, 按日志尾部定位; 若是本地 GPU/图形栈相关报错, 加 --no-dml --no-vulkan 重试。
  • 自动下载的运行时无法启动(如冻结二进制缺 libllama.so 报 Failed to load dynlib/dll): 换用本机可用的 q3asr 源码安装/已解压运行时, 设 TRANSCRIBE_EXE 指向它即可, 不必改本文件。
  • 乱码 !!! / 花屏: 设置环境变量 GGML_VK_DISABLE_F16=1 后重新转录(Vulkan 禁用 fp16, 规避部分驱动不兼容)。
  • ffmpeg 不存在: 立即停止, 先安装 ffmpeg 并确保在 PATH 中, 再继续第 1 步。

第 2 步: 时间戳 → YAML

按来源选择脚本:

  • 音频/视频来源(<audio>.json): 运行 python3 <skill_dir>/scripts/timestamp_to_yaml.py <audio>.json main.yaml (可选 --max-width 每行宽度上限默认 30, --gap 分句停顿阈值秒默认 1.5)
  • SRT 来源: 运行 python3 <skill_dir>/scripts/srt_to_yaml.py <input>.srt main.yaml

生成中间文件 main.yaml:

main:
  - from: 00:00:02,003
    to: 00:00:05,069
    en: |
      Narrator:
      TODAY ON "HOW IT'S MADE"...
  - from: 00:00:26,227
    to: 00:00:28,026
    en: |
      ALUMINUM FOIL...

转换后立即跑塌缩检测(脚本, 必须先于人工复核): ASR 时间戳经常整块塌缩——多条 cue 挤在同一秒(甚至零时长)、文本乱码。机械复核前先用脚本扫一遍:

python3 <skill_dir>/scripts/check_collapse.py main.yaml

  • 检测: zero(零时长 from==to)、cluster(3+ 条共享同一开始时间 = 整块塌缩)、order(乱序)、overlap(时间重叠)。
  • 退出码: 干净为 0, 有问题为 1。出现 zero/cluster 即按第 3 步"分段重转修复"处理该区域。
  • 窗口重转出的 seg*.yaml 用 --strict 再扫一遍(2 条同秒即报警): python3 <skill_dir>/scripts/check_collapse.py seg.yaml --strict——大窗口重转自身也常在末尾塌缩, 转完先自查再拼回。

转换后必须复核(模型判断): 脚本按句号/叹号/问号/长停顿自动分句, 并按宽度自动拆分过长句子, 已自动合并过短片段(句内孤片并入相邻、无句末标点的单字孤儿并入下句)。转换脚本已内置"悬空分句自动合并": ASR/宽度切分常把句子拦腰截断在功能词处(以 the/a/to/any/each/boil/known 等结尾), 或幻觉句号后小写续写(plasters./is applied.), 或留下单字头(Plasters/are made of...)。timestamp_to_yaml.py 会自动把这些残片并入下句, 减少人工合并工作量。复核时:- 检查分句是否自然; 过长或切分不自然的句子重新确定拆分点(优先在顿号、逗号等软分隔处)。

  • 极短片段必须合并: 若某条 cue 只有 1-2 个词或明显是从完整句中拆出的残片(如单独的 mercury,、The), 用 edit 并入上一句或下一句, 使每条字幕都是完整语块。标题性短句(Cheese.、Tights.)除外。
  • 音频/视频来源: 重新拆分时必须读取原始 JSON, 按拆分后每个子片段的词 token 起止时间更新 from/to(SRT 无词级时间戳, 不适用此条)。

分句合适性检查(逐条 cue 判断, 必须执行): 脚本按宽度/停顿机械切分, 常把句子拦腰截断。对照以下标准逐条检查, 不合适就用 edit 合并或移动拆分点:

  • 每条 cue 必须是完整语块: 不能以悬空介词/连词结尾。行尾出现 and、or、as、where、which、before、to、of、into 等时, 说明切分点错了, 应把该词并入下一行或整体合并。
  • 拆分点放在从句/并列连接词之前, 而不是之后。例: assure quantity distribution / before they're carried...(而非 ...distribution before / they're carried...); come down 2,000 times per minute / to cut a total of 8,000...(而非 ...to cut a / total of 8,000...)。
  • 同一语块的介词短语不要拆开: 5 hours of work 保持完整, 不要拆成 5 hours / of work; the brush and roller area 不要拆成 the brush and / roller area。
  • 残片合并后若读起来才是一句完整的话, 就合并: 如 ...cuts the billet strips into + small, equal-sized pieces. 应合并为一条; ...responsible for the + cloudiness of the beer. 应合并。
  • 中文分句镜像英文: 中文译文的行边界应与英文 cue 一致, 行尾同样不能悬空(如 按量分配, 后接 随后被送往..., 应把 随后 移到下一行; 落下2000次,切割出 应改为 落下2000次 / 短短60秒内总计切割出8000根)。
  • 合并/移动拆分点后, 必须读取原始 JSON 按新分片的词 token 起止时间更新 from/to。

第 3 步: 校对原文

逐句阅读 en 字段, 找出拼写错误、听译错误、漏字, 直接用 edit 工具修正 main.yaml 中的 en, 并在回复中列出修改点。禁止只在注解中提示而不改原文。

保持 main.yaml 的标准格式( - from: + en: | 块, 见第2步示例): 只做局部 edit, 禁止用脚本重排整个文件(如 yaml.safe_dump 重写), 以免破坏缩进与块标量格式。

分段重转修复(幻觉/错误时间戳)

发现坏区域(单条字幕时长异常长、文本乱码、cue 时间重叠)时:

  1. 选窗口: 坏区域起点往前 ~3s、终点往后 ~3s, 得 X 与 D = end - X。
  2. 重转该段(必须带 --out, 否则覆盖全片 <audio>.json): python3 <skill_dir>/scripts/run_transcribe.py <audio>.mp3 --seek-start X --duration D --out seg1 -y(时间戳相对切片起点, 产物为 seg1.json)。
  3. 重转段自检: python3 <skill_dir>/scripts/check_collapse.py seg1.yaml --strict。大窗口重转常自身塌缩(多条 cue 挤在同一秒), 有 zero/cluster 就先缩小窗口重转, 不要继续拼。
  4. 还原绝对时间: python3 <skill_dir>/scripts/timestamp_to_yaml.py seg1.json seg.yaml --offset X(脚本自动合并悬空分句, 见第 2 步)。
  5. 核对覆盖: 用 --offset 后 seg.yaml 最后一条的 to 应 ≈ X + D。若明显早于 X + D(重转输出被截断), 扩大窗口重转, 不要继续拼。
  6. 拼回(必须传窗口参数): python3 <skill_dir>/scripts/splice_yaml.py main.yaml seg.yaml main.new.yaml --seek-start X --duration D。脚本会用请求窗口而非段内容范围做删除, 并校验覆盖——若重转段被截断, 脚本会报错拒绝拼回(必要时可 --force, 但先扩大窗口重转为宜)。
  7. 复核: 检查 splice 输出(删除清单 + 字数警告 + LOSS 行)。每次 splice 都会默认打印被删 cue 清单; 若出现 LOSS: 行, 说明有条被删 cue 的文本没在重转内容里出现——若是完好句子, 扩大窗口重转。若出现 BOUNDARY: 行, 说明有条被删 cue 跨窗口边界(起点在窗口前或终点在窗口后), 其内容可能被拦腰截断——确认该窗口真覆盖了它, 否则扩大窗口重转。确认无漏词后, 用 edit 以 main.new.yaml 内容替换 main.yaml; 若丢词, 扩大窗口重转或手工 edit 修正。

必须用 splice_yaml.py 拼回, 禁止手工拼接重转片段: 手动把新 cue 贴进 main.yaml 极易产生重复/重叠 cue(同一 from 出现两次), 用脚本按时间窗口替换可避免。替换后若发现重复 from, 说明拼接过当, 用 splice 重做。

时间戳二次核对(第二遍听写交叉验证)

同一音频连转两遍, 词级时间戳会明显漂移(实测: 两遍之间 max delta 可达数十秒, 部分 cue 相差 12-40s)。因此听写一遍出的时间戳不可全信。整理完 YAML 后, 必须再完整听写一遍, 与当前 cue 时间交叉核对:

  1. 复制音频再转第二遍(不要覆盖第一遍 JSON): cp <audio>.mp3 <audio>.pass2.mp3, 然后 python3 <skill_dir>/scripts/run_transcribe.py <audio>.pass2.mp3 -y, 产出 <audio>.pass2.json(也可用 --out pass2 省去手动 cp, 效果相同)。
  2. 逐条核对: python3 <skill_dir>/scripts/compare_timestamps.py main.yaml <audio>.pass2.json --threshold 1.0。脚本按规范化文本把每条 cue 的 en 定位到第二遍的词 token, 输出 delta start/end(当前 cue 时间 − 第二遍词级时间)与 <<< 标记。阈值默认 1.0s(第二遍自身会漂移, 0.5s 假阳性太多)。
  3. 对 <<< 或 NOT FOUND 的 cue 精确校对: 第二遍听写只是探测器, 不是权威——它自己也会漂移(整段整体偏移), 绝不能直接以第二遍时间戳为准改 from/to。一律按上文"分段重转修复"流程对该窗口重转: 取该 cue 前后 ~3s 窗口重转 → --offset 还原绝对时间 → splice_yaml.py 拼回, 以窗口重转结果为准。若窗口重转与第二遍一致, 则主 yaml 时间确实错了, 修; 若一致确认主 yaml 对, 不改。
  4. 交叉复核译文侧: compare_timestamps.py 可对任意 yaml 用 --full 输出全部 cue 的 delta, 便于整体看漂移趋势。
  5. 反复执行直到无 <<< 且无 NOT FOUND(或已人工确认)。

说明: 第二遍听写也偶有自身漂移或文本不同(hence NOT FOUND), 所以最终以分段窗口重转 + 人工听音为准, compare_timestamps.py 只是快速发现可疑 cue 的探测器。

第 4 步: 分批翻译

开始翻译前, 先读取 <skill_dir>/terminology.yaml(不存在则创建空文件)。 术语表存放在本 skill 的目录里(全局安装时即机器级), 跨视频、跨项目、跨会话持久共享, 保证不同视频里同一人名/地名/专有名词译法一致。翻译中遇到新术语, 先把它加进 <skill_dir>/terminology.yaml 再使用; 匹配不区分大小写。

说明: 若 <skill_dir> 与当前项目不同(全局安装), 术语表就是全局唯一的一份; 项目里不再单独维护 terminology.yaml。

翻译采用结构化批量输出 + 脚本写入, 不用逐句 edit:

  1. 分批翻译(每批 ≤50 句): 在回复中输出结构化译文块——start 是该批第一句在 main.yaml 中的 cue 序号(0-based), translation 列表逐句对应, 顺序与 main.yaml 的 cue 完全一致。禁止一次性输出全部字幕的翻译, 一批写完确认后(脚本写入 + 抽查)再处理下一批。
start: 0            # 本批第一句的 cue 序号(0-based)
translation:
  - 第1句译文
  - 第2句译文
  - |
    多行译文第一行
    多行译文第二行
  - 第4句译文
  1. 脚本写入: 把上面的结构化块保存为 batch.yaml(工作目录内), 运行 python3 <skill_dir>/scripts/apply_translations.py main.yaml batch.yaml main.new.yaml 脚本按 cue 序号把 chs 字段精确插入每条 en 块之后, 不重排文件(非 safe_dump), 注解与其他行原样保留。核对后 cp main.new.yaml main.yaml。

    • --overwrite: 替换已有 chs(默认遇已有 chs 报错, 防止错位批量静默覆盖)
    • --dry-run: 只打印将写多少条, 不落盘
    • 脚本会校验 start + 条数 不越界; 越界即报错, 停下核对 start
  2. 翻译不落地前先自查: 每条译文遵守下方翻译规则(句尾无句号/逗号、数字阿拉伯化、术语表一致、行边界镜像英文 cue)。写完一批后人工抽查该批首尾几条, 确认 cue 序号与内容对齐(尤其检查翻译块里的 start 是否等于上一批的 start + 上一批条数)。

最终审阅仍用 edit 工具逐条修正——批量写入负责"灌入", 人工 edit 负责"精修"。

main:
  - from: 00:00:02,003
    to: 00:00:05,069
    en: |
      Narrator:
      TODAY ON "HOW IT'S MADE"...
    chs: |
      旁白:
      今天的《造物小百科》……

翻译规则

  1. 意译优先, 不逐字逐句。 按汉语语序和句式长度调整词序、位置, 可合并或拆分句子, 确保中文通顺自然。
  2. 专有名词统一走术语表。 人名、地名、作品名、品牌名等, 在 terminology.yaml 中统一翻译, 并每次翻译前先读取。术语匹配不区分大小写。遇到新术语时先加入术语表再使用:
terminology:
  Susan: 苏珊
  Texas: 德州
  HOW IT'S MADE: 造物小百科
  1. 句尾标点。 译文正文句末若最后一个字符是句号 。 或逗号(全角 , 或半角 ,), 直接去掉。例: "欢迎收看本期节目。" → "欢迎收看本期节目"。句号/逗号只允许出现在句中, 不得作为译文句尾。
  2. 数字用阿拉伯数字。 译文中的数字尽量用阿拉伯数字书写: 三到八小时 → 3-8 小时、二十年前 → 20 年前、六千克面粉 → 6000 克面粉、百分之九十五 → 95%、四点四米 → 4.4 米、750 摄氏度 → 750 摄氏度。用于专有名词/标题里的数字(如 "How It's Made"、年份、型号)除外。
  3. 注解字幕。 字幕中出现中文语境少见的当地习俗、节日、专业名词、英制单位等, 添加 ≤20 字(约 4 字/秒)的简短注解, 写入 main.yaml 的 annotations 列表。同一术语只在第一次出现时注解。
annotations:
  - from: 00:00:02,003
    text: 造物小百科:科普纪录片栏目

注解规则:

  • 每个注解 ≤20 字, 尽量简洁。
  • from 与对应字幕的开始时间对齐。
  • to 不必填写, yaml_to_ass.py 按 4 字/秒 自动计算结束时间。
  • 同一句(开始时间相同)若出现多个注解, 脚本会合并为一条事件, 上下并列展示。
  • 连续注解若前一条结束时间晚于后一条开始时间, 脚本会将前一条结束时间钳制到后一条开始之前, 避免时间重叠。
  • 英制单位: 注解直接给出该句具体数值的标准国际单位换算, 如 "500磅≈227公斤"、"60英里≈96.6公里/时"、"62°F≈17°C", 不解释单位本身的含义(如"英制重量单位")。单位换算用 ≈ 表示近似; 数值不同时每次出现都需换算, 不受"首次出现"限制。

第 5 步: 校对译文

通读全部 chs, 检查错译、漏译、术语不一致、时间轴错位, 用 edit 工具修正。

校对完成后, 再通扫一遍 main.yaml, 把适合阿拉伯数字表示的数字直接用 edit 改成阿拉伯数字:

  • en(听写)里的英文词形数字: three to eight hours → 3 to 8 hours、six thousand kilos → 6,000 kilos、twenty years ago → 20 years ago、half a centimeter → 0.5 centimeter、seventy-five → 75、first/second → 1st/2nd。
  • chs(译文)里的中文数字: 二十年前 → 20 年前、三到八小时 → 3-8 小时、六千公斤 → 6000 公斤、百分之九十五 → 95%、四点四米 → 4.4 米。
  • 用于专有名词/标题/年份/型号的数字保持不变(如 "How It's Made"、Narrator: 里的年份)。
  • 只改明确无疑的; 拿不准的就保持原文。

第 6 步: 合并 ASS

运行: python3 <skill_dir>/scripts/yaml_to_ass.py main.yaml output.ass --check

--check 会校验 cue 完整性(重叠 / 零时长 / 乱序), 有错则报错并退出, 防止带病出片。合并完成后, 把成品 .ass 复制到输入文件所在目录(如视频旁边), 便于用户直接使用; 工作目录里的中间产物留给用户按需清理。

生成格式(模板内嵌于脚本, 要点如下):

[Script Info]
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080
WrapStyle: 2

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Translation,Noto Sans CJK SC,56,&H00FFFFFF,&H000000FF,&H00141414,&H80000000,-1,0,0,0,100,100,0,0,1,3,1,2,80,80,81,1
Style: Original,Noto Sans CJK SC,36,&H00FFFFFF,&H000000FF,&H00141414,&H80000000,-1,0,0,0,100,100,0,0,1,2,1,2,80,80,45,1
Style: Annotation,Noto Sans CJK SC,26,&H00FFE066,&H000000FF,&H00141414,&H80000000,-1,0,0,0,100,100,0,0,1,1,1,7,40,40,20,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text

输出为三条独立轨道, 便于后期逐轨调整样式(各轨道用独立的 Layer 与 Style, 可在 Aegisub/剪辑软件中分开编辑):

LayerStyle内容字号/位置
0Translation简体中文译文fs56, 底栏主行
1Original原语言文本fs36, 紧贴译文下方
2Annotation注解fs26, 左上角

布局要求:

  • 译文为主: 底栏大字号(Layer 0)。
  • 原文为辅: 译文下方小字号(Layer 1)。
  • 注解在左上角(Layer 2, Alignment 7)。

示例事件:

Dialogue: 0,0:00:02.00,0:00:05.06,Translation,,0,0,0,,今天的《造物小百科》……
Dialogue: 1,0:00:02.00,0:00:05.06,Original,,0,0,0,,Narrator: TODAY ON "HOW IT'S MADE"...
Dialogue: 2,0:00:02.00,0:00:03.62,Annotation,,0,0,0,,造物小百科:科普纪录片栏目

常见错误 (Common Mistakes)

错误正确做法
跳过 YAML 直接输出 ASS必须先转 main.yaml, 翻译再合并
手写 ASS 代替脚本用 yaml_to_ass.py 合并, 注解时间由脚本计算
出 ASS 前不校验完整性用 yaml_to_ass.py --check 查重叠/零时长/乱序
一次性翻译全部字幕每批 ≤50 句, 分批输出结构化译文, 脚本写入
逐句 edit 写 chs用 apply_translations.py 批量写入, edit 只用于最终审阅
批量 start 序号错位start 必须 = 上一批 start + 上一批条数; 脚本越界会报错
批量覆盖已有译文默认遇已有 chs 报错; 确需替换才加 --overwrite
人名地名前后译法不一致写入 terminology.yaml, 每次先读取
注解超过 20 字压缩, 只保留必要信息
注解结束时间随手填交给脚本按 4 字/秒 计算
同一句多个注解未并列脚本自动合并为上下两行
英制单位注解只解释单位含义直接给出该数值的 SI 换算(如 "500磅≈227公斤")
原文错误只加注解不改直接修正 main.yaml 的 en
同一术语反复注解只在第一次出现时注解
译文句尾保留句号/逗号去掉句末的 。、,、,
跳过第 5 步校对出 ASS 前必须通读 chs
重转片段时间轴不对用 --offset X 还原绝对时间
直接删旧字幕不重转走分段重转: 重转 → --offset → splice 拼回
幻觉时间戳靠脚本钳制用分段重转修复, 不用钳制
只信一遍听写的时间戳听写会漂移, 必须第二遍听写交叉核对(compare_timestamps.py)
塌缩区域不检测就人工复核复核前先跑 check_collapse.py main.yaml
分段重转不传 --out不带 --out 会覆盖全片 JSON, 必须传
拼回时不传 --seek-start / --duration不传窗口参数 splice 脚本无法正确替换, 必传
译完不跑 --check 就出片禁用 --check 可能带重叠/零时长 cue 出片
第二遍时间戳直接覆盖主 yaml第二遍自身会漂移, 只用作探测器

相关技能