使用MediaSource播放视频时如何实现seek跳转及解决appendBuffer报错
这个错误本质是媒体元素已经触发了运行时错误,此时无法再向SourceBuffer追加数据,按以下步骤排查修复:
- 首先修复代码中的变量未定义问题:你的
fetchRange的onload回调里直接使用了未赋值的chunk变量,实际请求到的二进制数据存放在xhr.response中,需要把sourceBuffer.appendBuffer(chunk)改为sourceBuffer.appendBuffer(xhr.response)。 - 追加数据前先校验SourceBuffer状态:调用
appendBuffer前必须确保sourceBuffer.updating为false,且mediaSource.readyState为open,如果当前正在更新中,需要监听updateend事件等待状态空闲后再追加。 - Seek操作前清空旧缓冲:用户拖动进度条触发seek时,先调用
sourceBuffer.abort()终止正在进行的缓冲操作,再调用sourceBuffer.remove(0, video.duration)清空已有的缓冲内容,避免新旧不连续的媒体片段导致解码器报错。 - 修正Range请求边界:计算end值时增加边界判断,避免请求范围超过文件总大小:
end = Math.min(start + Math.round(start / 5), totalFileSize - 1)。 - 增加错误监听:给video元素绑定error事件,打印具体错误信息辅助定位:
video.addEventListener('error', () => { console.error('媒体错误:', video.error.code, video.error.message) })
修正后的参考代码如下:
function seek(e) { // 先终止旧的缓冲操作,清空缓冲 if (sourceBuffer.updating) { sourceBuffer.abort(); } sourceBuffer.remove(0, video.duration); // 等待清空完成后再请求新片段 sourceBuffer.addEventListener('updateend', () => { const start = Math.round((totalFileSize / video.duration) * video.currentTime); const end = Math.min(start + Math.round(start / 5), totalFileSize - 1); fetchRange(assetURL, start, end); }, { once: true }); }; function fetchRange(url, start, end) { var xhr = new XMLHttpRequest(); xhr.open('get', url); xhr.responseType = 'arraybuffer'; xhr.setRequestHeader('Range', 'bytes=' + start + '-' + end); xhr.onload = function () { console.log('fetched bytes: ', start, end); bytesFetched += end - start + 1; // 校验状态后再追加 if (!sourceBuffer.updating && mediaSource.readyState === 'open') { sourceBuffer.appendBuffer(xhr.response); } }; xhr.send(); };
内容的提问来源于stack exchange,提问作者Sakura
相关产品推荐
相关产品推荐

