HTML录音完全依赖MediaStream,无流则MediaRecorder无法初始化;必须传有效MediaStream实例,禁止传null/undefined/srcObject未赋值对象;需手动stop轨道、验证音频轨道存在、避免clone复用,并注意Web Audio中转及跨浏览器兼容限制。
HTML录音本身不“配合”媒体流,而是完全依赖 MediaStream 才能工作——没有它,MediaRecorder 根本无法初始化,调用 start() 会直接抛 InvalidStateError。
MediaRecorder 的第一个参数强制要求是有效的 MediaStream 对象,不能是 HTMLAudioElement、Blob、ArrayBuffer,也不能是未赋值的 srcObject。
new MediaRecorder(videoEl.srcObject) 却没检查 videoEl.srcObject 是否已存在 → 流为 null 或 undefined,报 TypeError: Failed to construct 'MediaRecorder': parameter 1 is not of type 'MediaStream'
getUserMedia() 的流最可靠:const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
captureStream() 的流有严重兼容限制:Safari 16.4+ 才支持 video.captureStream(),iOS Safari 仍不支持音频捕获if (stream.getAudioTracks().length === 0) { /* 静音或无音频,录制将无声 */ }
MediaRecorder 持有 MediaStream 引用期间,麦克风/摄像头设备持续占用,系统指示灯常亮,且下次 getUserMedia() 可能失败或返回静音流。
mediaRecorder.stop() 不会自动停止轨道,必须显式调用:stream.getTracks().forEach(track => track.stop())
stream.clone() 试图复用:克隆流与原始流共享底层轨道,原始流 stop() 后克隆流也失效mediaRecorder.state;若不是 "inactive",应 new MediaRecorder(stream) 创建新实例若想在录音前加降噪、增益、AGC 等处理,必须走 Web Audio API,并通过 MediaStreamAudioDestinationNode 把处理后的音频导出为新流,再喂给 MediaRecorder。
立即学习“前端免费学习笔记(深入)”;
MediaStreamSource → GainNode → AnalyserNode → MediaStreamAudioDestinationNode → new MediaRecorder(destinationNode.stream)
MediaStreamAudioDestinationNode 支持不稳定,部分版本静音或报 NotSupportedError
captureStream() 不可用,这是架构级限制,不是代码能补的gainNode.gain.value = 1.0,但仅对 Web Audio 输出路径有效,不影响 MediaRecorder 原始编码start()/stop()
长时间连续录音时,反复对同一 MediaRecorder 实例调用 start()/stop() 容易触发状态异常,尤其在低端安卓机上出现断点或 dataavailable 漏发。
MediaRecorder 实例,配合时间戳对齐,避免状态污染dataavailable,CPU 压力大且易丢帧Blob 要及时用 URL.revokeObjectURL() 清理,否则内存泄漏明显audio/webm;codecs=opus 兼容性最好;audio/mp4 在 Safari 可用,但 Android Chrome 不支持 AAC 编码的 MP4 录制真正麻烦的从来不是怎么写那几行 start() 和 stop(),而是不同来源的 MediaStream 在时间戳精度、轨道同步性、跨浏览器行为上的差异——这些在开发阶段很难暴露,往往上线后才在特定机型上突然崩掉。