原生 标签不支持双语字幕同时显示,因浏览器字幕机制为单激活模式,同一时刻仅一个 subtitles 轨道可处于 showing 状态;正确方案是合并至单个 .vtt 文件,用 ::cue() 和内联 class 分层控制样式。

原生 <track></track> 标签不支持双语字幕自动叠加显示,必须合并进单个 .vtt 文件并用 CSS 控制分层样式,或改用 JavaScript 动态合成 —— 试图靠两个独立 <track></track> 同时启用,浏览器只会显示其中一个。
为什么两个 <track></track> 无法同时显示双语
浏览器的字幕轨道机制是单激活模式:video.textTracks 中任意时刻最多一个轨道处于 "showing" 状态。即使你写了两个 <track kind="subtitles"></track>,用户在播放器菜单里也只能手动切换,不能“同时打开”。这不是 bug,是规范行为。
- Chrome、Firefox、Safari 全部遵循该逻辑;右键菜单里没有“双轨并行”选项
-
srclang="zh"和srclang="zh-Latn"虽语义不同,但kind相同(都是subtitles),仍被视作互斥轨道 - 若强行设两个
default,仅第一个生效,第二个始终为"disabled"
正确做法:合并进一个 .vtt 文件 + ::cue() 分类控制
把翻译和拼音/英文写在同一段 cue 里,用内联 class 区分,再用 CSS 控制上下位置与样式。这是唯一能稳定跨浏览器生效的原生方案。
- VTT 文件开头必须是顶格
WEBVTT,后跟空行;时间戳严格为00:00:01.234 --> 00:00:03.456(毫秒三位) - 每段内容用
<v class="translation">...</v><v class="pinyin">...</v>包裹,确保换行符是真实 \n(不要用<br>) - CSS 必须写成
video::cue(.translation)和video::cue(.pinyin),不能省略video前缀,否则不生效 - 避免在 VTT 里写
<b></b>或<i></i>:Safari 不渲染,只当纯文本输出
WEBVTT 00:00:01.000 --> 00:00:04.000 <v class="translation">你好,很高兴见到你。</v> <v class="pinyin">nǐ hǎo, hěn gāo xìng jiàn dào nǐ.</v>
替代方案:JavaScript 动态合成双轨(适合需要开关自由的场景)
当用户要能分别开启/关闭翻译、拼音、原文三者时,原生 <track></track> 就不够用了。此时应禁用所有 default,改用 JS 解析多个 VTT 文件,按时间戳对齐后注入自定义 DOM 层。
立即学习“前端免费学习笔记(深入)”;
- 先 fetch 两个 VTT 文本(
zh.vtt和pinyin.vtt),用正则或专用 parser(如@lyneinc/vtt-parser)提取 cues - 监听
video.addEventListener('timeupdate', ...),查表匹配当前时间对应的两行文本 - 把结果塞进
<div id="subtitle-layer">,用 flex 或 grid 实现上下排布 <li>注意防抖:避免每帧都重绘;可加 <code>requestAnimationFrame节流 - 缺点:失去原生字幕的无障碍支持(如屏幕阅读器识别)、字体抗锯齿可能不一致
容易被忽略的关键细节
很多失败不是因为逻辑错,而是卡在边缘约束上:VTT 文件必须 UTF-8 无 BOM(Windows 记事本默认带 BOM,务必换 VS Code 保存为 “UTF-8 without BOM”);<track></track> 必须放在 <source></source> 之后、 之前;本地开发时不能用 file:// 协议,必须起服务(python3 -m http.server);Nginx/Apache 要显式配置 .vtt 的 MIME 类型为 text/vtt,否则 Safari 拒绝加载。



















