使用翻译和时间序列算法同步字幕





5.00/5 (9投票s)
将字幕同步从一个字幕文件传输到另一个字幕文件
Codeplex: https://robosubsync.codeplex.com/
简介
我时不时会产生一个想法,这个想法让我无法忘怀……
这个程序就是从这样一个想法开始的,并发展成了一个完全不需要与实际电影互动即可工作的字幕同步工作室。听起来很奇怪?继续阅读。
背景
这个想法大致是这样的:你有一部电影,还有你选择语言的字幕,但你发现它与你下载的电影版本不同步。这可能发生在电影很老、很新,甚至有时应该与同一版本同步的字幕实际上不同步的时候。
通常还会有一个英文(或其他语言)的同步字幕。自动翻译它显然是个坏主意,但你可能会想,如果你有一个同步的字幕和一个语言字幕,总会有某种方法可以提取同步信息并转移它,从而创建一个好的字幕版本——现在,看我的下一个把戏,我将做到这一点,而你——抓点爆米花……
除了帮助解决同步问题外,这种方法还可以帮助(在已有英文版本的情况下)首先将字幕同步到多个视频版本,这目前是一项相当繁琐的工作。
为了比较这两个字幕,我们需要将它们转换成同一种语言。谷歌翻译是我首先想到的,所以我的第一个版本只是将翻译好的字幕复制进去,然后输出英文。之后,匹配行只是编写代码的事。我的初步结果非常令人鼓舞,我继续实现了几种算法和方法,以改进结果并让你更好地控制最终结果。
后来我玩了一下微软的翻译,并使其自动化。如果你想使用它,请阅读链接文章的开头,并注册微软翻译。
用户指南
自动同步字幕(简而言之)
- 在第一个文本框中输入英文 .srt 文件的路径
- 在第二个文本框中输入语言 .srt 文件的路径
- 选择你的语言 srt 文件的正确编码
- 按添加翻译(如果你已注册微软翻译,请在 MS translation config 扩展器中输入密码,然后跳至第 7 步)
- 打开 str 文件,将内容复制到谷歌翻译中(检查翻译是否已完成至文本末尾)
- 在打开的窗口中输入你的 srt 内容的谷歌翻译英文翻译
- 关闭翻译窗口
- 点击 AutoSync
- 点击 Save Srt File(右下角)
- 尽情享用!
有很多选项,通过调整它们可以获得比让程序自动处理更好的结果。
这里实际发生的是:
- 翻译后的行与英文(已同步)字幕进行模糊匹配
- AutoSync 按钮尝试多个值,并使用产生最多行匹配的值。
- 创建基线(蓝线)
- 任何异常的匹配(离基线太远)都会被丢弃。
- 绘制行和基线
- 按下保存按钮
- 语言字幕行根据匹配行线进行校正
- 修复后的 srt 文件将保存到磁盘,名为 fixed_
.srt
图中的线
- 同步差值(紫色) - 该图中的每个点代表一个匹配,其值为(同步字幕时间 - 语言字幕时间),将其添加到语言字幕中将校正它以与视频同步。
- 基线(蓝色) - 由基线算法创建的移动基线类似于移动平均线,用于剔除异常值,去除大部分不正确的匹配。
- 阶梯线(橙色) - 此算法基于电影版本存在不同的商业广告休息时间,或者其中一个版本由几个部分组成,它试图找到同步差值恒定的阶梯,然后跳到另一个恒定级别。
- 线性回归线(绿色) - 与所有点距离最小的直线,如果同步差值以恒定速度增长(+ / -),则此线将接近紫色匹配线。(例如,当帧率不同时)
参数部分
这些部分中的大多数参数都需要你按“更新图”来应用更改,然后将重新计算和重绘图表。
- 行匹配参数 - 提供对模糊匹配算法的控制,包括匹配所需的相似度百分比、最小字母数和搜索提前松弛空间。
- 基线参数 - 允许你调整基线的创建方式,是否用于移除异常点,以及一个点需要多远才算异常(正常区域以标准差衡量)。
- 微软翻译配置 - 存放 MS 注册信息的地方,如果你有的话(它是免费的)
- 阶梯线参数 - 允许你微调阶梯线,包括尝试创建的阶梯数,以及在进入下一个阶梯之前似乎属于下一个阶梯的点数等等。
- 修复保存字幕 - 在这里你可以选择哪条线用于修复字幕,包括原始线(同步差值)、基线、阶梯线和回归线。
实时编辑:
另一个选项是手动修复同步差值线,根据你自己的差值估算。为了适应这种用法,我增加了拖动同步差值线顶点上下移动的能力。在拖动过程中,工具提示将显示两条线(英文和本地语言),以便你判断匹配度。
如果这两条线看起来不匹配,将点拖回到其邻居形成的斜坡中将消除其对同步的影响。
图表导航
- 该图表基于DynamicDataDisplay项目,可以使用鼠标平移,使用滚轮或 +/- 键缩放,右键单击它会显示一个有用的菜单。
- 如果图表缩放失真,按键盘上的“Home”键将恢复到初始位置。
代码
代码的某些部分被反复重构,直到我找到了一个简单的方法来处理行数据,从而消除了对行的担忧。
SampleCollection 是一个表示同步校正线的类,它包含匹配点,并且可以应用算法来计算新线(返回一个新的 SampleCollection 实例),这使你能够创建计算链而无需担心影响。它还可以将其数据传输到图表的 DataSource 以便显示。
BingTranslator - 封装了对微软翻译服务的调用。
MainVM - 主窗口的 ViewModel,包含大部分逻辑,以及大量的可观察属性……(一个好的起点是 SyncSubtitles)
LineInfo - 表示字幕中的一行(有时一个 TimeStamp 包含两三行)
TimeStamp - 包含字幕时间以及一系列行
SubtitleInfo - 表示一个字幕文件及其所有内容(时间和行),还可以加载和保存 srt。
Baseline - 用于基线算法的类。(由 SampleCollection 使用)
算法
这里使用了几种算法:
模糊匹配:这是我为了完成工作而想出的方法:
- 尝试将一行与其对应行进行匹配
- 对于翻译后的字幕行中的每个单词
- 如果包含在已同步的行中
- count += 单词字母数。
- 计算字母命中率等。
- 检查匹配是否符合阈值,以确定它是否是一个好的匹配:
- 如果匹配,则在两个字幕中前进到下一行
- 如果不匹配,则在翻译的字幕中前进一行,然后重试(创建偏移)
- 切换字幕,尝试将翻译后的作为固定字幕。
- 选择具有最多行匹配的匹配。
基线算法:通过一种自适应平均算法完成,该算法将先前达到的平均值作为新平均值的一部分,其余部分作为剩余部分,nextAvg = [alpha*avg + (1-alpha)*newPoint]。因此,alpha 决定了算法跟随差值线的接近程度。
步进检测算法:使用聚类(k-means)来查找具有相似 y 轴的点簇
- 将最高 Y 值和最低 Y 值之间的空间划分为 K+1(可配置)相等的部分
- 使用这些 K 条线初始化均值向量
- 直到 [均值向量无变化]:
- 对于每个点
- 找到最近的均值
- 添加到最近的均值累加器
- 增加最近均值的计数
- 对于每个均值:(更新均值)
- mean = meanAccumulator / meanCount
现在每个均值(= 水平线)应该已经与最近的阶梯对齐了。
为了创建阶梯线,我们现在需要决定何时从一个阶梯移动到下一个阶梯,这是通过遍历点来完成的,并且当我们看到 X 个属于下一个簇的点时决定进行阶梯。 (在这里我们可以要求点是连续的,从而在数据混乱时使用更严格的方法)
线性回归是通过简单的最小二乘线性回归算法完成的。
未来工作
我在此程序的待办事项列表中有一些改进和功能:
- 可以从 OpenSubtitles 等网站自动下载英文字幕。
- 可以使用自动编码检测(这里有一篇很好的文章)
- 支持 .sub 文件(最简单的方法是编写一个子转 srt 的例程,它接收帧率)。
- 目前此程序仅支持 srt 文件,其他流行格式可以转换为 srt。
- 支持非英语语言作为通用语言(例如,将两个字幕都翻译成英语,或者将语言字幕翻译成另一种通用语言)。
- 添加命令行界面或批处理支持,用于自动同步多个字幕。
- 封装可编辑图表组件
结论
我喜欢偶尔挑战一下,而这次挑战很有趣。我认为这可以极大地造福字幕创作者,以及像我一样,偶尔遇到不同步字幕的人。
请在下面的评论中告诉我你的想法,以及你希望在下一个版本中看到什么。
如果你喜欢这个程序,并希望为其做出贡献,你可以将更改提交到RoboSubSync codeplex 存储库。