Django网站音频在iPhone/iPad无法播放问题求助
问题分析与修复方案
你的问题核心是MediaRecorder并未生成真正的MP3格式音频。虽然你手动将Blob的type设为audio/mp3并命名为audio.mp3,但实际上浏览器的MediaRecorder默认输出的是WebM(Opus编码)或WAV格式——这些格式被强行标记为MP3后,iOS Safari无法正确识别解析,导致播放失败。
修复方案1:前端录制通用格式,后端转标准MP3
这是兼容性最强的方案,后端转换能确保生成全设备支持的标准MP3文件。
前端代码修改
放弃强行指定MP3类型,改用MediaRecorder实际支持的格式:
record_btn.onclick = () => { $('#stop_btn').removeClass('hidden'); $('#record_btn').addClass('hidden'); $('#voice-bars').removeClass('hidden'); device = navigator.mediaDevices.getUserMedia({ audio: true}); device.then(stream => { recorder = new MediaRecorder(stream); var items = []; recorder.start(); recorder.addEventListener('dataavailable', e => { items.push(e.data); }); recorder.addEventListener('stop', e => { // 使用MediaRecorder原生支持的MIME类型,避免伪造格式 const actualMimeType = recorder.mimeType || 'audio/webm'; blob = new Blob(items, { 'type': actualMimeType }); // 文件名对应真实格式 myFile = new File([blob], `audio.${actualMimeType.split('/')[1]}`); $('#source').attr("src", URL.createObjectURL(blob)); }); }); }
Django后端转换处理
使用pydub库(依赖FFmpeg)将上传的WebM/WAV文件转为标准MP3:
- 安装依赖:
pip install pydub # 需额外安装FFmpeg: # Ubuntu/Debian: sudo apt install ffmpeg # macOS: brew install ffmpeg # Windows: 下载FFmpeg并配置系统环境变量
- 上传处理示例:
from pydub import AudioSegment from django.http import HttpResponse def save_recorded_audio(request): if request.method == 'POST': audio_file = request.FILES.get('recorded_audio') if not audio_file: return HttpResponse("No audio file uploaded", status=400) # 读取上传的音频文件 raw_audio = AudioSegment.from_file(audio_file) # 导出为标准MP3 mp3_output_path = f"media/recordings/{audio_file.name.split('.')[0]}.mp3" raw_audio.export(mp3_output_path, format='mp3', bitrate='128k') # 后续业务逻辑... return HttpResponse("Audio processed successfully")
修复方案2:前端直接编码为MP3(兼容性稍弱)
若需前端直接生成MP3,可使用第三方编码库(如lamejs)处理原始音频数据,而非依赖MediaRecorder的默认输出:
// 引入lamejs库(可通过CDN或本地文件引入) record_btn.onclick = () => { $('#stop_btn').removeClass('hidden'); $('#record_btn').addClass('hidden'); $('#voice-bars').removeClass('hidden'); navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => { const audioContext = new AudioContext(); const source = audioContext.createMediaStreamSource(stream); const processor = audioContext.createScriptProcessor(4096, 1, 1); // 初始化MP3编码器(单声道、采样率、比特率) const mp3Encoder = new lamejs.Mp3Encoder(1, audioContext.sampleRate, 128); const mp3Data = []; source.connect(processor); processor.connect(audioContext.destination); // 实时编码音频数据 processor.onaudioprocess = function(e) { const inputData = e.inputBuffer.getChannelData(0); const mp3Chunk = mp3Encoder.encodeBuffer(inputData); if (mp3Chunk.length > 0) { mp3Data.push(new Int8Array(mp3Chunk)); } }; // 绑定停止录制逻辑到stop_btn $('#stop_btn').click(() => { processor.disconnect(); source.disconnect(); stream.getTracks().forEach(track => track.stop()); // 完成编码,生成MP3 Blob const finalMp3Chunk = mp3Encoder.flush(); if (finalMp3Chunk.length > 0) { mp3Data.push(new Int8Array(finalMp3Chunk)); } const mp3Blob = new Blob(mp3Data, { type: 'audio/mp3' }); myFile = new File([mp3Blob], 'audio.mp3'); $('#source').attr("src", URL.createObjectURL(mp3Blob)); // 恢复按钮状态 $('#stop_btn').addClass('hidden'); $('#record_btn').removeClass('hidden'); $('#voice-bars').addClass('hidden'); }); }); };
方案对比
- 方案1兼容性拉满,后端转换不受浏览器限制,能确保生成全设备支持的标准MP3,推荐优先使用。
- 方案2无需后端参与,但需引入第三方库,部分旧版浏览器可能不支持AudioContext相关API。
内容的提问来源于stack exchange,提问作者pjuaristi
相关产品推荐
相关产品推荐

