track元素必须作为video或audio的子元素存在,且需在媒体元素src设置后、play()前插入,并正确设置kind、srclang和src属性,否则浏览器将忽略它。

track元素必须作为video或audio的子元素存在
直接用document.createElement('track')创建的track元素,如果没挂到媒体元素下,浏览器会完全忽略它——既不触发load事件,也不显示字幕,控制台也无报错。这是最常被忽略的前提。
实操建议:
- 先确保
或DOM 已就绪(可用DOMContentLoaded或检查video.readyState > 0) - 用
appendChild()或insertBefore()把track加到媒体元素内部,不能加到body或其他容器 -
track必须在媒体元素src设置**之后**、play()调用**之前**插入,否则部分浏览器(如 Safari)可能不加载
必需设置kind、srclang和src属性才能生效
即使DOM结构正确,缺任意一个关键属性,track仍处于“inactive”状态。常见错误是只设src却漏掉kind或srclang。
实操建议:
-
kind必须是"subtitles"、"captions"、"descriptions"、"chapters"或"metadata"之一;其他值会被静默忽略 -
srclang必须是有效BCP 47语言标签(如"zh"、"en-US"),空字符串或"auto"无效 -
src需为同源URL(或开启CORS),且返回的VTT文件HTTP状态码必须是200,MIME类型建议为text/vtt
示例:
const track = document.createElement('track');
track.kind = 'subtitles';
track.srclang = 'zh';
track.src = '/subtitles.zh.vtt';
track.label = '中文';
video.appendChild(track);
动态添加后需手动触发track加载与激活
JavaScript创建的track不会自动进入readyState === 2(loaded),也不会被浏览器默认选中。尤其当页面已有其他track时,新添加的几乎总是处于disabled状态。
实操建议:
- 监听
track的load事件确认加载完成(注意:不是onload,而是addEventListener('load', ...)) - 通过
video.textTracks获取已加载轨道列表,遍历找到对应srclang的TextTrack对象 - 显式设置
mode = 'showing'激活显示('hidden'或'disabled'都不行)
示例:
track.addEventListener('load', () => {
const tt = Array.from(video.textTracks).find(t => t.language === 'zh');
if (tt) tt.mode = 'showing';
});
兼容性与常见陷阱
Firefox对动态track支持最稳定;Chrome 100+ 后要求src必须同源或带CORS头;Safari在video未preload="metadata"时可能延迟加载字幕。
容易踩的坑:
- VTT文件首行必须是
WEBVTT(大小写敏感),且前后不能有BOM或空格 - 动态添加的
track不会出现在初始HTML中,因此video.textTracks.length在插入后立即读取可能仍为0——要等load事件后才可用 - 重复添加相同
srclang的track会导致多个同语言轨道并存,但只有第一个能被mode = 'showing'激活
真正麻烦的点在于:整个流程没有统一的Promise化接口,必须靠事件+轮询+状态判断组合推进,稍有遗漏就会静默失败。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











