default属性不保证字幕显示,仅在首次访问且未操作字幕控件时可能启用候选轨道;真正决定可见性的是track.mode="showing",需JS监听loadedmetadata后主动设置并确保readyState===2。

加了 default 字幕还不显示,大概率不是它“缺失”,而是你误以为它该管的事,它根本不管——default 不负责“让字幕可见”,只参与“选哪条轨道作为候选”。真正决定字幕是否出现的,是 track.mode 的实时值和用户操作历史。
为什么删掉 default 反而更可控
很多开发者反复加 default、改 srclang、清缓存,却没意识到:一旦用户手动关过一次字幕,浏览器就会永久记住这个选择,后续所有 default 都被跳过。这不是 bug,是规范行为。
-
default只在「首次访问 + 未动过字幕开关」时可能起效,之后完全失效 - 多个
track都写default,多数浏览器静默忽略全部,或只启用第一个(行为未定义) - Safari 移动端(iOS 16.3 及更早)直接不响应
default,track.mode初始恒为"disabled" - Chrome 和 Firefox 对
default的处理逻辑不一致:Chrome 可能设mode = "showing",Firefox 常保持"disabled"直到用户点开 CC 按钮
track.mode === 'showing' 才是字幕可见的唯一条件
无论有没有 default,只要 track.mode 不是 "showing",字幕就绝不会渲染。而 mode 的初始值由浏览器决定,不可靠。
- 必须监听
loadedmetadata事件后再操作textTracks,此时轨道才完成注册 - 不能遍历
video.textTracks后直接设mode = "showing",要先检查track.readyState === 2(LOADED),否则无效 - 推荐匹配逻辑:
navigator.languages?.[0]→ fallback 到document.documentElement.lang→ 再 fallback 到主语言码(如zh-Hans→zh) - 设完目标轨道后,显式把其他同
kind="subtitles"的轨道设为"disabled",避免冲突
跨域、路径、VTT 格式这三关不过,default 就是摆设
default 是个“锦上添花”的属性,前提是轨道本身得加载成功。任何一环失败,它连候选资格都没有。
立即学习“前端免费学习笔记(深入)”;
- 本地开发用
file://协议?所有现代浏览器都会静默拒绝加载.vtt,必须起 HTTP 服务(如 VS Code Live Server) -
src路径大小写错误(ZH.VTTvszh.vtt)、漏扩展名、多斜杠,会导致 404;而某些 CDN 对 404 响应不返回 CORS 头,你看到的报错仍是跨域相关 - VTT 文件开头必须是顶格
WEBVTT(无 BOM、无空行、严格大小写),时间戳必须用英文句点(00:01:02.500),毫秒三位,块间至少两个换行符 - 服务器必须返回
Content-Type: text/vtt,Safari 尤其敏感;Nginx 需在types块中加text/vtt vtt;
真正该做的:删 default,用 JS 主动控制
别再调试 default 为什么没生效。删掉它,把控制权拿回来。
- HTML 中只保留干净的
<track kind="subtitles" srclang="zh" label="中文"> - JS 里监听
loadedmetadata,遍历textTracks找匹配语言的轨道,确认readyState === 2后设mode = "showing" - 全屏场景下额外注意:Chrome 98+ 要求全屏状态已生效后才能设
mode = "showing",否则无效 - 用户手动关闭过?那就别试图“恢复默认”,而是记录偏好并持久化到 localStorage,下次加载时读取
最易被忽略的是:即使你 JS 设置成功,用户下次刷新页面前手动关掉字幕,浏览器仍会记住这个选择,并覆盖你所有的初始化逻辑——这才是 default 真正失效的地方,不是代码写错了,是浏览器在按规范做事。



















