最近遇到一个需求,对接某公有云上的坐席系统,需要接收人工坐席和客户对话的语音流,然后调用
ASR
(Automatic Speech Recognition,自动语音识别)引擎,对语音流实时转写,最后将实时转写的内容推送到kafka,供下游系统消费。
大致流程图如下:
标绿的系统即是我方需求对接系统。
问题: 上述前面流程都没问题,但是发现最终的转写内容总是会丢最后的一两句话。对接系统也没有错误日志。
联系坐席客服系统研发人员协助排查问题,刚开始对方的研发人员也没发现问题,对方系统也没有错误日志(是压根就没打印日志,这个是最坑的)。最后排查很久依然无法找到问题,就只能对方的测试系统和我本地的系统直接联调。对方的系统开启日志后发现有一个报错,报错如下:
2024-04-02 15:23:46.144 INFO 1 --- [tReadThread-152] c.t.c.a.rasr.client.RasrClientWebSocket [] [] [] [] [] : rasr-web-socket onClose. message=No async message support and buffer too small. Buffer size: [8,192], Message size: [76,992]...
该日志就很明显了,我方系统的Websocket服务端默认接收的字节流长度为8192
,但是发送的字节流达到了76992
,所以最后的音频流接收不到,导致最后几句话的内容丢失。
为什么只会丢失最后几句话?
原因:坐席客服系统重复发语音流的过程中语音流的长度为4096
,未超过WebSocket
服务端默认接收的字节流长度,所以中间过程没问题。但是最后通话结束后,坐席客服系统会把剩余所有的字节流全部发送过来,字节流的长度超过了8096
,服务端不会接收该字节流导致最后的语音流丢失,且服务端没有相关错误日志。
怎么解决?
如何增加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上传文件发现的问题 | 生子当如哈士奇的小空间