这类问题我又碰上了一次。WebSocket 实时语音对话,客户端每 20ms 发一帧 PCM,服务端攒满 1 秒才送 ASR,从说完到听到回复平均 2.1 秒,用户反馈像带着回音打电话。

第一反应是「TTS 整段合成完才开始播,首字要等全部生成」,验证下来不成立。

排查方向其实有限,先把可能性排一排。攒包等待完整句子,白白多出一秒;ASR 用的是非流式接口,必须等整段音频结束才有结果;链路上每一跳都各自加了缓冲区。

给每一跳打时间戳算出真实间隔

python -c "import time;print(int(time.time()*1000))"

然后把攒包窗口降到 200ms 并开流式识别

python vad_stream.py --window-ms 200 --endpoint-silence 300 --interim

TTS 边合成边播首段

python tts_stream.py --chunk-chars 12 --play-now

压测 WebSocket 往返确认没有二次阻塞

python ws_bench.py --url ws://127.0.0.1:8000/ws --frames 500

改完先别撤,确认这几项。从最后一帧上行到首段音频下行的间隔小于 700ms,说话过程中就能看到 interim 文本,主观回音感消失。

补一句。延迟要按跳分配预算,先量再改;攒包窗口砍得太短会让断句变碎,得和 VAD 端点参数一起调。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。

作者 9823189