必须用多个并列的track元素写在video内部且位于source之后、/video之前;每个track需唯一srclang和label,kind必须为subtitles,至少一个设default,src须同源或配CORS。

video 标签里怎么加多个 实现字幕切换
必须用多个 元素并列写在 内部,不能嵌套、不能放外面;每个 的 srclang 和 label 必须唯一,否则浏览器无法区分。常见错误是只写一个 default 却忘了其他字幕要手动激活,或者把 kind="subtitles" 错写成 kind="caption"(后者专指带音效描述的强制字幕,行为不同)。
实操要点:
-
必须放在之后、之前,顺序错会导致部分浏览器忽略 - 至少保留一个
default,否则首次加载时可能无字幕显示(即使 JS 后续启用) -
src值需同源或配好 CORS,跨域 VTT 文件会静默失败,控制台报Failed to load resource但不提示字幕问题 - 移动端 Safari 对
srclang大小写敏感,写srclang="zh-CN"比srclang="zh-cn"更稳妥
JS 切换 textTracks 时为什么总切不到目标字幕
因为 video.textTracks 是实时集合,不是静态快照;循环遍历时若直接改 mode,可能受异步加载影响——比如 VTT 还没解析完,track.mode 设为 "showing" 会被浏览器忽略。更稳的做法是监听 load 事件后再操作,或用 readyState 判断。
推荐写法:
- 先过滤出
kind === "subtitles"的轨道,避免误操作章节或描述轨道 - 用
track.label匹配(而非索引),防止动态增删导致序号偏移 - 设
track.mode = "showing"前,确认track.readyState === 2(loaded),否则跳过或延后重试 - 关闭其他字幕时,统一设
mode = "disabled",别用"hidden"——后者仍占用渲染资源且不暂停下载
hidden 属性和 textTracks.mode 能混用吗
不能。二者作用域完全不同:hidden 是 HTML 元素级显隐,对 标签本身无效(它本来就不渲染 DOM);textTracks.mode 才是控制字幕是否叠加到视频画面上的唯一合法方式。有人试图给 加 hidden 或 display: none,完全没用,还可能干扰 parser。
真正要隐藏字幕,只做这一件事:
-
track.mode = "disabled":彻底停用,不解析、不渲染、不请求字幕内容 -
track.mode = "hidden":已加载的内容暂不显示,但继续缓冲、保持时间轴同步(适合快速开关) -
track.mode = "showing":显示,且自动随视频播放滚动字幕
移动端点按字幕切换按钮没反应的常见原因
不是 JS 写错了,大概率是触摸事件穿透或焦点丢失。iOS Safari 在 上默认禁用非原生控件的点击,尤其当字幕按钮覆盖在视频区域上时。另外,如果用 做切换入口,但没加 type="button",表单提交会刷新页面。
避坑建议:
- 字幕按钮不要用
position: absolute盖在上,改用外置 toolbar 或控制条内嵌 - 确保按钮有足够点击热区(至少 44×44px),iOS 对小区域触摸有抑制
- 切换前调用
video.focus(),避免 Safari 把焦点锁在地址栏导致事件不触发 - 不要依赖
click,补监听touchstart并preventDefault(),防止滚动冲突
关键点在于:字幕切换本质是媒体轨道状态管理,不是 DOM 显隐。VTT 文件加载时机、textTracks 的就绪状态、以及移动端对 video 区域的事件限制,这三处最容易被当成“JS 逻辑问题”去调试,实际要查网络面板、track.readyState 和 touch 事件流。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











