字幕不显示主因是标签位置错误或webvtt文件不合规:必须为直接子元素且位于之后、之前;vtt首行须为webvtt,utf-8无bom,时间戳格式正确,服务器返回text/vtt类型,且srclang、label、kind属性缺一不可。

字幕不显示,90% 是 <track></track> 标签位置、格式或属性写错了——不是浏览器不支持,而是它根本没认出这是条有效轨道。
track 必须是 video 的直接子元素且顺序严格
浏览器只在 <video></video> 开始标签之后、结束标签之前,并且紧接在所有 <source></source> 之后的位置识别 <track></track>。放错位置等于没写。
-
<track></track>不能包在<div> 或其他容器里 <li>不能写在 <code><source></source>前面(常见错误) - 不能写在
外面,哪怕只多一个换行 - 多个
<track></track>之间不能有空标签或注释干扰解析 - 首行必须是
WEBVTT(全大写,无空格,无 BOM) - 编码必须是 UTF-8 无 BOM(用 VS Code 打开 → 右下角点编码 → “Save with Encoding” → 选 UTF-8)
- 时间戳格式必须为
00:00:01.234 --> 00:00:04.567,不能用 SRT 的序号行或空行分隔 - 服务器需返回
Content-Type: text/vtt,否则部分浏览器拒绝加载(Nginx/Apache 要手动配 MIME 类型) -
kind必须是"subtitles"、"captions"或"descriptions"之一,写成"subtitle"或空值会被忽略 -
srclang推荐用标准 BCP 47 码,如"zh"、"en-US",别用"ch"或"cn" - 多个
<track></track>中只能有一个带default属性,否则全部失效 -
label建议写明确语言名,比如label="中文(简体)",避免和srclang="zh"混淆 - 监听
video.textTracks[i].onload或检查track.readyState === 2(即TextTrack.LOADED)再操作 - 禁用当前轨道时,记得把其他同 kind 的轨道设为
"disabled",否则可能多轨同时显示 - 移动端 Safari 默认隐藏原生字幕按钮,且不响应
default,必须自己做 UI + JS 控制mode - 测试时务必真机验证:
video.textTracks.length在 iOS Safari 上可能始终为 0,得 fallback 到 div 渲染
WebVTT 文件必须满足四个硬性条件
哪怕只漏一个,Chrome/Firefox 都会静默失败:不报错、不加载、字幕空白。
srclang、label、kind 缺一不可,default 只能有一个
srclang 不只是“可选语言标识”,它是 JS 切换时定位轨道的唯一依据;label 不只是 UI 文字,缺失会导致浏览器下拉菜单里只显示“字幕”两个字,用户无法区分中英文。
JS 切换字幕前必须等 track.readyState === 2
直接设 track.mode = "showing" 很可能无效——因为文件还没加载完。浏览器不会等你,它只会跳过。
最易被忽略的其实是路径和编码:相对路径在带 hash 的 URL(如 page.html#section)下会解析错;UTF-8 BOM 在 Chrome 里会让整个 VTT 静默失败,控制台连 Network 请求都看不到。











