default属性不能可靠默认显示字幕,仅在首次访问、未操作字幕控件且浏览器支持时可能生效;真正可控的方式是监听loadedmetadata事件后用JavaScript匹配navigator.languages并设targetTrack.mode='showing'。

default 属性不能可靠让字幕默认显示,它只在极窄条件下“可能生效”;真正可控的方式是用 JavaScript 在 loadedmetadata 事件后主动设 textTrack.mode = 'showing'。
为什么 default 常常不生效
这不是你漏写了属性,而是浏览器根本没按字面意思执行。常见失效点包括:
-
srclang值不合法(比如写成zh-CN,但用户系统语言是zh;或拼错为chinese) - 多个
<track></track>都加了default→ 多数浏览器直接忽略全部,或行为未定义 -
kind不是"subtitles"(例如用了"captions"),Safari 等浏览器不对其触发default逻辑 -
src返回 404、CORS 错误,或服务端没返回text/vttMIME 类型 → 轨道加载失败,default失去作用对象 - 视频还没触发
loadedmetadata事件,video.textTracks还为空,浏览器来不及处理default
textTracks 初始化必须等 loadedmetadata
video.textTracks 是一个实时集合,但它的内容不是 DOM 加载完就立刻可读的。在 DOMContentLoaded 或元素刚插入时访问,大概率是空数组或只有未加载的轨道。
- 错误时机:
document.querySelector('video').textTracks在readyState === 0(HAVE_NOTHING)时为空 - 正确时机:监听
loadedmetadata(推荐)、或canplay;不要用onload(<track></track>不触发该事件) - 跨域限制:若
video或track.src来自 CDN,需服务端配置 CORS,否则textTracks可能被浏览器静默屏蔽
用 JS 主动匹配并启用首选字幕
绕过 default 的不确定性,用用户系统语言做依据,在轨道加载完成后手动启用:
立即学习“前端免费学习笔记(深入)”;
video.addEventListener('loadedmetadata', () => {
const lang = navigator.languages?.[0] || navigator.language || 'zh';
const targetTrack = Array.from(video.textTracks).find(track =>
track.kind === 'subtitles' &&
(track.srclang === lang || track.srclang.startsWith(lang.split('-')[0]))
);
if (targetTrack) {
targetTrack.mode = 'showing';
Array.from(video.textTracks)
.filter(t => t !== targetTrack && t.kind === 'subtitles')
.forEach(t => t.mode = 'disabled');
}
});
- 必须等
loadedmetadata后再遍历textTracks,否则找不到已加载的轨道 -
mode只能设为"disabled"、"hidden"或"showing",其他值无效 - 建议关闭其他同类型轨道,避免多条字幕同时显示
lang 必须写在 标签上才有效
页面默认语言不是靠 JS、<meta> 或 设置的——浏览器和屏幕阅读器只认 这一处。
-
<meta http-equiv="content-language">已废弃,Chrome/Firefox/Safari 全部忽略 -
document.documentElement.lang = "en-US"是事后修改,语音引擎不重载,CSS:lang()不重计算 - 值要用 BCP 47 标准:
zh-CN最稳;zh-Hans在部分旧 Safari 中匹配不准;zh过于宽泛,iOS VoiceOver 可能跳过中文 TTS 引擎 - 多语言混排时,外文片段必须显式加
lang,如<blockquote lang="en"></blockquote>,否则读屏仍用中文规则硬读
最易被忽略的是:即使 JS 匹配逻辑写对了,如果 缺失或错位,navigator.languages 就可能返回空或错误值,整个自动匹配链就断了。这个根节点问题不解决,后面所有逻辑都白搭。



















