default属性仅表示字幕轨道可被默认启用,实际显示需满足srclang合法、kind="subtitles"、vtt文件http 200且content-type为text/vtt等条件,否则浏览器静默忽略;移动端safari完全不支持default,须用js监听loadedmetadata事件并设track.mode="showing"。

default 属性根本不会让字幕“自动显示”,它只表示“可被默认启用”——用户仍需手动点 CC 按钮,或你用 JS 主动设 track.mode = "showing"。
为什么写了 default 字幕还是不出现
浏览器加载后,<track default></track> 确实会让对应轨道的 mode 初始为 "showing",但前提是:该 <track></track> 已被识别、srclang 合法、kind="subtitles"、VTT 文件 HTTP 返回 200 + Content-Type: text/vtt,且没被用户历史操作覆盖。常见静默失效原因包括:
-
kind拼错(如"subtitle"或带空格的"subtitles ")→ 浏览器当kind="metadata"处理,不进字幕菜单 -
srclang不合法("chinese"、"zh_CN"、空字符串)→ 轨道注册失败,video.textTracks里根本找不到它 -
<track></track>放在<source></source>前面,或包裹在<div> 里 → 浏览器直接跳过解析,控制台无报错 <li>VTT 文件返回 404 或 MIME 类型不是 <code>text/vtt(尤其 Safari 会直接拒载)→ 加载失败但 Network 面板只显示 “cancelled” - 移动端 Safari 完全忽略
default,track.mode初始恒为"disabled"
如何用 JS 强制字幕一加载就显示
必须等轨道真正就绪再操作,否则 textTracks 可能为空或 readyState !== 2。推荐监听 loadedmetadata 事件:
video.addEventListener('loadedmetadata', () => {
const targetTrack = Array.from(video.textTracks).find(track =>
track.kind === 'subtitles' && track.srclang === 'zh'
);
if (targetTrack && targetTrack.readyState === 2) {
targetTrack.mode = 'showing';
}
});
关键点:
- 不要用
DOMContentLoaded或onload——textTracks此时大概率未初始化 - 务必检查
track.readyState === 2(LOADED),否则设mode无效 - 多个字幕轨道时,记得把其他同
kind的轨道设为"disabled",避免冲突 - 若需按系统语言自动匹配,用
navigator.languages?.[0],并 fallback 到主语言码(如"zh-Hans"匹配不到就试"zh")
跨域和本地开发导致的“看似 default 失效”
很多问题根本不是 default 不生效,而是字幕压根没加载成功:
- 用
file://协议双击打开 HTML → 所有.vtt请求被浏览器静默拦截(安全策略强制) - 字幕放在 CDN,但服务端没配 CORS → Network 面板里
zh.vtt状态是 “cancelled”,控制台报No 'Access-Control-Allow-Origin' - 路径写错(大小写敏感、多斜杠、漏扩展名)→ 服务器返回 404,而某些 CDN 对 404 不返回 CORS 头,错误看起来像跨域问题
- Safari 要求 VTT 必须返回
Content-Type: text/vtt,Nginx/Apache 需显式配置 MIME 类型
真正决定字幕是否可见的,从来不是 default 属性,而是 track.mode 的实时值 + 用户是否触发过 UI 开关 —— 这个细节在调试时最容易被忽略。











