使用MSE实现视频无缝切换

563 阅读1分钟

最近遇到一个需求,需要实现多个.mp4格式视频的无缝连续播放。虽然现有开源播放器,可以基本实现需求,但为了足够轻还是自己用mse简单实现一下。此篇文章非常浅薄,仅作记录使用。

💡 MSE 对视频格式有一定要求,需要是分段 MP4,笔者拿到的视频时未分段的mp4格式视频,使用ffmpeg进行分段。
ffmpeg -i non_fragmented.mp4 -movflags frag_keyframe+empty_moov

因为对音视频格式知识的匮乏,这块卡了很长时间,详细可以查阅。

Transcoding assets for Media Source Extensions - Web APIs | MDN

实现

初始化

首先定义一个MediaSource对象,并赋值给video.src

const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
let sourceBuffer;

添加sourceopen事件,该事件是在mediasourcevideo元素打开时触发。获取sourceBuffer对象,设置mode。

💡 mode的默认值是 `segments` 播放顺序是按照媒体片段的时间戳决定段的播放顺序;需要改为`sequence`根据添加的顺序设置播放顺序并自动生成时间戳。
mediaSource.addEventListener("sourceopen", async () => {
     console.log("source open!");
     sourceBuffer = mediaSource.addSourceBuffer(mimeCodec)
     sourceBuffer.mode ="sequence"
})

添加视频

通过fetch获取视频数据,并添加到sourcebuffer。


async function addVideo(fileUrl) {
			try{
      const res = await fetch(fileUrl)
      const segment = await res.arrayBuffer();
      sourceBuffer.appendBuffer(segment)
			if(video.paused){
          video.play();
      }
			}catch(err){
					video.pause();
			}
};

因为是本地运行,且视频较短,没有进行分段,如果视频较长,可以进行分段加载

const res = await fetch(fileUrl,{
      headers:{
          'range':'bytes=0-10240000'
      },
})

总结

因为需求并不复杂,实现起来也比较简单。其实直接用到MSE的时候非常少,如果是常规的视频播放,使用现有的开源库即可。

参考文档

Media Source Extensions API - Web API 接口参考 | MDN

Media Source Extensions™