简体中文

视频和字幕·字幕工具包

浏览器如何解析 SRT 文件:块、索引、时间码和文本

· 工作原理

字幕 srt 文件格式

两个 SRT 提示块由空行分隔,每个提示块都有一个索引行、一个时间码行和文本行
原始 ToolAcre 矢量图

SRT 看起来微不足道,直到您遇到真正的文件。这篇文章将介绍解析器如何分割块、读取索引和时间码、处理多行文本以及从实际文件包含的格式错误的块中恢复。

文件“看起来不错”,但缺少一半线索——看似宽松的格式如何隐藏严格的期望

SRT 没有规范主体,没有 MIME 注册,也没有玩家附带的验证器。相反,存在的是大多数软件都同意的形状:一个数字、一个时间码行、一行或多行文本,然后是一个空行。由于形状是常规的而不是指定的,因此两个文件在文本编辑器中看起来都是正确的,但只有其中一个加载,并且失败通常是无声的。无法读取提示的玩家往往会跳过它而不是报告它,因此带有损坏块的文件会出现间隙而不是错误。

因此,解析器有两个相反方向的工作。它必须接受真实文件包含的变化,因为文件是由转录服务、手工编辑和格式转换器生成的,每个服务都做出不同的假设。它还必须拒绝会在错误时间发出提示的读数,因为默默地错误的时间戳比报告的故障更糟糕。

分割成块 - 空行作为分隔符以及杂散空白和 CRLF 的麻烦

拆分发生在空行上,而不是索引号上。解析器首先规范行结尾,用单个换行符替换 CRLF 对和单独的 CR,因为在 Windows 上编写并在 Unix 上编辑的文件可以包含这两者。然后它会分割成两个或多个换行符,修剪每个结果块并丢弃空的块。这种顺序很重要:在标准化之前进行分割会在时间码行的末尾留下杂散的回车符,然后时间码将无法匹配。

字节顺序标记在其中任何一个之前被剥离。文件开头的 UTF-8 BOM 是三个字节,天真的解析器将其视为第一个索引号的一部分,这足以使第一个提示在后面的每个提示解析时不可读。空白分隔行上的尾随空格由修剪处理,因此空白行包含空格的文件仍然可以正确分割。

索引行 — 为什么数字经常错误、重复或丢失以及为什么解析器不应该信任它们

索引号被读取然后被忽略。真实文件编号提示从零开始,合并后重新编号,手动编辑后复制数字,或者在转换器写入文件时完全省略该行。信任这些数字意味着继承每一个错误,因此解析器会分配自己的序列号,计算迄今为止已成功构建的线索。

该选择也解释了为什么解析器从不要求存在索引行。它通过在块中搜索包含箭头的第一行来定位时间码行,而不是假设时间码是第二行。没有索引行的块会正常解析,而时间码之前有两个杂散行的块仍然会解析,因为位置不是标识时间码的内容。

时间码行 — HH:MM:SS,mmm --> HH:MM:SS,mmm,可容忍的变化和破坏玩家的变化

时间码行与单个正则表达式匹配,并且其中的容差是经过深思熟虑的。时间是可选的,因为 WebVTT 允许两个字段的读数并且转换器会发出它。无论文件声称采用哪种格式,都接受逗号或句号作为毫秒分隔符,因为混合分隔符很常见,拒绝它们会导致更多好的文件失败而不是坏的文件。小数位填充在右侧,因此以一位数结尾的提示会被读取为数百毫秒而不是单位。

两次读数被拒绝。超过五十九分或秒的字段将被拒绝而不是携带,因为九十秒不是时钟读数,通常表示文件已损坏或转换错误;默默地将其标准化会移动提示。开头或结尾无法解析的行会生成一个记录的问题,命名有问题的文本和预期的形状,并且该块将被跳过而不是猜测。

文本行 — 多行提示、格式化标签以及块真正结束的位置

时间码行之后的所有内容都是提示文本,与换行符重新连接在一起。没有行数限制,也不会尝试重排,因此三行提示将保留为三行。这就是空行是承载的原因:它是唯一告诉解析器文本已经结束的东西,这就是为什么自己的文本包含空行的提示将被读取为两个块,而后半部分将被报告为没有时间码。

提示设置与结束时间戳之间由两个或多个空格分隔。 WebVTT 允许定位指令(例如对齐和行放置)遵循同一行的结束时间,因此解析器在解析时间戳之前将它们分开,并将它们保留在提示旁边。单个空格不是分隔符,它可以防止杂乱的时间码行丢失其结束时间。

工作示例:解析具有两个故意错误的五个提示文件 - 强大的解析器恢复什么以及它标记什么

取一个五块文件,其中块三的时间码行已损坏,无法读取 00:01:75,000 --> 00:01:78,000,而块四在复制和粘贴过程中完全丢失了其时间码行。解析器正常读取块一和块二,并将它们编号为一和二。第三块与时间码的形状匹配,但带有 75 秒字段,因此它被拒绝并记录为错误的时间戳,命名它无法读取的行。

块四根本不包含箭头,因此它被记录为没有时间戳,引用该块的前四十个字符,以便可以在原始文件中找到该行。块五解析并成为提示三,而不是提示五,因为编号会计算成功的提示。结果是三个可用的提示和两个具体的、已定位的投诉,而不是第一个故障出现异常并且没有关于第二个故障的信息。

这不包括 - ASS/SSA 样式、定位代码和非字幕文本转储到 SRT

这描述了 SRT 以及共享其提示形状的 WebVTT 部分。它不包括 ASS 和 SSA,它们带有脚本头、样式定义和每个事件的样式引用,并且不能通过在空行上拆分来读取。这些格式使用的卡拉 OK 计时、绘图命令和内联覆盖标签超出了提示和时间码解析器模型的范围。

它也不修复文本。粘贴到没有时间码的文件中的脚本会生成没有时间戳的块列表,该列表可以准确报告,但如果没有不存在的计时信息,则无法将其转换为字幕。编码错误是一个单独的问题:使用错误的字符集解码的文件会解析为完全有效的提示,但其文本是错误的,并且任何结构检查都无法检测到这一点。

要点:宽松解析,严格编写 — 字幕工具包如何读取混乱的 SRT 并写回干净的内容

工作规则是宽解析、严书写。在进入过程中,接受可选的时间、分隔符、缺少索引行、混合行结尾和前导字节顺序标记,并将每个错误记录为已定位问题,而不是抛出第一个错误,因此可以一次性修复文件。在退出时,发出一种规范形状。

这就是字幕工具包在转换时所做的事情。提示从 1 开始重新编号并保持连续,时间戳以 SRT 的逗号和 WebVTT 的句号重新发出,返回的文件是玩家期望的形状,无论输入多么不规则。将玩家拒绝的文件粘贴到转换器中,并首先阅读报告的问题;他们命名提示并引用台词,这通常足以找到原作中的错误。