html 的 标签仅支持文本轨道(如字幕、描述),无法叠加视频流;视频叠加需通过 dom 元素(如 video+div/canvas)视觉层叠实现,并注意 z-index 层叠上下文、定位设置及时间同步机制。

HTML 本身不支持“视频轨道叠加”——<track></track> 只能声明字幕、说明、章节等**文本轨道**,不能叠加另一路视频流或画面层。所谓“多轨道叠加”,实际是 DOM 层级的视觉叠加(video + div/img/canvas),不是媒体轨道意义上的合成。
为什么 <track></track> 不能叠加视频
<track></track> 是语义化文本轨道容器,浏览器只允许它加载 WebVTT 文件并渲染为字幕/CC/描述文字。它没有 video、audio 或 canvas 的渲染能力,也不能接收帧数据或像素信息。试图给 <track></track> 的 src 指向 MP4 或 WebM,浏览器会静默失败,Network 面板里看到 404 或 MIME 类型不匹配(期望 text/vtt,却收到 video/mp4)。
- 所有“视频叠加”需求,必须用
<video></video>+ 定位覆盖层(<div>、<code><img>、<canvas></canvas>)实现 -
<track kind="subtitles"></track>和<track kind="captions"></track>是互斥类型,同一时间只能激活一条同 kind 轨道;但可共存多个不同 kind(如 subtitles + descriptions) - 浏览器不会把
<track></track>当作图层管理,它的显示完全由播放器 UI 控制,无法用 CSSz-index干预位置或层级 - 确保两个元素的最近公共父容器 **没触发新 stacking context**:检查是否误加了
opacity: 0.99、transform、filter、will-change或isolation: isolate -
<video></video>默认是position: static,z-index对它无效 —— 必须显式设position: relative或absolute - 覆盖层必须是定位元素:
position: absolute+top: 0; left: 0;+ 父容器position: relative - 移动端 Safari 全屏时会重置所有 CSS 层级,此时靠 JS 监听
webkitbeginfullscreen/webkitendfullscreen动态调整类名更可靠,而不是依赖初始 z-index - 背景视频设
opacity: 0.7或mix-blend-mode: overlay(注意:mix-blend-mode在 iOS Safari 上支持有限,慎用) - 前景视频建议加
playsinline和webkit-playsinline,避免 iOS 强制全屏导致定位错乱 - 两个
<video></video>的currentTime必须手动同步:监听主视频的timeupdate,然后赋值给副视频(secondaryVideo.currentTime = mainVideo.currentTime),但要注意 seek 后的 readyState 判断,否则报错InvalidStateError - 若副视频是 RTSP/HLS 转 WebRTC 流,无法精确对齐帧,建议用服务端下发的 NTP 时间戳做主时钟,前端只比对
performance.now()与服务端时间差来驱动渲染 - 每条弹幕/框体必须带唯一 ID 或时间戳标识,避免重复创建;用
requestAnimationFrame替代setTimeout驱动更新,防止卡顿堆积 - 必须限制最大并发数:
document.querySelectorAll('.danmaku').length > 15 && document.querySelector('.danmaku:first-child').remove() - seek 后要清空所有未结束的弹幕:
document.querySelectorAll('.danmaku').forEach(el => el.remove()),再按新currentTime重新拉取 - 移动端务必加
pointer-events: none到弹幕/框体元素上,否则点击穿透失效,用户点不到视频控件
z-index 失效时怎么让视频和覆盖层正确叠放
常见现象:给 <video></video> 设 z-index: 10,给 <div class="overlay"> 设 <code>z-index: 20,但覆盖层仍被视频压住。根本原因是它们不在同一个层叠上下文(stacking context)里。
真·视频流叠加:双 <video></video> 同屏播放的实操要点
要让两个视频画面物理重叠(比如画中画、背景视频+前景人像),需两个 <video></video> 标签共用同一容器,并用 CSS 控制透明度、混合模式与尺寸。
弹幕、打框、热区这些“叠加内容”怎么管生命周期
它们本质都是动态插入的 DOM 元素,不是轨道,但需要和视频时间强绑定。关键不在“怎么加”,而在“怎么删”和“怎么限”。
最易被忽略的是:所有叠加层的时间同步逻辑,都依赖于 video.currentTime 的可靠性。而它在 HLS(hls.js)、RTSP-WebRTC、甚至某些 MP4 文件里,可能滞后 200–500ms 或跳变。不要假设它永远精准——得预留校正机制,比如用 WebSocket 带时间戳推送 + 前端本地时钟漂移补偿。











