track元素必须与video同域且显式关联,需在HTML中预声明或用addTextTrack()创建并绑定src,切换视频时须手动禁用旧track、启用新track,并注意浏览器兼容性及VTT响应头。

track 元素必须和 video 元素同域且显式关联
浏览器只允许 加载与 同源的字幕文件,且不能靠 JS 动态插入后自动生效——必须在 初始 HTML 中声明,或用 addTextTrack() 手动创建并绑定。直接替换 标签节点(比如 innerHTML 重写)不会触发字幕加载。
实操建议:
- 每个视频对应一套独立的
,预先写在各自内部,初始设default属性仅给当前激活项 - 切换视频时,先调用
video.textTracks[i].mode = 'disabled'关闭旧 track,再对新的 track 调用.mode = 'showing' - 如果 track 是动态生成的(如从 API 获取 VTT URL),必须用
video.addTextTrack('subtitles', 'zh', 'zh')创建空 track,再通过track.src = url赋值,并监听load事件确认加载完成
用 data-* 属性管理多视频 track 映射关系
播放列表通常由 JS 控制切换,光靠 HTML 结构无法自动同步 track。需要把字幕路径、语言等元信息和视频项绑定,避免硬编码或错位。
实操建议:
- 在播放列表项(如
或)上加data-track-zh="video1-zh.vtt"、data-track-en="video1-en.vtt"等属性 - 切换时读取当前项的
dataset.trackZh,清空旧的,再用addTextTrack()+src设置新 track - 注意:VTT 文件需返回正确的
Content-Type: text/vtt,否则 Chrome 会静默失败,控制台报Failed to load resource: net::ERR_INVALID_RESPONSE
切换时清除旧 track 避免叠加和内存泄漏
反复调用 addTextTrack() 而不清理,会导致 video.textTracks 数组不断增长,旧 track 仍驻留内存,甚至出现多套字幕同时显示的异常。
实现 Markdown↔ HTML 互转,支持导出 PDF,用于用户请求的文档格式转换。
实操建议:
- 每次切换前执行循环:
for (let i = video.textTracks.length - 1; i >= 0; i--) { video.textTracks[i].mode = 'disabled'; } - 不要依赖
removeChild()删除标签——DOM 移除不影响已加载的 track 对象,必须操作textTracks集合 - 若使用
标签预置方式,切换视频后需手动设置video.querySelectorAll('track').forEach(t => t.mode = 'disabled'),再启用目标 track
Chrome 和 Safari 对动态 track.src 的兼容性差异
Safari 16.4+ 支持给动态创建的 track 设置 src 并触发加载;Chrome 需确保 track 已添加到 video 后再赋值 src,否则不发起请求。
实操建议:
- 严格按顺序执行:
const track = video.addTextTrack('subtitles'); track.kind = 'subtitles'; track.label = '中文'; track.srclang = 'zh'; video.appendChild(track); track.src = url; - 为防 Safari 延迟加载,可在
track.addEventListener('load', handler)后再调用track.mode = 'showing' - 调试时检查
track.readyState:0=not loaded, 1=loading, 2=loaded;track.cues为空说明加载失败或格式错误
实际中最容易被忽略的是 track 的生命周期管理——它不像 那样随 src 切换自动重置,必须显式控制 mode 和 src,且每一步都依赖 video 元素是否已挂载、是否在 document 中。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










