video元素通过加载.vtt字幕,需确保webvtt文件首行为webvtt、utf-8无bom、服务器返回text/vtt mime类型,且为子元素。

video 元素怎么加载 .vtt 字幕文件
HTML 原生支持字幕,但必须用 <track></track> 标签配合 <video></video>,且字幕文件格式只能是 WebVTT(.vtt),不是 SRT 或其他格式。直接把 SRT 当成 VTT 用会失效——浏览器解析失败,控制台报 Failed to parse WebVTT file。
实操要点:
-
<track></track>必须作为<video></video>的子元素,不能放在外面; -
kind="subtitles"是必需属性,别写成caption(那是为听障设计的,样式和触发逻辑不同); -
srclang必须是合法 BCP 47 语言码,比如zh、en、ja,写ch或cn会导致字幕不显示; -
default属性只允许一个<track></track>设置,否则无效; - 路径必须可访问:如果
src是相对路径,需确保服务器能返回text/vttMIME 类型,否则 Chrome 会静默忽略(无报错但不加载)。
WebVTT 文件开头必须有合法 header
VTT 文件不是纯文本时间轴,第一行必须是 WEBVTT(大小写敏感,后面可跟空格或注释,但不能换行或加空行)。常见错误是复制 SRT 内容后直接改扩展名,结果第一行是 1 或空行,导致整个文件被跳过。
正确示例(保存为 sub.vtt):
WEBVTT 00:00:01.000 --> 00:00:04.000 你好,这是第一句字幕。 00:00:05.000 --> 00:00:08.000 第二句字幕在这里。
注意:两个空行之间不能有多余字符(包括 BOM),UTF-8 编码无 BOM 最稳妥;时间戳格式必须是 hh:mm:ss.mmm,不支持 ss,mmm 或省略小时。
JavaScript 动态切换字幕 track 时容易失效
通过 JS 修改 track.mode 是唯一可控方式,但直接设 "showing" 不一定立即生效——前提是该 <track></track> 已加载完成且无解析错误。常见坑:
- 在
video的loadedmetadata事件之后再操作track.mode,避免 DOM 存在但轨道尚未就绪; - 不要用
track.hidden = false,这个属性只读; - 多个
<track></track>同时设mode = "showing",只有最后一个生效; - 如果字幕没出现,检查
track.readyState:0=not loaded,2=loaded,不是 2 就别设 mode。
移动端 Safari 字幕支持有限制
iOS Safari(直到 iOS 17)不支持内建字幕渲染,即使 <track></track> 正确,也不会显示——这是 Apple 的策略限制,不是代码问题。替代方案只有自己实现 overlay 字幕层(用 <div> + <code>video.currentTime + 定时匹配),或者用第三方播放器如 Video.js。
Android Chrome 和桌面端主流浏览器(Chrome/Firefox/Edge)均支持原生 <track></track>,但务必测试实际设备,尤其企业内网环境可能禁用某些 MIME 类型或跨域策略影响 .vtt 加载。
最常被忽略的是服务器配置:.vtt 文件必须响应 Content-Type: text/vtt,Nginx 默认不识别,需手动加 types { text/vtt vtt; };Apache 则要确认 AddType text/vtt .vtt 已启用。











