track 的 default 属性仅是弱提示且常失效,因依赖严格语言匹配、单 default 限制、正确 kind 和 MIME 类型等;可靠启用须在 loadedmetadata 后用 JS 检查 readyState 并设 mode=showing。

track 元素无法真正“自动开启”字幕,default 属性只是个弱提示,浏览器不保证执行;可靠方式必须用 JavaScript 主动控制 textTracks 的 mode。
为什么 default 属性经常失效
它不是开关,而是加载时的初始选中信号,且只在极窄条件下起效:
-
srclang必须严格匹配navigator.languages中首个语言码(如用户系统设为zh-CN,但你写srclang="zh",部分浏览器会忽略) - 多个
<track></track>同时带default→ 多数浏览器直接丢弃全部 -
kind不是"subtitles"(比如用了"captions"),Safari 等会跳过default逻辑 -
.vtt文件返回 404、CORS 错误或 MIME 类型不是text/vtt→ 轨道加载失败,default失去作用对象 - 代码执行早于
loadedmetadata事件 →video.textTracks还为空,根本找不到目标轨道
用 JS 主动启用字幕的正确时机与写法
必须等 loadedmetadata 触发后操作,此时轨道已加载完成,textTracks 可遍历:
video.addEventListener('loadedmetadata', () => {
const lang = navigator.languages?.[0] || 'zh';
const targetTrack = Array.from(video.textTracks).find(track =>
track.kind === 'subtitles' &&
(track.srclang === lang || track.srclang.startsWith(lang.split('-')[0]))
);
if (targetTrack && targetTrack.readyState === 2) {
targetTrack.mode = 'showing';
}
});
关键点:
立即学习“前端免费学习笔记(深入)”;
-
targetTrack.readyState === 2是硬性检查(2表示loaded),避免因网络延迟导致mode设置被静默忽略 - 用
startsWith匹配主语言(如zh-CN匹配zh),比完全相等更鲁棒 - 不要在
DOMContentLoaded或load事件里操作 —— 此时视频元数据可能还没解析完
切换字幕时必须关闭旧轨道
浏览器不允许多个 subtitles 轨道同时为 "showing",否则渲染错乱或静默失败:
- 手动切换前,先遍历所有
subtitles轨道,把非目标轨道设为disabled - 调用
track.mode = 'showing'前,确认该轨道mode !== 'disabled'(否则无效) - 若用户之前从未点开过字幕菜单,首次设置
showing可能仍不生效 —— 这是浏览器策略限制,JS 无法绕过 - 流媒体场景(hls.js/dash.js)需等播放器实例 ready 后再注入轨道,不能依赖 HTML 声明
最易被忽略的是:即使代码全对,若用户已在该域名下手动关闭过字幕,浏览器会记住这个偏好,后续任何 JS 设置都会被覆盖 —— 这是设计使然,不是 bug。



















