非Safari浏览器录制的音频无法在Safari中播放的问题
解决跨浏览器录制音频无法在Safari播放的问题
问题根源
Chrome、Firefox等浏览器的MediaRecorder默认会生成Opus编码的WebM音频文件,哪怕你指定type: 'audio/wav',浏览器也只会用它支持的最接近格式,不会严格生成标准PCM编码的WAV。而Safari对这种非标准的"伪WAV"兼容性极差,但它自己录制的是符合规范的PCM WAV,所以能正常播放。
前端修复方案(统一录制格式)
核心思路是强制使用全浏览器兼容的编码格式,比如AAC编码的MP4(Chrome、Firefox、Safari全平台支持),步骤如下:
- 先检测浏览器支持的兼容编码格式
const getSupportedMimeType = () => { // 优先选择全平台兼容的AAC MP4,其次是标准WAV,最后用Opus兜底 const candidateTypes = [ 'audio/mp4;codecs=mp4a.40.2', 'audio/wav;codecs=1', 'audio/webm;codecs=opus' ]; for (const type of candidateTypes) { if (MediaRecorder.isTypeSupported(type)) { return type; } } return 'audio/webm;codecs=opus'; };
- 修改录制和Blob生成逻辑
navigator.mediaDevices .getUserMedia({ audio: { sampleRate: 44100 } }) .then(function (stream) { // ... 原有状态更新代码不变 const targetMimeType = getSupportedMimeType(); mediaRecorder = new MediaRecorder(stream, { mimeType: targetMimeType }); // 指定兼容格式 mediaRecorder.start(); // ... ondataavailable等逻辑不变 mediaRecorder.onstop = async function (e) { // 用检测到的MIME类型生成Blob let blob = new Blob(chunks, { type: targetMimeType }); // ... 后续上传代码不变 } })
- 更新HTML的audio标签type属性
如果用的是MP4格式,修改为:
<audio controls src={process.env.NEXT_PUBLIC_API_URL + voice?.url} type="audio/mp4"> Your browser does not support the <code>audio</code> element. </audio>
后端转码方案(兼容已有录制文件)
如果已经有大量旧的非兼容音频文件,可在后端用ffmpeg转码为标准格式:
- 转成AAC MP4(推荐,文件小兼容性好):
ffmpeg -i input.webm -acodec aac -b:a 128k output.mp4
- 转成标准PCM WAV:
ffmpeg -i input.webm -acodec pcm_s16le -ar 44100 -ac 2 output.wav
转码后保存新文件,前端播放时指向转码后的文件即可。
额外注意事项
- 永远用
MediaRecorder.isTypeSupported()检测实际支持的格式,不要硬编码假设浏览器会遵守你指定的type。 - 确保后端返回音频时设置正确的
Content-Type响应头(比如MP4对应audio/mp4,WAV对应audio/wav),否则Safari可能无法识别。 - Safari 14.1及以上才支持
MediaRecorder,如果需要兼容旧版本Safari,得额外做降级处理。
内容的提问来源于stack exchange,提问作者Sakata Gintoki
相关产品推荐
相关产品推荐

