使用MediaSourceExtension(MSE)加载音频播放时长归零且无法播放求助
问题分析与解决方案
核心原因:MP4格式不兼容MSE要求
你当前用FFmpeg生成的是标准MP4,这类文件的moov原子(包含媒体元数据)在文件末尾,而MSE需要可流化的Fragmented MP4(fMP4)——即moov原子前置,且媒体数据被分割为可逐个加载的片段。这就是音频元素能识别时长,但无法播放的关键原因。
步骤1:修正FFmpeg命令生成兼容的fMP4
替换原FFmpeg命令为:
ffmpeg -i m.wav -c:a aac -b:a 32k -f mp4 -movflags frag_keyframe+empty_moov output.mp4
参数说明:
frag_keyframe:让每个关键帧对应一个媒体片段,适配流式加载逻辑empty_moov:生成空的moov原子放在文件开头,确保MSE能提前解析元数据
步骤2:修正代码中的MIME类型
MSE要求明确指定编码格式,不能仅用audio/mp4,需补充codecs参数:
const sourceBuffer = mse.addSourceBuffer('audio/mp4; codecs="mp4a.40.2"');
mp4a.40.2对应AAC-LC编码,和你用FFmpeg指定的aac编码完全匹配。
步骤3:确保加载完整的媒体数据
你代码中Uint8Array([0x00, 0x00, 0x00, 0x1C, 0x66, ...])如果只是截取的部分数据,会导致MSE无法解析完整媒体流。测试时建议直接加载完整的fMP4文件:
function msOpen(e) { URL.revokeObjectURL(ae.src); var mse = e.target; const sourceBuffer = mse.addSourceBuffer('audio/mp4; codecs="mp4a.40.2"'); // 加载完整的fragmented mp4文件 fetch('output.mp4') .then(res => res.arrayBuffer()) .then(buffer => { sourceBuffer.appendBuffer(buffer); }); sourceBuffer.addEventListener('updateend', function() { if (!sourceBuffer.updating && mse.readyState === 'open') { mse.endOfStream(); console.log('Audio is ready to play!'); } }); }
额外说明
你遇到的播放中止错误,是因为调用endOfStream()后媒体资源被标记为已结束,再次播放时浏览器会认为资源已终止。在后续WebSocket直播场景中,你不需要调用endOfStream(),直到直播结束时再执行即可。
内容的提问来源于stack exchange,提问作者engine32
相关产品推荐
相关产品推荐

