Python能否转换音频数据为文件?Flask服务端音频文件生成异常求助
问题分析
当前生成的temp.webm无法播放,核心原因有两点:
- 前端每次发送的是MediaRecorder生成的音频片段,后端直接将片段追加写入文件,破坏了WebM容器的结构,导致文件损坏。
- 若要生成可播放的WAV文件,需要将WebM格式的音频解码后重新编码为WAV。
解决方案
一、先修复WebM文件完整性(确保生成可播放的WebM)
前端代码调整(voice.js + fetch.js)
MediaRecorder的dataavailable事件返回的是媒体片段,需将所有片段合并为完整Blob后再一次性上传,而非分批发送:
// voice.js let mediaRecorder; const voiceChunks = []; navigator.mediaDevices .getUserMedia({ audio: true }) .then((mediaStream) => { mediaRecorder = new MediaRecorder(mediaStream, { mimeType: 'audio/webm; codecs=opus' // 明确编码,提升兼容性 }); mediaRecorder.start(); mediaRecorder.addEventListener("dataavailable", (e) => { voiceChunks.push(e.data); // 示例:录制30秒后自动停止并上传 setTimeout(() => { mediaRecorder.stop(); }, 30000); }); mediaRecorder.addEventListener("stop", () => { const fullBlob = new Blob(voiceChunks, { type: 'audio/webm' }); uploadAudio(fullBlob); }); }); // fetch.js 改为上传函数 function uploadAudio(blob) { fetch('http://localhost:5000/audio', { method: 'post', body: blob }).then(res => console.log('上传完成')) .catch(err => console.error('上传失败', err)); }
后端代码调整(server.py)
现在后端收到完整的WebM文件,直接写入即可:
from flask import Flask, render_template, request, make_response app = Flask(__name__) @app.route("/") def hello_world(): return render_template('index.html') @app.route("/<name>.js") def getJs(name): return render_template(f'{name}.js') @app.route("/audio", methods=['post']) def audio(): with open('recording.webm', 'wb') as f: f.write(request.data) return make_response('', 200) if __name__ == '__main__': app.run(debug=True)
此时recording.webm可正常播放。
二、将WebM转换为WAV格式
使用pydub库(依赖ffmpeg)完成转码:
1. 安装依赖
pip install pydub
同时安装ffmpeg:
- Windows:下载ffmpeg并添加至系统PATH
- macOS:
brew install ffmpeg - Linux:
sudo apt install ffmpeg
2. 修改后端代码添加转码逻辑
from flask import Flask, render_template, request, make_response from pydub import AudioSegment app = Flask(__name__) @app.route("/") def hello_world(): return render_template('index.html') @app.route("/<name>.js") def getJs(name): return render_template(f'{name}.js') @app.route("/audio", methods=['post']) def audio(): # 保存完整WebM文件 with open('recording.webm', 'wb') as f: f.write(request.data) # 转码为WAV audio = AudioSegment.from_file('recording.webm', format='webm') audio.export('voice.wav', format='wav') return make_response('', 200) if __name__ == '__main__': app.run(debug=True)
额外优化:实时分批上传场景
若需实时发送片段,后端需维护客户端的音频片段队列,合并后再转码:
from flask import Flask, render_template, request, make_response, session from pydub import AudioSegment import os app = Flask(__name__) app.secret_key = 'your_secret_key' user_audio_chunks = {} # 存储各用户的音频片段 @app.route("/") def hello_world(): if 'user_id' not in session: session['user_id'] = os.urandom(16).hex() return render_template('index.html') @app.route("/<name>.js") def getJs(name): return render_template(f'{name}.js') @app.route("/audio", methods=['post']) def audio(): user_id = session['user_id'] user_audio_chunks.setdefault(user_id, []).append(request.data) # 示例:累计5个片段后合并转码 if len(user_audio_chunks[user_id]) >= 5: temp_webm = f'{user_id}_temp.webm' with open(temp_webm, 'wb') as f: for chunk in user_audio_chunks[user_id]: f.write(chunk) audio = AudioSegment.from_file(temp_webm, format='webm') audio.export(f'{user_id}_voice.wav', format='wav') user_audio_chunks[user_id] = [] # 清空队列 return make_response('', 200) if __name__ == '__main__': app.run(debug=True)
内容的提问来源于stack exchange,提问作者조성호
相关产品推荐
相关产品推荐

