# SRT 字幕时序校验：重叠、零时长与媒体边界

渲染前拒绝序号歧义、零时长、重叠和超出片尾的字幕。本配方只覆盖明确声明的简单 SRT 子集与输入的两秒媒体边界。

完整包只使用 Node 标准库。不需要安装媒体工具。

在本目录运行，并选择不存在的新输出目录，脚本拒绝覆盖。受内存管理的工作站可在 Node 命令前加本地串行执行包装器。不需要提供商密钥，夹具不会向设备外发请求。

```sh
node run-recipe.mjs --out ./my-run
```

实际记录：9项检查通过，包含6项预期拒绝，Node v24.18.0。未启动 FFmpeg 子进程。

准备

- 只需要 Node.js，不需要第三方包或 FFmpeg。duration.json 明确给出 2000 毫秒媒体边界。
- 查看 valid.srt：第一条 0–700ms，第二条 700–1400ms，第三条 1500–2000ms；允许相邻字幕，也允许最后结束点等于媒体时长。
- 保留严格的 HH:MM:SS,mmm --> HH:MM:SS,mmm、连续序号和非空文字。夹具是纯文本，不承诺字体或烧录结果。

## 01. 解析前先写清时序规则

本例使用整数毫秒、从一连续编号、不允许重叠、结束必须晚于开始。媒体边界是明确输入，脚本不会探测真实视频时长；第三条之前的 100 毫秒空隙是刻意保留。

## 02. 实际解析合法字幕

运行命令后检查 cue-table.json，其中保存三条真实解析的开始与结束数值。开始恰等于上一条结束可以通过，末条也允许恰在 2000 毫秒结束。

## 03. 重放六份错误字幕

脚本写出并测试重叠、零时长、超边界、错误序号、毫秒格式错误及分钟越界变体。每项预期失败都记录具体异常；即使时间串外形正确，分钟为60仍不合法。

## 04. 把时序结果交给独立渲染环节

核对九项断言，把时间表与原始 SRT 成套保存。字形覆盖、换行、阅读速度、HTML 扩展与实际画面需要另验；本包不包含 CJK 字体清单或烧录字幕视频。

验收

- 合法 valid.srt 实际解析为三条整数毫秒记录。
- 第二条开始等于第一条 700ms 结束时可以通过。
- 最后一条恰在 2000ms 媒体边界结束可以通过。
- 重叠与零时长变体分别因不同原因被拒绝。
- 2001ms 结束与不连续编号均被拒绝。
- 毫秒格式错误及分钟60均被拒绝，九项检查全部通过。

排错

首尾相接的字幕被误报重叠。将无重叠规则设为 start >= previousEnd，再实跑 700ms 相接边界。

恰好到片尾的末条被拒绝。先核对输入 durationMilliseconds，确认后允许 end 等于该边界，同时继续拒绝 2001ms。

时间串格式正确，但字幕没有可见时长。只调整 end，使其严格晚于 start，再检查与下一条重叠；不删除零时长规则。

公开回执副本仅归一化本地 checkout 路径，publicPathNormalization 保存原始回执 SHA-256；未改动原件保留在非公开资产之外。真实回执位于 executed/。failure-receipt.json 记录预期负向案例，不表示套件断言失败。原创新夹具会重新生成到指定新目录，包内保留实跑输入输出便于复核。临时原始数据和本机 HTTP 服务在 finally 清理。

checksums.json 覆盖自身与 ZIP 以外的全部分发文件，避免循环自引用；ZIP 内包含同份清单。下载后可重算，但比较前提是预期清单可信。execution-receipt.json 记录实际脚本运行前后哈希，ZIP 也会由发布目录的资产清单绑定。

合法时序是渲染环节的输入，不能证明指定字体可显示、字幕能放进画布或观众读得完。

2026-10-14 实际读取的来源

- Node.js filesystem API: local file inspection：https://nodejs.org/api/fs.html
- Node.js crypto API: SHA-256 hashing：https://nodejs.org/api/crypto.html
