字幕失效的根源在于四个硬性条件未同时满足:track位置错误、kind非"subtitles"、srclang不合法、.vtt首行非严格webvtt;且需确保编码utf-8无bom、换行lf、content-type为text/vtt、跨域头正确、路径准确、mode设为"showing"。

track 标签本身不“同步”字幕,它只是声明轨道;多语言字幕能否正常切换,取决于四个硬性条件全部满足——缺一不可,浏览器也不会报错,只会静默失效。
为什么字幕菜单里完全看不到选项?
大概率是以下任意一项没做对:
-
track没放在<source></source>之后、之前(比如写在<div> 里或 <code><source></source>前面) -
kind没设成"subtitles"(写成"subtitle"、"captions"或留空都无效) -
srclang不合法(如用"ch"、"Chinese",必须是"zh"、"en-US"这类 BCP 47 标准码) -
.vtt文件首行不是严格WEBVTT(带 BOM、小写、空格、缺空行,全都会导致加载失败) - 第一行必须是纯文本
WEBVTT(全大写,无空格,无 UTF-8 BOM) - 第二行必须为空行
- 时间戳格式必须为
00:00:01.234 --> 00:00:04.567(毫秒位固定三位,箭头前后各一个空格) - 文件编码必须是 UTF-8 无 BOM(VS Code 右下角点编码 → “Save with Encoding” → 选 UTF-8)
- 不能用 Windows 的 CRLF 换行以外的格式;推荐统一用 LF
- 本地双击 HTML 打开(
file://协议):99% 触发 CORS,字幕请求被拦截 —— 必须起本地服务,例如python3 -m http.server -
.vtt响应头中Content-Type不是text/vtt(常见于 Nginx/Apache 默认配成text/plain) - 跨域时没加
Access-Control-Allow-Origin响应头(CDN 托管字幕时必配) - 路径写错:
src="sub/zh.vtt"但 HTML 在子目录下,实际解析以当前页面 URL 为基准,不是以 HTML 文件位置为准 - 只有设为
"showing"才会显示;"hidden"仍解析但不渲染;"disabled"完全不处理 - 同一时间只能有一个
subtitles轨道是"showing",否则行为未定义 - 动态添加的轨道(
video.addTextTrack())默认mode = "disabled",需显式设置 - 监听
track.onload而非轮询readyState,VTT 加载完成会触发该事件
WebVTT 文件怎么才算“能用”?
不是把 SRT 改个后缀就行,浏览器对格式极其敏感:
验证方式:用浏览器直接打开 zh.vtt URL,看是否显示原始字幕内容且无乱码;如果显示下载或空白,说明文件或服务端配置已出问题。
服务器和本地开发最容易踩的坑
即使 HTML 和 .vtt 全部写对,仍可能白屏:
JS 动态切换字幕时 mode 设置不对
不能靠 default 属性实现“自动匹配系统语言”,必须手动控制 textTracks[i].mode:
真正麻烦的从来不是写几行 track,而是每个环节都得严丝合缝——从文件保存编码、到服务器响应头、再到 DOM 位置,漏掉一个,字幕就彻底消失,连控制台都不会提醒你。











