track字幕生效需同时满足四个条件:结构上track必须紧邻source之后且在video内;vtt文件须为utf-8无bom、首行webvtt、空行分隔、时间戳规范;服务端返回text/vtt mime类型及正确cors头;kind、srclang、label属性缺一不可。

track 标签加字幕不是“加了就行”,而是必须满足四个硬性条件:位置对、格式对、编码对、服务端配置对。缺一不可,否则字幕静默失效——浏览器既不报错,也不显示。
track 标签必须紧挨 source 之后、且在 video 内部
这是最常被忽略的结构陷阱。浏览器只认一种顺序:video → 一个或多个 source → track → /video。任何偏差都会导致字幕完全不加载:
- 把
track放在source前面:不生效 - 把
track写在video外面(比如父容器里):不生效 - 多个
track之间混入其他标签(如div或注释):部分浏览器会中断解析
正确写法示例:
<video controls><source src="movie.mp4" type="video/mp4"><track kind="subtitles" srclang="zh" label="中文" src="zh.vtt" default></track></source></video>
WebVTT 文件必须严格符合语法和编码规范
浏览器对 .vtt 文件极其挑剔,哪怕一个空格或 BOM 头都会让整份字幕失效:
- 首行必须是
WEBVTT(全大写,无空格,无 UTF-8 BOM) - 第二行必须为空行
- 每段字幕以数字编号开头,后跟时间戳(
00:00:02.000 --> 00:00:05.000),再空一行,再写文本 - 文件必须保存为 UTF-8 无 BOM 编码(用 VS Code、Notepad++ 等可明确设置)
- 禁止使用 Windows 换行符(CRLF)以外的变体;推荐统一用 LF
错误示例(常见于从 SRT 转换未清理):WEBVTT(开头带 BOM)、webvtt(小写)、缺少空行、时间戳毫秒位不足三位。
服务器必须返回正确的 MIME 类型和 CORS 头
即使 HTML 和 VTT 都写对了,如果服务端没配好,字幕照样加载失败:
-
.vtt文件响应头中Content-Type必须是text/vtt(不是text/plain或application/octet-stream) - 若视频与字幕跨域(比如字幕放在 CDN),需在字幕响应头中添加
Access-Control-Allow-Origin: *或具体域名 - 本地开发时直接双击 HTML 打开(
file://协议):99% 会因 CORS 被拒,必须走本地服务(如python3 -m http.server)
验证方式:打开浏览器开发者工具 → Network → 找到 zh.vtt 请求 → 查看 Response Headers 中是否有 content-type: text/vtt。
kind、srclang、label 属性一个都不能少
这三个属性不是可选的“锦上添花”,而是播放器识别和用户切换字幕的依据:
-
kind="subtitles":必须显式声明,不能省略或写成"subtitle"(少 s) -
srclang="zh":语言代码要标准(zh、en、ja),不能写zh-CN或Chinese -
label="中文":用户在播放器字幕菜单里看到的名字,必须提供,否则某些浏览器(如 Safari)不显示该轨道 -
default属性只建议设在一个轨道上;设多个会导致行为不一致
漏掉 srclang 或 label 的后果:字幕轨道可能出现在 video.textTracks 列表里,但播放器 UI 不显示选项,也无法通过 JS 正常启用。
真正卡住人的往往不是“怎么加”,而是“为什么没反应”——这时候优先查顺序、查 VTT 文件头、查 Network 里的响应头,而不是改 JS 或重写 HTML 结构。










