Media Source Extension切换新视频分片无响应问题求助
问题根因
你的代码在切换新视频分片时存在4个核心错误,导致播放失效:
- 仅调用
sourceBuffer.abort()没有清空已缓冲的旧数据,旧分片内容仍留在SourceBuffer缓存中,新分片的时间戳与旧缓存冲突无法正常播放 - 每次调用
appendFirstSegment都会重复绑定updateend事件,导致appendNextSegment被多次触发,缓存逻辑完全混乱 - 切换视频时没有重置Transmuxer的状态,旧视频的转封装上下文残留,处理新分片时会生成错误的MP4片段
- 没有重置MediaSource的时长、播放头位置,播放逻辑仍基于旧视频的时间轴运行
正确切换流程与代码修改
切换新视频分片需要按以下流程修改代码:
- 暂停视频,先移除SourceBuffer上已绑定的
updateend事件,避免旧事件异常触发 - 调用
sourceBuffer.remove()清空所有已缓冲的旧数据,等待remove操作完成后再执行后续逻辑 - 重置Transmuxer实例,清空旧的转封装状态
- 重置
segments数组为新视频的分片列表,将播放头复位到0 - 重新调用分片加载逻辑
修改后的核心代码如下:
// 新增重置播放状态的通用函数,切换视频时调用 function resetPlayState(newSegments) { // 暂停视频 video.pause(); // 移除旧的updateend事件监听 if (sourceBuffer) { sourceBuffer.removeEventListener('updateend', appendNextSegment); // 清空所有缓冲内容 if (!sourceBuffer.updating) { sourceBuffer.remove(0, mediaSource.duration || Infinity); } // 等待清空操作完成 const onRemoveDone = () => { sourceBuffer.removeEventListener('updateend', onRemoveDone); // 重置转码器 transmuxer = new muxjs.mp4.Transmuxer(); // 重置分片列表 segments = newSegments; // 播放头归0 video.currentTime = 0; appendFirstSegment(); video.play(); }; sourceBuffer.addEventListener('updateend', onRemoveDone); } } // 修改play1函数,切换video2时调用这个函数传新分片列表即可 function play1() { const newSegments = [ "segment_0.ts", "segment_1.ts", "segment_2.ts", "segment_3.ts", "segment_4.ts", "segment_5.ts", "segment_6.ts", "segment_7.ts", "segment_8.ts", "segment_9.ts" ]; resetPlayState(newSegments); } // 修改appendFirstSegment,避免重复绑定事件 function appendFirstSegment(){ if (segments.length == 0){ return; } console.log('appendFirstSegment') if(!sourceBuffer){ sourceBuffer = mediaSource.addSourceBuffer(mime); sourceBuffer.mode = 'sequence'; } // 先移除再绑定,避免重复绑定 sourceBuffer.removeEventListener('updateend', appendNextSegment); sourceBuffer.addEventListener('updateend', appendNextSegment,false); transmuxer.off('data'); transmuxer.on('data', (segment) => { let data = new Uint8Array(segment.initSegment.byteLength + segment.data.byteLength); data.set(segment.initSegment, 0); data.set(segment.data, segment.initSegment.byteLength); console.log(muxjs.mp4.tools.inspect(data)); sourceBuffer.appendBuffer(data); }) fetch(segments.shift()).then((response)=>{ return response.arrayBuffer(); }).then((response)=>{ transmuxer.push(new Uint8Array(response)); transmuxer.flush(); }) }
内容的提问来源于stack exchange,提问作者Vitalii
相关产品推荐
相关产品推荐

