SRT 转 WebVTT
把 SRT 字幕转成 WebVTT,让 HTML <video> 真的显示得出来。全部在浏览器里完成,并说明文件头、逗号、MIME 类型与编码这四个坑。
在你的浏览器中运行
负值表示字幕提早出现。会被推到零之前的字幕会停在零,不会被丢掉。
没有带过去的东西
解析与输出都在你的浏览器里完成,文件不会上传。
为什么非转不可
浏览器不读 SRT。<track> 元素只接受一种字幕格式,就是 WebVTT,其他一律忽略——而且是无声无息地
忽略,控制台不会有错误,画面上也看不出哪里不对。影片播得好好的、字幕就是不出来,几乎都是这件事。
两种格式想做的事其实一样,所以「把副档名改掉」才会让人觉得应该可行。它不可行,理由有三个:
| SRT | WebVTT | |
|---|---|---|
| 第一行 | 数字 1 | WEBVTT 这个字 |
| 时间戳 | 00:01:02,500 | 00:01:02.500 |
| 字幕编号 | 每一条都有 | 不使用 |
把文件贴到上面,或用选档按钮挑一个,就会得到 .vtt。没有任何东西被上传。
那行文件头不是装饰
一个 WebVTT 档如果开头不是 WEBVTT,它就不是 WebVTT 档,规格要求浏览器当场停止解析。转好的文件
还是什么都不显示,最常见的原因就是这个。
逗号是另一半。00:00:01,000 在 WebVTT 里是解析错误,而一个坏掉的时间戳只会弄死它自己那一条
字幕,不会弄死整个文件——所以手动改过的文件可能只少几句话、其他都正常,这比整份不显示难发现
得多。
挂到影片上
<video controls crossorigin="anonymous">
<source src="film.mp4" type="video/mp4" />
<track kind="subtitles" src="film.vtt" srclang="zh-Hant" label="中文" default />
</video>
文件本身没问题,还有三件事会让它失败:
- 要以
text/vtt提供。 服务器把.vtt当成application/octet-stream或text/plain送 出去,这条轨就会被拒绝。text/vtt才是注册过的类型。 file://不行。<track>受同源政策管辖,而直接从硬盘开启的页面过不了。随便一个本机 服务器就够了。- 跨域名要两边都做。 字幕放在别的域名,需要那个域名回
Access-Control-Allow-Origin,而且<video>要加crossorigin。只做一边等于没做。
default 决定字幕默认开启;没有它,观众得自己去播放器菜单里找,而大多数人不会去找。
编码——中文字幕踩得最惨的一个坑
WebVTT 档一定要是 UTF-8。 规格里没有编码宣告,也没有退路——你没有办法在文件里写「我是 Big5」。
SRT 没有这条规定,所以外面流通的 SRT 是当初存档那台机器用什么就是什么:Big5、GB18030、
Shift-JIS、Windows-1252。从论坛抓来的中文字幕档非常可能是 Big5,逐字节转过去,会得到一个格式
完全合法、内容全是乱码的 .vtt。
这个页面以 UTF-8 读取文件。如果上面的预览已经是乱码,那就是原档不是 UTF-8,再怎么转都不会 好——先用能选编码的文字编辑器另存成 UTF-8,再回来转。
这趟转换改变了什么
几乎什么都没改,这正是重点。时间精确到毫秒完全一致,文字原样搬过去,<i>、<b>、<u> 在两种
格式里写法相同,会活下来。
字幕编号会被拿掉,因为 WebVTT 不用。cue 识别码——时间行上面那个选填的名字——也会拿掉,因为除了 WebVTT 自己的 CSS 之外没有东西会读它。
反过来转一样不会掉东西,只有 align:start position:10% 这类 cue 设定例外,因为 SRT 根本没有
「位置」可言。