video标签中track必须作为其直接子元素且紧接在所有source之后,否则浏览器静默忽略;kind、srclang、label三属性缺一不可,src须为合法URL且服务端返回text/vtt MIME类型。

video标签里必须嵌套track,不能放外面
直接把 <track></track> 写在 <video></video> 外面,浏览器会完全忽略它——不报错、不警告、字幕就是不出。这是规范强制要求,不是兼容性问题。
正确结构只有一种:<video></video> 开始后、 之前,且必须在所有 <source></source> 之后(顺序错也可能导致 Safari 不识别)。
-
<source></source>负责告诉浏览器“视频在哪、用什么解码”,<track></track>是附加轨道,必须依附于已声明的媒体资源 - 多个
<track></track>可并列,但每个都得独立写在<video></video>内部 - Vue 或 React 中用动态绑定时,也要确保最终渲染出的 DOM 结构满足这个嵌套关系,不能靠 JS 把
<track></track>插到<video></video>外层容器里
src 必须是可访问 URL,Blob 或 data URL 一律无效
<track src="..."></track> 的 src 值不支持 blob: 或 data: 协议,浏览器会静默跳过加载——控制台连 404 都不会报。
开发时常见踩坑点:
实现 Markdown↔ HTML 互转,支持导出 PDF,用于用户请求的文档格式转换。
立即学习“前端免费学习笔记(深入)”;
- 本地双击 HTML 文件(
file://协议),Chrome/Firefox 会因 CORS 拒绝加载同目录下的.vtt;必须起本地服务,比如python3 -m http.server - 字幕内容由 API 动态返回?别试图把文本塞进
src,得先用URL.createObjectURL(new Blob([text], {type: 'text/vtt'}))创建 URL,再赋给track.src(注意:这仍是合法 URL,不是 blob 协议) - 服务器部署后 404?检查路径是否相对于 HTML 文件位置,而不是相对于 JS 执行位置
WebVTT 文件格式错一个字符,整份字幕就失效
浏览器对 .vtt 文件格式极其敏感,不是“大致能读”,而是“全或无”解析。常见失效原因:
- 文件开头缺
WEBVTT(必须全大写,后面跟换行,再空一行) - 时间戳毫秒位不是三位,比如
00:01:02.5→ 应为00:01:02.500 - 箭头
-->前后没空格,或用了中文符号 - 文件保存带 BOM(尤其 Windows 记事本默认),Firefox 会显示空白或乱码;务必用 VS Code、Sublime 等设为 “UTF-8 without BOM”
- 写了
<b></b>或<i></i>?WebVTT 不解析 HTML 标签,只会原样输出文本,要样式得用::cueCSS
default 属性只管初始状态,切换语言必须用 JavaScript
HTML 里写多个 <track default></track> 没用,浏览器只认第一个;用户点击播放器字幕菜单切换语言,本质是修改 track.mode 值。
真正可控的方式是 JS:
- 给每个
<track></track>设唯一id和正确srclang(如zh、en) - 切换时遍历
video.textTracks,把目标 track 的mode设为"showing",其余设为"disabled" - Safari 默认隐藏字幕菜单,即使写了
default,也得靠 JS 主动触发track.mode = "showing"才可见 - 注意:
mode改变后,浏览器不会自动滚动到当前时间点对应的字幕 cue,如需精确同步,得监听timeupdate自己匹配
text/vtt。Nginx/Apache 若没配,Chrome 会加载失败但不提示,DevTools Network 面板里看响应头 Content-Type 就能确认。


















