MediaRecorder录制长视频触发iOS Safari崩溃的问题咨询
iOS端MediaRecorder长视频录制崩溃解决方案
所有iOS端的浏览器均强制使用Webkit内核,你遇到的是Webkit的进程内存阈值限制问题,和具体浏览器无关,我已在多个生产项目中实现过iOS端最长10分钟的MediaRecorder视频录制功能,以下是可落地的修复方案:
崩溃根因
你当前的实现会将录制过程中生成的所有Blob片段暂存在内存中,录制结束后一次性拼接为完整大Blob,再生成ObjectURL挂载到video元素上。iOS对Web进程的内存限制非常严格,1分钟以上的高清视频对应的Blob体积很容易触达阈值,系统会直接杀死网页进程触发重载,因此不会留下控制台错误日志。
修复步骤
- 录制阶段避免全量Blob暂存内存
不要将所有Blob片段存在内存数组中,设置MediaRecorder的timeslice参数为2000~5000ms,每触发ondataavailable事件就将当前分片存入IndexedDB,同步清空内存中冗余的Blob引用,避免内存持续上涨。
初始化时必须显式指定mimeType为video/mp4; codecs=h264,iOS默认的录制格式内存占用更高、兼容性更差。
代码示例:// 录制初始化 const mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/mp4; codecs=h264', videoBitsPerSecond: 1000000, // 可根据画质需求调整,码率越低单分片体积越小 timeslice: 3000 // 每3秒返回一个分片 }); // 此处省略IndexedDB初始化逻辑,直接存储分片即可 let chunkIndex = 0; mediaRecorder.ondataavailable = async (e) => { if (e.data.size > 0) { await indexDBInstance.put('videoChunks', { id: chunkIndex, data: e.data }); chunkIndex++; } }; - 回放阶段不要用大Blob生成ObjectURL
改用MediaSource Extensions(MSE)接口流式加载分片,逐段喂给播放器,不需要提前拼接完整大Blob,大幅降低回放阶段的内存占用。
代码示例:const mediaSource = new MediaSource(); const video = document.querySelector('video'); video.src = URL.createObjectURL(mediaSource); mediaSource.addEventListener('sourceopen', async () => { const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs=h264'); let currentChunk = 0; const totalChunks = chunkIndex; const loadNext = async () => { if (currentChunk >= totalChunks) { mediaSource.endOfStream(); URL.revokeObjectURL(video.src); // 主动释放ObjectURL占用的内存 return; } const chunk = await indexDBInstance.get('videoChunks', currentChunk); sourceBuffer.appendBuffer(chunk.data); currentChunk++; }; sourceBuffer.addEventListener('updateend', loadNext); loadNext(); }); - 额外优化点
所有不再使用的ObjectURL必须主动调用URL.revokeObjectURL()释放内存,不要依赖浏览器自动回收;不要将同一份视频资源同时挂载到多个video元素上,避免重复占用内存。
按照上述方案调整后,iOS 15及以上系统可以稳定录制最长10分钟的1080P视频,不会触发内存重载问题。
内容的提问来源于stack exchange,提问作者Chip
相关产品推荐
相关产品推荐

