必须写全kind、srclang、label、src四个属性,缺一则静默失效:kind须为subtitles等严格小写值,srclang需合法BCP 47码,label不能为空,src路径须可访问且服务端返回text/vtt MIME类型。

track 元素必须写的四个属性
漏掉任意一个,浏览器就当它不存在——不会报错,也不会出现在字幕菜单里,静默失效。
-
kind:必须是subtitles、captions、descriptions、chapters或metadata之一,全小写、无空格、拼写严格匹配;写成caption或subtitles(末尾空格)都会被忽略 -
srclang:仅对subtitles和captions有效,值必须是合法 BCP 47 语言标签,如zh、en-US、ja;chinese、zh_CN、空字符串均无效 -
label:用户在播放器右键菜单或「CC」按钮里看到的名称,不能为空;建议带括号注明变体,比如中文(简体),否则多个中文轨道无法区分 -
src:指向 .vtt 文件的路径,必须可访问;若跨域,服务端需返回Access-Control-Allow-Origin: *,否则 Firefox/Edge 直接不加载,video.textTracks里也看不到
default 属性的使用边界
它只影响页面首次加载时的默认状态,不是“永久启用”,也不是“用户偏好锁定”。
- 只能在一个
<track></track>上设置,多个default会导致行为未定义(Chrome 通常只认第一个,Safari 可能全忽略) - 设了
default的轨道,加载后track.mode初始为'showing';但用户一旦手动切换到其他轨道,刷新页面也不会自动切回来 -
chapters类型不应加default,否则部分浏览器(如 Safari)会拒绝解析后续<track></track> - 移动端 iOS Safari 要求
<video></video>同时带controls属性,否则即使有default,字幕菜单也不出现
WebVTT 文件与 src 路径的实际约束
src 指向的 .vtt 文件,光路径对还不行,文件内容和服务端响应都得过关。
- .vtt 文件首行必须是
WEBVTT(不区分大小写,但前后不能有空格或 BOM),否则 Chrome 解析失败,控制台可能只报 “Failed to parse WebVTT file” - 时间格式必须是
HH:MM:SS.mmm --> HH:MM:SS.mmm,毫秒必须三位;写成00:01:02.1 --> 00:01:05.12(位数不齐)会被 Safari 静默跳过整段 - 文件必须 UTF-8 无 BOM 编码;用 VS Code 保存时选 “UTF-8” 而非 “UTF-8 with BOM”,否则中文显示为乱码或完全不加载
- 服务端需返回正确的 MIME 类型:
text/vtt;Nginx/Apache 若没配,Firefox 会拒绝加载(即使路径正确)
常见错误现象与快速定位方式
字幕不显示?先别改 JS,直接查 DOM 和网络请求——90% 的问题出在这几步。
立即学习“前端免费学习笔记(深入)”;
- 打开 DevTools → Elements 面板,确认
<track></track>确实在<video></video>开始标签之后、所有<source></source>闭合之后、之前;插在中间或包在<div> 里等于没写 <li>Network 面板过滤 <code>vtt,看对应文件是否发起请求;没请求说明 HTML 结构或src路径错了;请求 404 是路径问题;请求 0B 响应或 status 200 但内容为空,大概率是 BOM 或编码问题 - 控制台执行
document.querySelector('video').textTracks,长度为 0 表示浏览器根本没识别到任何<track></track>;长度 > 0 但mode === 'disabled',说明属性齐全但没设default或用户手动关了 - 右键视频 → 「字幕」菜单里没有选项?立刻检查
kind、srclang、label是否全部存在且合法——缺一不可
真正麻烦的不是写不对,而是写对了但浏览器不声不响地跳过——因为
<track></track> 的容错性几乎为零,每个环节都卡得死紧。



















