本地化部署ASR服务程序:以FastASR为例
语音呼叫如果要接入AI,语音转文字即ASR是必不可少的。 FastASR 是完全用C/C++实现的推理,很干净。支持好几种模型,尤其是支持达摩院的paraformer模型,效果很不错。但用到语音呼叫中,需要做些工程方面的工作。
1、协议:
我们实现实时的ASR,需自定义协议。我的设计是用一个TCP连接来进行控制,如通道绑定、解绑、识别文本结果返回等,也容易实现多机自动负载均衡;然后服务器再侦听一个UDP端口,接收实时的音频包,类似RTP,但更加简化:前面8字节填充通道id,随后就是固定的320字节的线性pcm音频数据,正好20ms采样,符合基于sip或webrtc的大部分语音通话的场景。
当然,协议时底层通信时使用,真正暴露给客户端应用层调用的是一组简单的C语言API函数。
2、重采样:ASR的模型只支持16k采用率,而voip大多是8k采样,因此要进行插值将采样率提升到16k。
3、ASR服务器程序的优化和改造
FastASR使用的效果最好的paraformer模型,是非流式模型,需要自己加上VAD处理改为流式,使用简单实用webrtc的vad库效果就不错,这个过程费时费力,考验耐心,句子太短反应太快则准确度会降低,句子太长准确度上升但反应略慢。可以设计一个api函数来专门设置参数,供不同场景选择。
FastASR使用的数学库是openblas,速度已经比较快,遗憾的是它不支持GUP加速,我电脑很普通,是intel集成显卡。我花了些时间摸索看能否进一步提速。Intel搞了一个oneAPI试图统一CPU、GPU等硬件,是一个很好的编程模型。我用oneAPI替换了最耗时的两个函数,一是特征处理时的快速傅立叶变换,二是推理时的大矩阵乘法运算,使用集成显卡GPU速度和原先一样,可能和集成显卡没有独立内存有关。但我在初始化的时候指定cpu,速度能提升10%左右,看来intel的oneAPI库还是进行了高度优化。以后有机会使用独显gpu,估计能真正大提速。改造时也发现FastASR存在一些bug,这里就不展开说了。
ASR服务器程序在收到udp数据时,先放入队列缓存,处理线程从队列中取出进行处理,这样效率最高。
4、ASR客户端
语音呼叫系统作为ASR客户端,逻辑比较简单,建立连接后收到rtp包解码后即可发给asr服务器程序,比较简单,在控制连接上收到识别结果,即使用回调或队列方式通知更上层。
实际效果非常好,速度飞快,反应灵敏。