尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Lingarr字幕解析器源码解读:SRT与SSA解析/写入的完整实现原理

Lingarr字幕解析器源码解读:SRT与SSA解析/写入的完整实现原理 Lingarr字幕解析器源码解读SRT与SSA解析/写入的完整实现原理【免费下载链接】lingarrLingarr is an application that supports both local and SaaS translation services to translate subtitle files into a specified target language. With automated translation options, Lingarr simplifies translating subtitles.项目地址: https://gitcode.com/gh_mirrors/li/lingarrLingarr 是一款支持本地与 SaaS 翻译服务的字幕翻译工具而它最核心的地基就是内置在Lingarr.Server/Services/Subtitle/目录下的字幕解析器与写入器。无论是 SRT 还是 SSA/ASS 格式Lingarr 都要先把字幕文件解析成统一的SubtitleItem对象翻译完成后再按原格式写回。本文带你逐层拆解 Lingarr 字幕解析器的完整实现原理看看它是如何在毫秒级时间轴上完成读取→清洗→翻译→写回的全流程。Lingarr字幕解析器整体架构一条流水线打通两种格式Lingarr 没有为每种格式写死逻辑而是定义了统一接口让上层代码完全不用关心文件格式ISubtitleParser负责把字幕流解析成ListSubtitleItem接口定义见 ISubtitleParser.csISubtitleWriter负责把翻译后的字幕对象异步写回流接口定义见 ISubtitleWriter.csSubtitleItem统一的数据载体包含序号Position、毫秒级起止时间StartTime/EndTime、原始行Lines、纯文本行PlaintextLines和翻译行TranslatedLines定义见 SubtitleItem.cs。调度层在 SubtitleService.cs 中通过扩展名路由.srt交给SrtParser/SrtWriter.ssa/.ass交给SsaParser/SsaWriter。这意味着翻译引擎拿到的永远是同一种对象格式差异被完全隔离在解析器内部。SRT字幕解析原理详解逐块读取与时间轴容错SRTSubRip格式结构简单序号行、时间码行、若干文本行、空行分隔。SrtParser的解析策略非常稳健1. 按块累积用序号识别边界解析器逐行读取非空内容当读到一行纯数字、且当前块的首行也是数字时就判定这是一条新字幕的开始于是把上一块送进TryParseBlock处理。这种数字对数字的判断方式比依赖空行更宽容能应对空行缺失的畸形文件。2. 时间码解析兼容逗号与小数点SRT 时间码形如00:00:01,000 -- 00:00:04,500而SrtParser用正则TimeCodeRegex解析并做了两个贴心处理毫秒分隔符兼容正则里[,\.]同时接受逗号和点号某些工具导出的00:00:01.000也能正常解析毫秒位数补齐01会被PadRight(3,0)补成010毫秒不会出现 1 毫秒被当成 10 毫秒的错误防呆校验分钟和秒超过 59 直接判为非法如果结束时间早于开始时间还会自动交换避免脏数据污染后续翻译。3. 文本清洗与纯文本双通道每条字幕同时保留原始行含{\an8}、i等标记和清洗后的纯文本行供翻译引擎使用这样翻译完成后还能尽量还原原始样式。核心清洗逻辑RemoveMarkup的源码在 SubtitleFormatterService.cs稍后单独展开。SRT字幕写入原理毫秒转时间码的格式化艺术SrtWriter的写入逻辑集中在 SrtWriter.cs核心技巧有两点TimeSpan 格式化把毫秒整数转成TimeSpan后用{start:hh\:mm\:ss\,fff}输出标准 SRT 时间码逗号需要转义确保输出永远是00:00:01,000 -- 00:00:04,500的规范形态序号复用原位置写入时直接使用subtitleItem.Position作为条目序号保证经过解析→翻译→写回后字幕编号不乱。写入采用异步WriteLineAsync流式输出条目之间补一个空行符合 SRT 规范播放器都能正确识别。SSA/ASS字幕解析原理详解分区状态机与列映射SSA/ASS 比 SRT 复杂得多文件由[Script Info]、[V4 Styles]、[Events]等分区组成且 Dialogue 行是逗号分隔的表格结构。SsaParser用状态机 列索引两招化解1. 分区状态机解析器维护currentSection变量读到[开头的行就切换当前分区。不同分区走不同分支[Script Info]收集元信息并解析WrapStyle换行模式[V4 Styles]原样收集样式[Events]则是重头戏。2. Format 列映射Text 字段只取不拆[Events]下的Format:行定义了列顺序Marked, Start, End, Style, Name, MarginL/R/V, Effect, Text解析器把它建成列名→索引字典。关键难点是Text 字段本身可能包含逗号如{\pos(100,200)}所以ParseDialogueLine用了FindTextFieldStart逐字符数逗号来定位 Text 起始位置绝不整体Split(,)这部分实现见 SsaParser.cs。3. 兼容老版 Aegisub 的缺列容错有些老工具导出的 ASS 会省略 Layer 列解析器会尝试少一列再定位 Text若成功则自动补一个默认 Layer 值0保证下游列索引不错位非常贴心。4. WrapStyle 换行规则ASS 的换行符有\N和\n两种含义取决于WrapStyle枚举见 SsaWrapStyle.csSmart/EndOfLine模式只认\NNone模式则两种都视为换行。解析器会按此规则把整行文本拆成多行字幕文本。SSA/ASS字幕写入原理样式保留与格式剥离双模式SsaWriter的写入策略体现了对粉丝字幕组的尊重完整保留模式原样写回[Script Info]、[V4 Styles]和每条 Dialogue 的 Marked/Style/Margin/Effect 等字段翻译后的文本用\N重新拼接见 SsaWriter.cs格式剥离模式当用户勾选去掉字幕格式时会生成精简的[V4 Styles]优先复用源文件的Style: Default保留下载站的字号字号设定找不到时则按PlayResY动态计算字体大小约为画布高度的 1/15288 高度≈19px1080 高度≈72px并强制所有 Dialogue 使用 Default 样式、清空 Effect输出干净统一的效果。字幕标记清洗原理RemoveMarkup 的层层过滤翻译前必须把样式标记从文本中剥离RemoveMarkup的过滤顺序很有讲究源码见 SubtitleFormatterService.cs先剔除 ASS 绘图块{\p1}...{\p0}这类矢量绘图数据一旦混入翻译会直接污染结果再删{...}样式标签如{\an8}、{\pos(...)}接着删...HTML 风格标签如i、font把\N、\n、\h、\t等转义符统一替换成空格合并多余空格后最后用矢量前缀正则^[mlcbsn]...识别以绘图命令开头如m 0 0 l 100 100的行直接置空丢弃。这套先绘图、后标签、再转义、末过滤的顺序保证了送给翻译引擎的永远是干净可读的纯文本。✨容错机制总结为什么 Lingarr 能扛住脏字幕综合四个解析/写入类的实现Lingarr 字幕解析器的健壮性来自层层防御流不可读或不可定位时直接拒绝ValidateStream解析失败不抛异常中断而是记录日志返回空列表让上层业务继续SRT 起止时间倒挂自动交换、SSA 缺 Layer 列自动补零空文件、无有效字幕时给出明确的FormatException提示解析后PlaintextLines与Lines双轨保存翻译失败也能回退原始文本。结语从 SRT 的逐块解析到 SSA 的列映射状态机Lingarr 用清晰的接口分层和缜密的容错细节把两种风格迥异的字幕格式统一成了同一条翻译流水线。无论你是想为 Lingarr 贡献新的字幕格式支持还是想在自己的工具里实现类似能力这份源码都是极佳的参考范本。相关代码集中位于Lingarr.Server/Services/Subtitle/与Lingarr.Server/Models/FileSystem/配合 SsaParserTests.cs 等测试用例可以快速验证你对解析逻辑的理解。【免费下载链接】lingarrLingarr is an application that supports both local and SaaS translation services to translate subtitle files into a specified target language. With automated translation options, Lingarr simplifies translating subtitles.项目地址: https://gitcode.com/gh_mirrors/li/lingarr创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表