必须同时满足字幕文件规范、HTML结构、属性完整、浏览器行为四方面条件,缺一环字幕菜单就完全不显示选项;WEBVTT首行须顶格全大写无BOM,时间格式严格为00:00:01.234 --> 00:00:04.567,编码UTF-8无BOM,track须为video直接子元素且位于source之后,kind/srclang/label/src四属性缺一不可,多语言切换需JS控制textTrack.mode。

直接加 <track></track> 标签不行,必须同时满足字幕文件规范、HTML 结构、属性完整、浏览器行为四方面条件,漏掉任一环,字幕菜单里根本不会出现“中文”“English”这类选项——不是不显示,是压根看不见。
WebVTT 文件必须严格合规,错一个字符就全灭
浏览器对 .vtt 文件零容错:首行必须是顶格、全大写、无空格、无 BOM 的 WEBVTT;时间格式必须为 00:00:01.234 --> 00:00:04.567(小时/分钟/秒两位,毫秒三位,箭头前后各两个空格);编码必须是 UTF-8 无 BOM(Windows 记事本默认带 BOM,务必用 VS Code 或 Notepad++ 选“UTF-8 无签名”保存)。
- 常见错误:
webvtt、WebVTT、WEBVTT(末尾空格)、00:01:02.5 --> 00:01:04.8(毫秒少一位)→ 整个 cue 被跳过 - 中文乱码?大概率是 BOM 或编码不对;用在线工具(如 webvtt-validator.org)可快速验证文件是否干净
- 不要在 .vtt 里写
<b></b>等 HTML 标签——会被原样输出,不是渲染;样式要用 CSS 的::cue
<track></track> 必须嵌在 <video></video> 内且位置固定
<track></track> 只能作为 <video></video> 的**直接子元素**,且**必须放在所有 <source></source> 之后、 之前**。写在 <source></source> 前面、写在 <video></video> 外、中间混入注释或 <div>,浏览器都会静默忽略。
<ul>
<li>正确顺序:<code><video controls><source src="a.mp4"><track kind="subtitles" src="zh.vtt" srclang="zh" label="中文"></track></source></video>
<track></track> 可并列,但顺序不影响 UI 显示逻辑;default 属性只建议用于初始语言,且仅对 kind="subtitles" 或 "captions" 有意义src 不能是 Blob URL(如 blob:http://...),浏览器会静默失败;开发时若用 file:// 协议,多数浏览器因 CORS 拒绝加载,必须起本地服务(如 python3 -m http.server)四个属性缺一不可,浏览器不推断任何默认值
浏览器只认显式声明的属性:kind、src、srclang、label 少一个,该轨道就不会出现在右键字幕菜单中。
立即学习“前端免费学习笔记(深入)”;
-
kind="subtitles"必须写全,不能省略,不能写成subtitle或captions(后者用途不同,UI 分离) -
srclang必须是标准 BCP 47 语言码,如zh-Hans、en-US、ja;写chinese或spanish无效,且影响default是否自动启用 -
label是用户看到的名字,为空时可能显示(no label);建议含括号注明变体,如“中文(简体)”、“English (UK)” -
src路径需可访问;若跨域,服务端必须返回Access-Control-Allow-Origin: *
多语言切换不能只靠 HTML,得用 JS 控制 mode
HTML 中写多个 <track></track> 只是提供选项,用户点击切换语言,必须靠 JavaScript 动态设置 track.mode,否则只有带 default 的那个会生效,其余始终是 disabled。
- 先给每个
<track></track>设唯一id和正确srclang(如zh、en) - 切换时遍历所有
track元素:track.mode = "showing"(目标)或"disabled"(其余) - 注意:修改
mode后,浏览器不会自动滚动到当前时间点的字幕;如需精确同步,得监听timeupdate手动触发匹配逻辑 - Safari 默认隐藏右键字幕菜单,除非你显式设置
kind="subtitles"(Chrome 则默认支持)
最容易被忽略的是:字幕文件首行 WEBVTT 后必须跟一个空行,且整个文件不能有不可见字符;还有就是 src 路径看似正确,实则因 CORS 或协议限制被静默拦截——控制台往往只报 Failed to load resource,不提示具体原因。



















