需同时满足四要素:合法WebVTT文件(首行WEBVTT、UTF-8无BOM、时间格式精确)、video内正确嵌套track(位于source后)、kind/srclang/src/label四属性齐全、服务端返回text/vtt MIME类型及CORS头,缺一即静默失效。

如何用 <track></track> 标签添加多语种字幕
HTML 本身不“定义”字幕,而是通过 <track></track> 元素把外部字幕文件(通常是 WebVTT)挂载到 <video></video> 上。关键不是“怎么写标签”,而是标签属性是否匹配实际资源和浏览器行为。
常见错误是写了 <track></track> 却没生效——多数因为 src 路径错、kind 值不对、或没设 srclang 导致浏览器无法识别语种。
-
kind="subtitles"是必须的,不能写成"caption"或漏掉(后者用于聋哑人描述音效,非翻译字幕) -
srclang必须是合法 BCP 47 语言标签,比如zh、zh-Hans、en-US,不能写chinese或english -
label是用户在右键菜单里看到的名字,建议用本地化写法,如label="中文(简体)" -
default属性最多只能在一个<track></track>上使用,且仅作初始启用参考,不强制覆盖用户偏好
<track></track> 的 srclang 和浏览器字幕切换逻辑
浏览器不会自动根据系统语言选字幕;它只按 srclang 匹配用户在设置中“首选语言”列表里的第一项(部分浏览器如 Chrome 还会检查 label 文本)。所以如果你的用户系统语言设为 zh-CN,但你的字幕写的是 srclang="zh-Hans",Chrome 可能不自动启用。
更稳妥的做法是:同一语种提供多个等效 srclang,例如:
立即学习“前端免费学习笔记(深入)”;
<track kind="subtitles" srclang="zh" label="中文" src="cn.vtt" default> <track kind="subtitles" srclang="zh-Hans" label="中文(简体)" src="cn.vtt"> <track kind="subtitles" srclang="zh-Hant" label="中文(繁體)" src="tw.vtt">
注意:重复加载同一文件无害,但多个 srclang 能提升匹配容错率。
WebVTT 文件路径与 MIME 类型问题
即使 <track></track> 标签写对了,如果服务器没返回正确的 Content-Type: text/vtt,Chrome 和 Edge 会直接拒绝加载字幕,控制台报错:Failed to load resource: net::ERR_INTERNET_DISCONNECTED(这个错误信息极具误导性,实际是 MIME 拒绝)。
- 静态服务如 Nginx 需显式配置:
add_type text/vtt .vtt; - 开发时用
python3 -m http.server默认不支持.vtt,会返回text/plain,导致失败;换成serve(npm)、live-server或加 header 的轻量服务更可靠 - 路径必须可跨域访问;若字幕和视频不在同源,需确保响应头含
Access-Control-Allow-Origin: *
JavaScript 动态控制字幕轨道的坑
用 JS 切换字幕不能只改 track.mode,还要处理其他轨道的冲突状态。比如手动启用一个轨道前,得先遍历 video.textTracks 把其他 mode === "showing" 的设为 "disabled"。
更麻烦的是:Chrome 中 textTracks 的顺序不保证与 HTML 中 <track></track> 顺序一致,也不能靠 srclang 稳定索引——建议用 track.label 或自定义 data-lang-id 属性做标记:
<track kind="subtitles" srclang="ja" label="日本語" data-lang-id="ja" src="jp.vtt">
然后 JS 查找:
const jaTrack = Array.from(video.textTracks).find(t => t.dataset.langId === 'ja');
否则容易切错轨道,尤其当用户手动开关过几次后,textTracks 的 mode 状态会变得混乱。
真正难的不是写对标签,而是让不同浏览器在各种网络、缓存、用户设置组合下都稳定显示指定语种——这需要测试真实设备+真实网络条件,而不是只看本地开发页是否“看起来正常”。



















