用 FunASR 的 runtime 做实时会议转写,WebSocket 连上后推送 16k 单声道 PCM,跑到一小时五十分左右连接被对端关闭,返回码 1006,重连后从头发送导致重复文本。

排查方向其实有限,先把可能性排一排。长时间没有业务帧时服务端按空闲超时断开;客户端没发心跳帧,中间件把静默连接判为死连接;重连后没有带上已发送的偏移量,从头重推;每帧长度给到 9600 字节,超过服务端单帧上限。

先用 wscat 观察空闲多久被断开

wscat -c wss://asr.example.com/stream --wait 1800

然后把每帧长度改成 20ms 对应的 640 字节

python -c "print(16000*2*0.02)"

再往下加入 5 秒一次的空心跳帧保持连接

python stream_asr.py --heartbeat 5 --frame 640

剩下的就是重连时带上 last_offset 从断点续推

python stream_asr.py --resume --offset-file offset.json

恢复的判定其实很直接。连续推两小时不断连,重连场景下文本不重复,最终转写字数与音频时长比例正常。

容易忽略的是,流式接口的断连大多不是网络问题,而是空闲判定和帧长不对,重连逻辑里必须记偏移量,否则重复文本比断连更难处理。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。

作者 9823189