Python WebSocket与JavaScript音频流传输故障排查求助
问题分析与修复方案
前端代码核心问题
dataavailable事件未触发:调用mediaRecorder.start()时未指定时间切片参数,MediaRecorder默认仅在调用mediaRecorder.stop()时才触发该事件。当前代码只启动录制未执行停止操作,导致没有音频数据发送到后端。- 未匹配音频编码格式:MediaRecorder默认编码(如Chrome下的
opus)与后端WAV要求的原始PCM格式不兼容,即使发送数据也无法直接写入WAV文件。 - 未校验WebSocket连接状态:点击按钮时WebSocket可能未完成连接,直接调用
socket.send()会静默失败,导致数据无法传输。
后端代码核心问题
- WAV文件生命周期错误:原代码中
with语句包裹了事件循环,run_forever()会阻塞线程,导致WAV文件头部信息无法正确写入;同时错误地读取message.data,websockets接收Blob时直接返回bytes类型,无需额外读取。
修复后的代码
前端修复版
<button id="start-recording">Start Recording</button> <button id="stop-recording">Stop Recording</button> <script> const socket = new WebSocket("ws://localhost:8080"); const startBtn = document.getElementById("start-recording"); const stopBtn = document.getElementById("stop-recording"); let mediaRecorder; socket.addEventListener('open', () => { console.log('WebSocket连接成功'); }); startBtn.addEventListener("click", async () => { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); // 指定PCM编码格式,匹配WAV文件要求 const options = { mimeType: 'audio/wav; codecs=1' }; if (!MediaRecorder.isTypeSupported(options.mimeType)) { console.error('不支持指定的音频编码格式'); return; } mediaRecorder = new MediaRecorder(stream, options); mediaRecorder.addEventListener("dataavailable", (event) => { if (event.data.size > 0 && socket.readyState === WebSocket.OPEN) { socket.send(event.data); } }); mediaRecorder.addEventListener("error", (event) => { console.error("MediaRecorder error:", event); }); // 每1秒触发一次数据回调,可按需调整间隔 mediaRecorder.start(1000); startBtn.disabled = true; stopBtn.disabled = false; }); stopBtn.addEventListener("click", () => { if (mediaRecorder && mediaRecorder.state !== 'inactive') { mediaRecorder.stop(); startBtn.disabled = false; stopBtn.disabled = true; } }); </script>
后端修复版
import asyncio import wave import websockets async def handle(websocket, path): # 连接建立后打开WAV文件,确保写入过程中文件保持打开 with wave.open("output.wav", "wb") as wav_file: wav_file.setsampwidth(2) wav_file.setnchannels(1) wav_file.setframerate(16000) async for message in websocket: if isinstance(message, bytes): wav_file.writeframes(message) start_server = websockets.serve(handle, "localhost", 8080) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever()
关键修复说明
- 前端新增停止按钮触发
dataavailable事件,指定PCM编码格式匹配WAV要求,增加WebSocket连接状态校验避免发送失败。 - 后端将WAV文件打开逻辑移到连接处理函数内,确保每个连接对应正确的文件写入时机,修复二进制数据读取方式。
内容的提问来源于stack exchange,提问作者XYBOX
相关产品推荐
相关产品推荐

