track元素必须嵌套在video或audio内部,且紧随source之后;kind、srclang、label三属性缺一不可,src需CORS合规,vtt文件须UTF-8无BOM并符合WEBVTT语法规范。

track 元素必须嵌套在 video 或 audio 内部才生效
直接把 <track></track> 放在 或独立位置,浏览器完全忽略它——这不是 bug,是规范强制要求。它不是独立资源加载器,而是媒体元素的「附属轨道控制器」。
常见错误现象:<track src="sub.vtt"></track> 单独写在页面里,控制台没报错但字幕死活不显示。
- 必须作为
<video></video>或<audio></audio>的子元素(不能是兄弟节点) - 父媒体元素需有
controls属性,否则即使加载成功也无法手动开启字幕 - 若用 JavaScript 动态添加
<track></track>,需确保插入到媒体元素内部且调用load()重载资源
src 路径必须可跨域访问,且响应头允许 CORS
浏览器对 <track></track> 的 src 执行严格 CORS 检查。哪怕本地文件双击打开(file:// 协议),也会因缺少响应头被静默拦截。
典型错误信息:Failed to load resource: Origin null is not allowed by Access-Control-Allow-Origin
立即学习“前端免费学习笔记(深入)”;
- 开发阶段务必用本地服务器启动(如
python3 -m http.server、live-server或 Vite) - 如果字幕托管在 CDN 或第三方域名,服务端必须返回
Access-Control-Allow-Origin: *(或指定域名) -
vtt文件本身不能有 BOM 头,否则 Safari 可能解析失败
kind、srclang、label 属性缺一不可,否则字幕菜单不出现
仅靠 src 不足以让字幕出现在播放器的字幕选择菜单里。浏览器依赖这三个属性协同识别轨道用途和语言。
错误写法:<track src="zh.vtt"></track> → 菜单里根本看不到该轨道
-
kind="subtitles"是最常用值(其他还有captions、descriptions等,语义不同) -
srclang="zh"必须是合法 BCP 47 语言标签(如en、zh-Hans、ja),大小写敏感 -
label="中文"是用户看到的菜单名,建议用简短可读文字,不要留空或用路径名
正确示例:
<video controls><br> <source src="movie.mp4"><br> <track kind="subtitles" srclang="zh" label="中文" src="zh.vtt"><br></video>
WebVTT 格式稍有语法错误,整个轨道就会静默失效
不同于 HTML 容错强,.vtt 文件只要时间戳格式错一位、漏一个空行、或用了中文标点,Chrome/Firefox 就会跳过加载,且不报任何错误。
容易踩的坑:00:00:01.234 --> 00:00:04.567 中用了全角冒号或破折号;文本块开头多了空格;最后一行没空行。
- 用在线验证工具检查:https://quuz.org/webvtt/(粘贴内容即可)
- 时间戳必须为
HH:MM:SS.mmm格式,毫秒三位,不能少也不能多 - 每段字幕之间必须有空行,第一行必须是
WEBVTT(无 BOM,无空格) - 避免在字幕文本中使用
<b></b>以外的 HTML 标签(<span></span>、<div> 均无效) <p>真正麻烦的地方在于:所有问题都表现为「字幕不出现」,但控制台安静得像没这事——得逐项核对 DOM 结构、网络请求状态、vtt 语法、CORS 响应头,缺一不可。</p> </div>



















