最近遇到一个需求,对接某公有云上的坐席系统,需要接收人工坐席和客户对话的语音流,然后调用 ASR(Automatic Speech Recognition,自动语音识别)引擎进行实时转写,最后将转写内容推送到 Kafka,供下游系统消费。
大致流程图如下:

标绿的系统即是我方负责对接的系统。
问题:前面的流程都没问题,但测试时发现,最终的转写内容总是会丢掉最后的一两句话,而我们的对接系统也没有任何错误日志。
我们联系了坐席客服系统的研发人员协助排查。刚开始对方也没发现什么问题,他们系统同样没有错误日志(是压根就没打印日志,这个是最坑的)。排查了很久依然定位不到原因,最后只能用对方的测试系统和我本地直接联调。对方系统开启详细日志后,终于发现了一个报错:
这个日志就很明显了。我方系统的 WebSocket 服务端默认接收的字节流长度为 8192,但对方发送的字节流达到了 76992。由于超出了限制,最后的音频流无法接收,导致最后几句话的内容丢失。
为什么只会丢失最后几句话?
原因:在通话过程中,坐席客服系统是分片发送语音流的,每次发送的长度为 4096,未超过 WebSocket 服务端默认接收的字节流长度,所以中间过程一切正常。但当通话结束后,对方系统会把剩余的所有字节流一次性全部发过来,此时字节流长度超过了 8192,服务端无法接收,直接导致最后的语音流丢失,而且服务端对此还没有任何错误日志。
怎么解决?
如何增加spring-sockjs-websocket服务器实现的输出缓冲区
因为我们是用 SpringBoot 整合 WebSocket,所以只需要增加如下配置即可调整输出缓冲区:
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
/**
* 开启WebSocket支持
*
* @author wave-muly
*/
@Slf4j
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Bean
public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(102400);
container.setMaxBinaryMessageBufferSize(102400);
log.info("Websocket factory returned");
return container;
}
}
参考链接:
How to increase output buffer for spring sockjs websocket server implementation - Stack Overflow、 在spring-boot利用websocket上传文件发现的问题 | 生子当如哈士奇的小空间

评论 0
可以先写评论,登录后草稿会自动恢复。