字幕不显示的主因是track标签未被识别为有效轨道,需同时满足位置正确(紧贴source后且在video内)、属性完整(kind/srclang/label缺一不可)、webvtt文件合规(首行webvtt、utf-8无bom、时间戳格式严格)、服务端返回text/vtt mime类型。

字幕不显示,大概率不是浏览器不支持,而是 track 标签没被浏览器识别为有效轨道——位置、属性、文件格式、服务端响应,四者缺一不可。
track 标签必须紧贴 source 之后且在 video 内部
浏览器只在 <video></video> 开始标签后、 前,并且所有 <source></source> 闭合之后的位置解析 track。放错位置等于没写,且几乎不报错。
- 错误:把
track放在<source></source>前面、写在外面、包在<div> 里 <li>错误:多个 <code>track之间插入注释或空行(部分浏览器会中断解析) - 正确顺序示例:
<video controls><source src="movie.mp4" type="video/mp4"><track kind="subtitles" srclang="zh" label="中文" src="zh.vtt" default></track></source></video>
- 首行必须是
WEBVTT(全大写,前后无空格,无 BOM) - 编码必须是 UTF-8 无 BOM(VS Code 右下角 → “Save with Encoding” → 选 UTF-8)
- 时间戳格式严格:如
00:00:01.234 --> 00:00:04.567,毫秒位必须三位,箭头前后各一个空格 - 服务器必须返回
Content-Type: text/vtt;本地开发用file://协议时必失效,得起服务(如python3 -m http.server) -
kind="subtitles":唯一能触发字幕 UI 的取值;写成"subtitle"或留空会被忽略 -
srclang必须是合法 BCP 47 码(如"zh"、"en-US"),不能是"ch"或"chinese";它是 JS 切换轨道时定位的唯一依据 -
label是用户在右键菜单或控件栏看到的名字;为空时可能显示"(no label)",无法区分中英文 -
default只能出现在一个track上;多个会导致全部失效 - 必须用
video::cue或全局::cue,例如:video::cue { color: white; font-size: 1.2em; background: rgba(0,0,0,0.7); } - 支持的样式极少:仅
color、opacity、font-size、text-shadow、background等;margin、display、transform全部无效 -
text-align: center对单行有效,但多行换行逻辑由浏览器控制,无法强制
WebVTT 文件必须满足四个硬性条件
哪怕只漏一个,Chrome/Firefox 就静默失败:不报错、不加载、字幕菜单为空。
kind、srclang、label 这三个属性缺一不可
它们不是“可选增强”,而是浏览器识别和渲染轨道的必要字段。
样式控制只能用 ::cue 伪类
字幕渲染在影子 DOM 中,普通 CSS 选择器完全无效,连 class 或 id 都不起作用。
最容易被忽略的是服务端 MIME 类型和本地 file:// 协议限制——这两点导致大量调试失败却找不到原因。别在本地双击 HTML 测试,先起个最小 HTTP 服务再说。











