FunASR C++部署实战:Websocket服务器高性能实现

FunASR C++部署实战:Websocket服务器高性能实现

【免费下载链接】FunASR A Fundamental End-to-End Speech Recognition Toolkit and Open Source SOTA Pretrained Models, Supporting Speech Recognition, Voice Activity Detection, Text Post-processing etc. 【免费下载链接】FunASR 项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR

引言:语音交互时代的服务端挑战

在实时语音交互场景中,Websocket协议因其全双工通信特性成为音频流传输的首选方案。FunASR作为阿里巴巴达摩院开源的端到端语音识别工具包,提供了高性能的语音识别能力。本文将深入解析如何基于FunASR构建C++ Websocket服务器,通过线程池优化、异步IO设计和模型推理加速,实现日均百万级语音请求的处理能力。

核心痛点与解决方案

痛点解决方案性能收益
高并发连接处理IO线程池与业务线程池分离支持10k+并发连接
语音流实时解码异步任务队列+批处理推理降低90%上下文切换开销
模型加载耗时预加载+内存共享启动时间减少70%
动态热词更新FST有限状态机集成热词生效延迟<100ms

技术架构:高性能服务器的设计范式

整体架构

mermaid

线程模型设计

FunASR Websocket服务器采用三级线程架构:

  1. IO线程池:处理TCP连接和WebSocket协议解析,默认2线程
  2. 解码线程池:执行语音特征提取和模型推理,可配置8-16线程
  3. 模型线程池:内部OP并行计算,通过--model-thread-num控制

关键代码位于websocket-server.cppon_message回调:

asio::post(io_decoder_,
    std::bind(&WebSocketServer::do_decoder, this,
        std::move(*(sample_data_p.get())),
        std::move(hdl), 
        std::ref(msg_data->msg),
        std::ref(*thread_lock_p),
        std::move(hotwords_embedding_),
        msg_data->msg["wav_name"],
        msg_data->msg["itn"],
        msg_data->msg["audio_fs"],
        msg_data->msg["wav_format"],
        std::ref(msg_data->decoder_handle)));

编译部署:从源码到服务

环境准备

依赖项版本要求作用
GCC7.5+C++14特性支持
CMake3.16+项目构建系统
ONNX Runtime1.14.0+模型推理引擎
FFmpeg5.0+音频格式处理
WebSocketpp0.8.2WebSocket协议栈
Asio1.24.0异步IO库

编译步骤(Linux)

# 1. 克隆代码库
git clone https://gitcode.com/GitHub_Trending/fun/FunASR.git
cd FunASR/runtime/websocket

# 2. 安装系统依赖
sudo apt-get install libopenblas-dev libssl-dev

# 3. 下载依赖库
bash third_party/download_onnxruntime.sh
bash third_party/download_ffmpeg.sh

# 4. 编译项目
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=release .. \
  -DONNXRUNTIME_DIR=../third_party/onnxruntime \
  -DFFMPEG_DIR=../third_party/ffmpeg
make -j 8

Windows编译要点

Windows环境需额外配置OpenSSL和Visual Studio:

# 下载依赖
wget https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/dep_libs/openssl-1.1.1w.zip
# 编译命令
cmake ../ -D OPENSSL_ROOT_DIR=d:/openssl-1.1.1w \
  -D FFMPEG_DIR=d:/ffmpeg-master-latest-win64-gpl-shared \
  -D ONNXRUNTIME_DIR=d:/onnxruntime-win-x64-1.16.1

核心代码解析

连接管理机制

服务器采用std::map存储活跃连接,结合智能指针和互斥锁实现线程安全:

void WebSocketServer::on_open(websocketpp::connection_hdl hdl) {
  scoped_lock guard(m_lock);
  std::shared_ptr<FUNASR_MESSAGE> data_msg = std::make_shared<FUNASR_MESSAGE>();
  data_msg->samples = std::make_shared<std::vector<char>>();
  data_msg->thread_lock = std::make_shared<websocketpp::lib::mutex>();
  data_map.emplace(hdl, data_msg);
  LOG(INFO) << "active connections: " << data_map.size();
}

异步解码流程

do_decoder函数实现音频数据的异步处理:

  1. 从缓冲区获取音频数据
  2. 调用FunASR离线推理API
  3. 封装JSON结果并返回客户端
void WebSocketServer::do_decoder(const std::vector<char>& buffer,
                                 websocketpp::connection_hdl& hdl,
                                 nlohmann::json& msg,
                                 websocketpp::lib::mutex& thread_lock,
                                 std::vector<std::vector<float>> &hotwords_embedding,
                                 std::string wav_name,
                                 bool itn,
                                 int audio_fs,
                                 std::string wav_format,
                                 FUNASR_DEC_HANDLE& decoder_handle) {
  // 音频数据处理与ASR推理
  FUNASR_RESULT Result = FunOfflineInferBuffer(
      asr_handle, buffer.data(), buffer.size(), RASR_NONE, nullptr, 
      hotwords_embedding, audio_fs, wav_format, itn, decoder_handle);
  
  // 结果封装与发送
  nlohmann::json jsonresult;
  jsonresult["text"] = FunASRGetResult(Result, 0);
  jsonresult["mode"] = "offline";
  jsonresult["timestamp"] = FunASRGetStamp(Result);
  // ...发送逻辑
}

热词优化实现

通过FST有限状态机实现热词加权:

// 热词加载
std::unordered_map<std::string, int> merged_hws_map;
FunWfstDecoderLoadHwsRes(msg_data->decoder_handle, fst_inc_wts_, merged_hws_map);

// 热词文件格式示例 (hotwords.txt)
阿里巴巴 20
通义实验室 30

性能优化实践

线程池参数调优

参数建议值说明
--io-thread-num2-4网络IO线程数,不宜过多
--decoder-thread-numCPU核心数*1.5解码线程池大小
--model-thread-num1-2模型内部并行线程
--batch-size4-8GPU推理批处理大小

内存优化策略

  1. 模型共享:多实例共享模型权重,降低内存占用
  2. 缓冲区复用:音频缓冲区池化,减少动态内存分配
  3. 结果串池:识别结果字符串复用,降低GC压力

网络优化

  • TCP_NODELAY:禁用Nagle算法,降低延迟
  • SO_RCVBUF/SO_SNDBUF:调整TCP缓冲区大小至64KB-128KB
  • 连接心跳:定期清理无效连接,释放资源

部署与监控

启动命令示例

./build/bin/funasr-wss-server \
  --download-model-dir ./models \
  --model-dir damo/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch \
  --vad-dir damo/speech_fsmn_vad_zh-cn-16k-common-pytorch \
  --punc-dir damo/punc_ct-transformer_zh-cn-common-vocab272727-pytorch \
  --port 10095 \
  --io-thread-num 4 \
  --decoder-thread-num 12 \
  --hotword ./hotwords.txt

关键监控指标

指标阈值优化方向
连接数<10k水平扩展或负载均衡
解码延迟<300ms调整批处理大小或模型量化
内存占用<2GB模型裁剪或蒸馏
CPU使用率<80%线程数调整或GPU加速

常见问题排查

编译错误

  1. 依赖缺失
CMake Error at CMakeLists.txt:102 (find_package):
  Could not find OpenSSL.

解决:安装libssl-dev:sudo apt-get install libssl-dev

  1. onnxruntime链接错误
undefined reference to `Ort::Env::Env(OrtLoggingLevel, char const*)'

解决:检查ONNXRUNTIME_DIR路径是否正确

运行时问题

  1. 模型下载失败

    • 检查网络连接
    • 手动下载模型并指定--model-dir
  2. 高延迟

    • 降低--global-beam(默认3.0)
    • 增加--decoder-thread-num
    • 启用模型量化(--quantize true

总结与展望

本文详细介绍了FunASR WebSocket服务器的C++实现方案,从架构设计、编译部署到性能优化,完整覆盖了高性能语音服务的关键技术点。通过IO与业务线程分离、异步任务处理和模型优化,该方案可满足高并发、低延迟的语音识别需求。

未来优化方向:

  • GPU加速:通过--use-gpu true启用GPU推理
  • 动态批处理:根据请求量自适应调整批大小
  • K8s部署:容器化部署与自动扩缩容

项目地址:https://gitcode.com/GitHub_Trending/fun/FunASR

欢迎点赞、收藏、关注,获取更多语音识别部署实战技巧!

【免费下载链接】FunASR A Fundamental End-to-End Speech Recognition Toolkit and Open Source SOTA Pretrained Models, Supporting Speech Recognition, Voice Activity Detection, Text Post-processing etc. 【免费下载链接】FunASR 项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值