HTML5视频字幕显示需四个条件全部满足:WebVTT文件合规(首行顶格全大写WEBVTT、时间戳毫秒三位、UTF-8无BOM)、track为video直接子元素且紧贴source后、kind/srclang/label/src属性齐全合法、服务端返回text/vtt MIME类型。

track 标签本身不“加字幕”,它只是声明一条外部文本轨道;字幕能否显示,取决于四个条件是否全部满足:字幕文件合规、HTML 结构正确、属性齐全、服务端响应达标。漏掉任一环,字幕菜单里就根本不会出现选项——不是错位,是静默消失。
WebVTT 文件必须严格合规,一个空格都不能错
浏览器对.vtt 文件零容忍,写错首行、时间格式或编码,整条轨道直接丢弃:
- 首行必须是顶格、全大写、无空格、无 BOM 的 WEBVTT(webvtt 或 WebVTT 都失败)
- 时间戳格式固定为 00:00:01.234 --> 00:00:04.567:小时/分钟/秒两位,毫秒三位,箭头前后各一个空格,不能多也不能少
- 文件必须保存为 UTF-8 无 BOM:Windows 记事本默认带 BOM,务必用 VS Code 或 Notepad++ 选“UTF-8 无签名”
- 不要用 SRT 改后缀:SRT 的序号+空行结构不被 WebVTT 解析器识别,必须用工具(如 srt2vtt)转换
track 必须紧贴 source 后,且不能包在任何容器里
位置错误是高频问题,浏览器只认一种嵌套顺序:
- track 必须是 video 的**直接子元素**
- 必须出现在所有 source 标签**之后**、 **之前**
- 中间不能插入注释、空行、div 或其它标签
- 错误示例:<video><track><source></video> —— 浏览器静默忽略
- 正确示例:<video controls><source src="movie.mp4"><track kind="subtitles" src="zh.vtt" srclang="zh" label="中文" default></video>四个属性缺一不可,值必须合法
浏览器不推断默认值,少一个或写错,轨道就不会注册进video.textTracks:
- kind:必须是 subtitles(注意复数 s),写成 subtitle 或 captions(除非你真要音效描述)都无效
- src:路径区分大小写(zh.vtt ≠ ZH.VTT),本地开发时 file:// 协议下必然失败,必须起本地服务(如 python3 -m http.server)
- srclang:必须是标准 BCP 47 语言码,如 zh-Hans、en-US,写 chinese 或 spanish 无效
- label:用户在右键菜单看到的名称,为空时显示 (no label);建议含括号注明变体,如 中文(繁體)服务端响应必须匹配,否则 Network 面板只报“Failed to load resource”
track src 是一次独立 HTTP 请求,受跨域和 MIME 类型双重限制:
- 服务器必须返回 Content-Type: text/vtt:Nginx 示例配置为 types { text/vtt vtt; },Apache 需加 AddType text/vtt .vtt
- 跨域时服务端必须返回 Access-Control-Allow-Origin: *(或具体域名),否则 Chrome/Firefox 显示 net::ERR_BLOCKED_BY_RESPONSE
- HTTPS 页面中 src 必须也是 HTTPS,混合内容会被拦截
- 本地开发别用双击打开 HTML,一定要用本地服务访问,否则所有 track 加载失败
真正卡住人的地方,往往不是“怎么写”,而是某一行 VTT 文件开头多了个空格、或是 Nginx 没配 MIME 类型、又或是把 track 放在了 source 前面——这些错误都不报红,只让字幕彻底消失。



















