浏览器不会自动显示字幕,必须手动启用CC按钮;default属性不可靠,需用JS在loadedmetadata后设target.mode='showing'并确保readyState为2。

为什么加了 <track></track> 字幕就是不显示
浏览器压根不会自动显示任何字幕轨道,<track></track> 只是声明“这里有条轨道”,不是“点开就出字幕”的开关。哪怕你写了 default,也只是告诉浏览器“这条轨道在加载时默认被选中”,仍需用户手动点击播放器的「CC」按钮并勾选它。
常见静默失效原因包括:
-
kind写成"captions"或"metadata"—— 必须是"subtitles"才会出现在字幕菜单里 -
srclang值非法,比如"chinese"、"zh-CN"(而用户系统语言是"zh"),或空着 -
.vtt文件走file://协议加载 → 因 CORS 限制被浏览器静默拦截(DevTools Network 面板里看不到请求,Console 也无报错) -
<track></track>没放在<source></source>之后、之前,或者被包在<div> 里 → 浏览器直接忽略该节点 <li>服务端没返回 <code>Content-Type: text/vtt→ 轨道加载失败,textTracks列表为空 - 多个
<track default></track>→ 大部分浏览器直接无视全部 - Safari 私密模式下,
<track></track>根本不解析 - 视频还没触发
loadedmetadata事件,video.textTracks还是空数组,default无从作用
default 属性到底能不能让字幕默认开启
不能可靠开启。它只在极窄条件下可能生效:用户首次访问、从未动过字幕开关、srclang 精确匹配系统语言、文件 HTTP 200、且同一 <video></video> 中仅有一个 default。
现实里更常遇到的是:
立即学习“前端免费学习笔记(深入)”;
真正可控的方式是用 JS 主动设 mode:
video.addEventListener('loadedmetadata', () => {
const target = Array.from(video.textTracks).find(t =>
t.kind === 'subtitles' && t.srclang === 'zh'
);
if (target && target.readyState === 2) {
target.mode = 'showing';
}
});
怎么用 JS 手动控制 textTracks 的显隐
绕过 UI 直接操作的前提很关键:该轨道必须已被用户“启用”过(即在播放器菜单里手动勾选过一次),否则 track.mode = 'showing' 会被浏览器忽略。
安全操作步骤:
- 等
video触发loadedmetadata后再遍历textTracks - 确认目标
track.readyState === 2(TextTrack.LOADED),否则设mode无效 - 先关掉其他同类型轨道:
t.mode = 'disabled',再设目标为'showing' - 不要一上来就硬设;可监听
textTracks.onchange,等用户切换后再响应
注意:textTracks 是实时集合,每次调用 Array.from() 都要重新取。
HLS/DASH 流媒体里 <track></track> 还管用吗
基本不管用。hls.js、dash.js 这类播放器接管了整个加载和解复用流程,<video></video> 只是渲染容器。<track src="xxx.vtt"></track> 声明的外挂文件仍能加载,但和流内字幕(如 HLS 的 EXT-X-MEDIA:TYPE=SUBTITLES)完全隔离。
流媒体字幕必须由 JS 解析后手动注入:
- hls.js 需调用
hls.subtitleTrack = index触发加载 - dash.js 要配
caption: {enable: true},且只认 WebVTT,不支持原生 TTML - 所有动态添加的轨道,都得用
video.addTextTrack()注入,并自己对齐时间轴(流字幕常有 PTS 偏移)
最终渲染入口永远只有 video.textTracks,但“怎么加进去”和“怎么保持同步”,全得自己兜底。



















