You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 22:20:47