<track> 标签无法直接支持 HLS/DASH 流媒体字幕同步,仅适用于 MP4/WebM 等本地视频;多语言切换需同时满足位置正确、属性齐全(kind/srclang/label/src)、VTT 文件合规、mode 控制得当四个条件。

<track> 标签不能直接实现流媒体(HLS/DASH)字幕同步,它只对 MP4/WebM 等本地视频文件生效;多语言切换可用,但必须满足四个硬性条件:位置正确、属性齐全、VTT 文件合规、mode 控制得当,缺一即失效。
为什么 <track> 在 HLS/DASH 播放器里基本不工作
主流播放器如 hls.js 或 dash.js 完全接管媒体加载逻辑,<video> 只是渲染容器。此时浏览器原生 <track> 不会解析 m3u8 或 mpd 中的字幕轨道,也不会提取 TS 分片里的 WEBVTT 载荷。
-
<track src="sub.vtt">声明的外挂文件仍可加载,但和流内字幕完全隔离 - HLS 的
EXT-X-MEDIA:TYPE=SUBTITLES或 DASH 的 TTML 轨道,必须由 JS 解析后调用video.addTextTrack()注入textTracks - 流媒体字幕常有 PTS 偏移(如 +200ms),不能直接设
track.mode = "showing",需等track.oncuechange触发后再校验activeCues[0].startTime与video.currentTime
<track> 必须写在 <video> 内且紧贴 <source> 之后
浏览器顺序解析子节点:<source> 告诉它“播什么”,<track> 告诉它“配什么轨道”。位置错,video.textTracks.length 就永远为 0,且无任何报错提示。
- 错误写法:
<div><track src="a.vtt"></div>或<video><track></video><source> - 正确结构:
<video><source src="x.mp4"><track kind="subtitles" srclang="zh" src="zh.vtt"><track kind="subtitles" srclang="en" src="en.vtt"></video> - 动态用 JS
appendChild插入<track>无效——除非在<video>加载前插入并强制重新解析(实际不可行)
kind、srclang、label、src 四个属性一个都不能少
浏览器不做容错推断,缺任一属性,该轨道就不会出现在右键字幕菜单中,Safari 甚至会静默丢弃整个 <track> 节点。
立即学习“前端免费学习笔记(深入)”;
-
kind="subtitles"必须显式写出,caption或省略会导致轨道不被识别为可切换字幕 -
srclang必须是合法 BCP 47 码(如zh-Hans、en-US),chinese或english无效 -
label是用户看到的菜单名,建议含变体说明,如label="中文(简体)" -
src必须指向可访问路径;若跨域,服务端需返回Access-Control-Allow-Origin: *和Content-Type: text/vtt
用 JavaScript 切换字幕时 mode 的坑比想象中多
track.mode 只接受 "disabled"、"hidden"、"showing" 三值,设成 true、"on" 或其他字符串都无效;而且同一时间只能有一个 subtitles 轨道为 "showing",否则 Safari 渲染错乱、Chrome 可能只显示第一个。
- 切换前应检查
track.readyState === 2(LOADED),否则刚设"showing"就可能因未加载失败 - 不要用
track.hidden = false,这仅控制 DOM 是否渲染,不影响字幕显示逻辑 -
default属性不可靠:Chrome 仅首次生效,Safari 16.4+ 才支持 JS 设置mode,iOS 旧版 Safari 仍可能忽略格式错误的 VTT - VTT 文件首行不是严格
WEBVTT(大小写/空格/BOM 错一点)、时间戳毫秒位不是三位、编码带 BOM —— 整条轨道就静默变成disabled,控制台零提示
真正难的不是写对那几行 HTML,而是每个环节都得严丝合缝:VTT 文件得用 VS Code 保存为 UTF-8 无 BOM,<track> 得卡在 <source> 后面,srclang 得查 BCP 47 表,JS 切换前还得轮询 readyState。漏掉任意一环,字幕就消失得无声无息。



















