要用HTML5 MSE实现流媒体播放,关键是构建JavaScript可控的媒体数据管道:先创建MediaSource并绑定video,监听sourceopen后添加匹配MIME的SourceBuffer;分片加载时须校验updating状态,音视频时间戳对齐;自适应码率需结合下载耗时、缓冲水位和丢帧数决策,并加入切换节制;直播需保证时间戳连续和缓冲区不空转。

要用 HTML5 MediaSource Extensions(MSE)实现流媒体播放,关键不是“加个插件就跑起来”,而是构建一条由 JavaScript 主动调度的媒体数据管道——浏览器只负责解码和渲染,数据从哪来、何时来、来多少,全由你控制。
必须先搭好 MSE 基础管道
这是所有功能的前提,跳过这步,后续逻辑全部失效:
- 创建 MediaSource 实例,并用
URL.createObjectURL(mediaSource)绑定到<video></video>的src,不能直接赋字符串 URL - 监听
sourceopen事件,在回调里调用addSourceBuffer()创建缓冲区;readyState是 “closed” 时调用会报InvalidStateError - SourceBuffer 的 MIME 类型必须与实际分片严格匹配,例如 fMP4 视频写
video/mp4; codecs="avc1.640020",音频单独加audio/mp4; codecs="mp4a.40.2";填错会导致appendBuffer()静默失败 - 服务端必须提供分片化格式(fMP4 或 WebM),完整 MP4 文件无法被正确解析和追加
分片加载与安全写入是核心动作
流媒体不是一次加载完,而是一段一段喂进去,每一步都要状态校验:
- 将视频切为 2–6 秒小段,每种码率(如 360p/720p)对应独立可寻址的分片序列
- 用
fetch下载当前选定码率的下一个片段,拿到ArrayBuffer后,**必须先判断sourceBuffer.updating === false**,再调用appendBuffer() - 监听
updateend事件确认写入完成,这是触发下一分片加载的可靠时机;反复在updating === true时写入会直接报错 - 音视频混流时,两个 SourceBuffer 的时间戳(PTS/DTS)必须对齐,否则出现音画不同步
自适应码率靠多维信号联动决策
MSE 本身不决定码率,但提供了做决策的数据入口和执行通道:
- 看下载耗时比:当前片段实际下载时间 ÷ 上一段预估时间,>1.3 表示网络拥塞,应降码率
- 看缓冲水位:
video.buffered.end(0) - video.currentTime,低于 3 秒立即降级,高于 15 秒可试探升码率 - 看丢帧数:
video.getVideoPlaybackQuality().droppedVideoFrames连续增长,说明设备解码或渲染已吃力 - 加入切换节制机制,比如 8 秒内最多切换 1 次,避免在带宽临界点反复震荡
直播与低延迟场景需额外关注时间连续性
普通点播卡一下影响不大,直播一旦断档就是黑屏或卡死:
- 服务端推送的 fMP4 片段时间戳必须连续,比如上一段结束在 10s,下一段起始 PTS 就该是 10s,跳变会导致播放中断
- WebSocket 推流时,要主动维护时间轴,不能只管收包;收到数据后需解析 moof+mdat 结构,提取并校正 PTS
- 缓冲区不能空转,需定时检查
video.buffered范围,若即将耗尽(如只剩 1 秒),立刻触发追赶式加载 - 倍速播放时,“预加载窗口”要按
playbackRate × 常规缓冲时长动态拉长,否则 2x 播放很快就会缓冲告急
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











