iOS Safari MediaRecorder录制无时长音频的时长添加方案咨询
iOS下MediaRecorder录制音频缺失时长元数据的解决方案
问题根源
iOS上MediaRecorder仅支持MP4容器(仅录音频时实际为M4A格式),但录制生成的文件会把包含时长信息的moov原子放在音频数据mdat原子之后,大部分播放器和系统无法读取这个位置的元数据,导致显示时长为0或未知。
解决方案一:用mp4box.js修复MP4结构
mp4box.js是专门处理MP4/M4A文件结构的工具库,可轻松调整原子位置并补全缺失的元数据。
修改后的代码示例
先引入mp4box.js(可下载本地文件引入,避免外链依赖),再调整录制完成后的处理逻辑:
let recorder; let chunks; document.querySelector("#stop").addEventListener("click", () => { recorder.stop(); }); document.querySelector("#start").addEventListener("click", async () => { const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false, }); recorder = new MediaRecorder(stream); chunks = []; recorder.ondataavailable = function(e) { chunks.push(e.data); }; recorder.onstop = async function() { const blob = new Blob(chunks, { type: recorder.mimeType }); // 用mp4box处理录制的Blob const fileReader = new FileReader(); fileReader.onload = function() { const arrayBuffer = this.result; const mp4File = MP4Box.createFile(); mp4File.onError = (e) => console.error(e); mp4File.onReady = function(info) { // 调整moov原子到文件开头 mp4File.setSegmentation(); const segments = mp4File.initializeSegmentation(); const newChunks = []; segments.forEach(seg => { const buffer = mp4File.getSegmentData(seg); newChunks.push(new Blob([buffer], { type: recorder.mimeType })); }); // 生成修复后的音频Blob const fixedBlob = new Blob(newChunks, { type: recorder.mimeType }); const url = window.URL.createObjectURL(fixedBlob); const a = document.createElement("a"); a.href = url; a.download = "recording.m4a"; // 明确后缀为m4a更规范 a.click(); window.URL.revokeObjectURL(url); }; mp4File.appendBuffer(new Uint8Array(arrayBuffer)); mp4File.flush(); }; fileReader.readAsArrayBuffer(blob); for (const t of stream.getTracks()) { t.stop(); } }; recorder.start(); });
方案二:手动调整MP4原子结构(不推荐,仅作原理说明)
若不想依赖第三方库,需手动解析MP4容器结构:
- 遍历文件定位
moov和mdat原子的位置 - 将
moov原子移至文件开头 - 更新
stts(时间到样本映射)原子中的总时长信息 - 修正所有原子的偏移量
该方法需对MP4格式有深入了解,代码复杂度高且易出错,优先推荐使用mp4box.js。
注意事项
- iOS 14及以上版本才支持
MediaRecorder的音频录制功能,需确保目标设备系统版本达标 - 修复后的文件建议命名为
.m4a后缀,避免部分系统识别异常
内容的提问来源于stack exchange,提问作者Luke Vo
相关产品推荐
相关产品推荐

