移动端Chrome调用MediaStream Recording API返回Blob长度为0如何解决
移动端Chrome音频录制返回0长度Blob的排查与解决方案
核心问题与修复方案
MIME类型配置错误
代码存在两个直接导致兼容性问题的配置错误:一是初始化MediaRecorder时错用了type作为配置键,正确配置键为mimeType;二是硬编码指定audio/x-mpeg-3(MP3)格式,移动端Chrome全版本均不支持原生录制MP3编码,仅桌面端部分浏览器做了容错兜底可正常运行,移动端遇到不支持的编码格式会直接返回空Blob。
修复代码:在初始化录制实例前先做兼容性检测,选择当前浏览器支持的编码格式,替换原requestRecorder函数:async function requestRecorder() { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); // 按优先级匹配浏览器支持的音频编码 const supportedMime = MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : MediaRecorder.isTypeSupported('audio/webm') ? 'audio/webm' : MediaRecorder.isTypeSupported('audio/mp4') ? 'audio/mp4' : '' return new MediaRecorder(stream, supportedMime ? { mimeType: supportedMime } : undefined); }如果业务侧必须使用MP3格式,可在录制完成后用ffmpeg.wasm做前端转码,不要依赖浏览器原生MP3录制能力。
录制时序与事件绑定逻辑缺陷
原代码中事件绑定逻辑随isRecording变化重复执行,存在事件绑定晚于录制启动时机的风险;同时调用start()时未传时间片参数、未判断录制状态就直接执行stop(),对状态流转校验更严格的移动端Chrome会因此返回空数据。此外原handleData取值逻辑存在错误:事件参数e为BlobEvent对象,音频Blob存储在e.data字段,直接取e.name、将e赋值给type字段均为无效逻辑。
修复代码:拆分useEffect逻辑,实例初始化后一次性绑定事件,启停录制前校验状态:// 单独处理录制实例的事件绑定 useEffect(() => { if (!recorder) return; const handleData = (e) => { // 过滤空Blob避免无效赋值 if (!e.data || e.data.size === 0) return; setAudioURL({ previewUrl: URL.createObjectURL(e.data), mimeType: e.data.type, size: e.data.size, rawBlob: e.data // 存储原始Blob用于后续服务端上传 }); }; const handleStop = () => { // 录制停止后主动释放麦克风权限 recorder.stream.getTracks().forEach(track => track.stop()); } recorder.addEventListener("dataavailable", handleData); recorder.addEventListener("stop", handleStop); return () => { recorder.removeEventListener("dataavailable", handleData); recorder.removeEventListener("stop", handleStop); } }, [recorder]); // 单独处理录制启停逻辑 useEffect(() => { if (!recorder) return; if (isRecording) { // 传入100ms时间片,兼容移动端事件触发逻辑,降低长录制内存占用 recorder.start(100); } else { // 仅在录制中状态执行stop,避免状态错误 if (recorder.state === 'recording') { recorder.stop(); } } }, [recorder, isRecording])运行环境权限限制
移动端Chrome对媒体权限有更严格的限制,以下场景也会导致采集到空流:- 页面未部署在HTTPS环境(本地localhost调试除外),通过局域网IP访问HTTP页面时会被限制麦克风权限
- 录制启动操作不是由用户主动交互直接触发:比如
startRecording被包裹在setTimeout、await异步回调中延迟执行,会被浏览器判定为非用户授权操作,拒绝返回有效音频流 - 录制过程中页面切到后台、或系统开启省电模式,Chrome会暂停媒体流采集,需监听
visibilitychange事件提示用户保持页面在前台。
额外注意事项
- 上传服务端时请直接使用
rawBlob字段存储的原始Blob对象,不要用URL.createObjectURL生成的预览地址做上传,该地址是浏览器生成的本地临时引用,无法作为文件读取。 - 首次调用麦克风权限时需要处理用户拒绝授权的场景,增加权限申请失败的提示逻辑,避免静默失败。
内容的提问来源于stack exchange,提问作者Bishal Peter Dores
相关产品推荐
相关产品推荐

