media source extensions(mse)是现代web视频播放的底层基础设施,通过解耦数据源与播放器实现自适应码率、低延迟直播等功能;其核心依赖mediasource状态机、sourcebuffer分片注入及javascript动态调度。

Media Source Extensions(MSE)不是增强功能,而是现代 Web 视频播放的底层基础设施。它让 JavaScript 能接管视频数据的加载、缓冲与拼接过程,从而实现原生 <video></video> 标签无法完成的任务:自适应码率切换、低延迟直播、DRM 加密播放、视频剪辑拼接等。
核心机制:解耦数据源与播放器
MSE 的本质是把“视频从哪来”和“视频怎么播”彻底分开。传统方式中,video.src 指向一个固定 URL,浏览器自行下载并解码;而 MSE 中,video.src 指向一个由 JS 控制的 MediaSource 对象,媒体数据由脚本分段写入,播放器只负责消费缓冲区内容。
- 必须用
URL.createObjectURL(mediaSource)绑定到video.src,不能直接赋值字符串路径 -
mediaSource.readyState初始为"closed",只有触发sourceopen事件后才变为"open",此时才能调用addSourceBuffer() - 在
sourceopen外部尝试添加缓冲区或写入数据,会抛出InvalidStateError
SourceBuffer:分片注入的关键通道
每个 SourceBuffer 对应一种媒体类型(如视频或音频),其 MIME 类型必须与实际分片格式严格匹配,否则 appendBuffer() 会静默失败或报错。
- fMP4 分片常用 MIME:
video/mp4; codecs="avc1.640020"(H.264 Main Profile)或av01.0.04M.08(AV1) - 音频需单独声明:
audio/mp4; codecs="mp4a.40.2"(AAC-LC) - 混流场景下必须创建两个
SourceBuffer,且音视频时间戳(PTS/DTS)需对齐,否则出现音画不同步 - 每次调用
appendBuffer()前必须检查sourceBuffer.updating === false,否则触发错误
分片加载与动态控制逻辑
ABR(自适应码率)能力不来自 MSE 本身,而是构建在其上的调度策略。MSE 提供的是可编程管道,决策权完全交给 JS。
- 服务端必须提供按时间切分的 fMP4 或 WebM 片段(如每 4 秒一段),而非完整 MP4 文件
- 码率选择依据包括:当前网络吞吐(下载耗时比)、缓冲区水位(
video.buffered.end(0))、丢帧数、设备解码能力 - 片段加载推荐使用
fetch,拿到ArrayBuffer后写入对应SourceBuffer - 监听
updateend事件确认写入完成,再触发下一片段请求,形成可控队列
常见陷阱与稳定性保障
MSE 行为高度依赖状态机,稍有疏忽就会中断播放。稳定运行需主动管理边界条件:
- 缓冲区断档(如片段时间戳跳变)会导致卡顿或黑屏,需在写入前校验时间连续性
- 遇到
sourcebuffer.error事件时,应先调用abort(),等待updateend后再重试 - 直播场景下需定期调用
mediaSource.duration = Infinity防止自动结束 - 播放结束时调用
mediaSource.endOfStream(),通知浏览器流已终止











