
FunASR gRPC 语音识别接口协议解析Request/Response 消息设计与双工流式识别实战【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR本文以 FunASR 仓库中 gRPC 接口的协议定义文档runtime/python/grpc/proto/Readme.md为核心系统讲解 ASR gRPC 服务中Request/Response消息各字段的语义、状态机设计speaking / decoding / finish并结合仓库中真实的 protobuf 定义、Python 客户端与服务端 C 实现说明如何搭建并验证一条完整的 gRPC 流式语音识别链路。读完后你将掌握 gRPC 双工流在 ASR 场景下的消息组织方式、客户端分片发送策略以及协议文件的重新生成方法。一、gRPC 服务接口双向流式 RecognizeFunASR 通过 gRPC 对外暴露流式语音识别能力。协议文档中定义的服务如下service ASR { //grpc service rpc Recognize (stream Request) returns (stream Response) {} //Stub }这里Recognize采用双向流client-streaming 与 server-streaming 的组合客户端以stream Request持续推送音频分片服务端以stream Response持续回传状态与识别结果。这种设计天然适配实时语音场景——客户端无需等待整段音频上传完毕服务端也能在音频流式到达的同时滚动输出中间结果。仓库中该协议的正式定义文件为 paraformer.proto同样声明了service ASR及其Recognize双工方法生成的 Python 桩代码即由它编译而来# paraformer_pb2.py and paraformer_pb2_grpc.py are already generated, # regenerate it only when you make changes to ./proto/paraformer.proto file. python -m grpc_tools.protoc --proto_path./proto -I ./proto --python_out. --grpc_python_out./ ./proto/paraformer.proto需要注意的是协议文档描述的是“客户端侧做 VAD”vad in client的接口形态而当前仓库 paraformer.proto 中实际生效的字段组织略有演进后文会对照说明。二、Request 消息一次请求要携带什么协议文档定义的Request消息如下message Request { //request data bytes audio_data 1; //audio data in bytes. string user 2; //user allowed. string language 3; //language, zh-CN for now. bool speaking 4; //flag for speaking. bool isEnd 5; //flag for end. set isEnd to true when you stop asr: //vad:is_speech then speakingTrue isEnd False, audio data will be appended for the specfied user. //vad:silence then speakingFalse isEnd False, clear audio buffer and do asr inference. }各字段的作用可以归纳为字段类型语义audio_databytes本次请求携带的音频字节流客户端以分片方式持续追加userstring用户标识服务端按用户维度维护各自的音频缓冲支持多路会话复用同一接口languagestring识别语言文档注明当前支持zh-CNspeakingbool说话状态标志由客户端侧 VAD 驱动isEndbool结束标志停止 ASR 时置为true从文档中的注释可以看出该协议的核心工作模式是客户端 VAD 驱动VAD 判定为有语音发送speakingTrue isEndFalse服务端将音频数据追加到该用户user字段指定的音频缓冲区VAD 判定为静音发送speakingFalse isEndFalse服务端清空音频缓冲并触发 ASR 推理用户停止识别置isEndtrue结束本轮识别。这一模式与协议目录下 workflow.png 描述的交互时序完全一致麦克风实时音频 → gRPC 客户端按 speaking 标志封装→ gRPC 服务端 → paraformer ASR pipeline服务端依次回传waiting、decoding、finish text等状态。仓库现行 proto 中的对应字段当前 paraformer.proto 中的Request消息为message Request { DecodeMode mode 1; WavFormat wav_format 2; int32 sampling_rate 3; repeated int32 chunk_size 4; bool is_final 5; bytes audio_data 6; } enum WavFormat { pcm 0; } enum DecodeMode { offline 0; online 1; two_pass 2; }可以看到现行实现把“语言/用户”维度收敛为更通用的解码模式DecodeMode与分片参数chunk_sizemodeoffline离线整段识别、online流式在线识别、two_pass2pass先流式出中间结果、后离线出最终结果wav_format当前仅支持pcm16-bit PCM 裸流sampling_rate采样率由客户端在首个请求包中给出chunk_size流式解码的分片配置重复字段is_final与文档中isEnd同义的结束标志audio_data音频字节分片与文档一致。三、Response 消息状态机与 action 语义协议文档定义的Response消息为message Response { //response data. string sentence 1; //json, includes flag for success and asr text . string user 2; //same to request user. string language 3; //same to request language. string action 4; //server status: //terminateasr stopped; //speakinguser is speaking, audio data is appended; //decoding: server is decoding; //finish: get asr text, most used. }user与language与请求原样回传用于客户端多路会话的路由匹配sentence以 JSON 形式包含成功标志与 ASR 文本。关键字段是action它构成服务端的状态机共四种状态action含义terminateASR 已停止speaking用户正在说话音频数据正在被追加到缓冲区decoding服务端正在解码finish已得到 ASR 文本最常用客户端主要消费此状态客户端的典型消费逻辑即忽略中间状态等到action finish时取出sentence中的识别文本。这与 workflow.png 中msg: decoding → msg: finish. text的时序对应。而现行 paraformer.proto 中的Response更精简message Response { DecodeMode mode 1; string text 2; bool is_final 3; }其中is_final取代了action字符串状态流式模式下服务端滚动返回is_finalfalse的中间文本is_finaltrue表示该段最终结果。在two_pass模式下客户端会先收到 online 中间结果、最后收到 offline 精修结果。四、Python 客户端实现分片发送与三模式对照仓库提供的参考客户端为 grpc_main_client.py它完整演示了文档协议的客户端侧实现要点。1. 分片参数self.audio_chunk_duration 1000 # ms self.audio_chunk_size int(self.sampling_rate * self.audio_chunk_duration / 1000) self.send_interval 100 # msGrpcClient.__init__中音频以int16读入soundfile按1000ms 为一个 chunk切分16kHz 下即 16000 个采样点每 100ms 发送一包模拟实时麦克风的到达节奏。这也是 Readme.md 中“In the demo client, audio_chunk_duration is set to 1000ms, and send_interval is set to 100ms”的出处。2. 请求迭代器首包参数 尾包 is_finalrequest_iterator的发送逻辑体现了 gRPC 流式 ASR 的两个关键约定if is_first_pack: is_first_pack False request.sampling_rate self.sampling_rate request.mode self.mode request.wav_format self.wav_format if request.mode DecodeMode.two_pass or request.mode DecodeMode.online: request.chunk_size.extend([5, 10, 5]) if start self.audio_chunk_size len(self.wav): is_final True request.is_final is_final request.audio_data audio_chunk.tobytes()首包携带会话级参数sampling_rate、mode、wav_format流式/2pass 模式下追加chunk_size [5, 10, 5]与 C 服务端GrpcEngine中默认的chunk_size_ {5, 10, 5}一致尾包置is_finalTrue通知服务端音频结束、可以出最终结果音频以tobytes()转为 int16 小端字节流2 字节/采样点。3. 三模式串行演示客户端main中依次以offline、online、two_pass三种模式请求同一段音频并计时for mode in [DecodeMode.offline, DecodeMode.online, DecodeMode.two_pass]: ... client GrpcClient(args.wav_path, uri, mode)每次收到响应都会打印mode / text / is final方便对照不同解码模式下的中间与最终输出。五、服务端实现印证解码线程与状态回调gRPC 服务端实现在 paraformer-server.h 中GrpcEngine类持有双向流的ServerReaderWriterResponse, Request并通过一组回调映射了协议文档中描述的服务端状态void DecodeThreadFunc(); // 独立解码线程 void OnSpeechStart(); // 对应 speakingTrue音频追加 void OnSpeechData(); void OnSpeechEnd(); // 对应 speakingFalse清空缓冲并触发推理其中默认chunk_size_ {5, 10, 5}、sampling_rate_ 16000、step_duration_ms_ 100与客户端发送节奏100ms/包形成呼应GrpcService继承ASR::Service并实现Recognize与 proto 中声明的服务一一对应。从源码结构看服务端在独立decode_thread_中执行流式解码音频缓冲audio_buffer_按 VAD/is_final信号进行累积与释放这正是协议文档中“appended / clear audio buffer and do asr inference”两条注释的运行载体。六、完整运行链路安装、生成桩代码、启动服务与客户端1. 安装依赖requirements.txt 仅包含两项grpcio grpcio-toolsgit clone FunASR 仓库 cd FunASR/runtime/python/grpc pip install -r requirements.txt注意 Readme.md 中的路径写作FunASR/funasr/runtime/python/grpc当前仓库实际目录为runtime/python/grpc以仓库现状为准。2. 重新生成 protobuf 桩代码paraformer_pb2.py与paraformer_pb2_grpc.py已随仓库生成仅当修改 paraformer.proto 后才需要重新执行python -m grpc_tools.protoc --proto_path./proto -I ./proto --python_out. --grpc_python_out./ ./proto/paraformer.proto3. 启动 gRPC 服务端服务端为 C 实现的paraformer-server参考 run_server.sh./build/bin/paraformer-server \ --port-id 10100 \ --model-dir models/damo/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch \ --online-model-dir models/damo/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online \ --quantize true \ --vad-dir models/damo/speech_fsmn_vad_zh-cn-16k-common-pytorch \ --vad-quant true \ --punc-dir models/damo/punc_ct-transformer_zh-cn-common-vad_realtime-vocab272727 \ --punc-quant true该脚本同时挂载离线大模型--model-dir、在线模型--online-model-dir、VAD 与标点模型默认端口10100——这正是客户端默认--port 10100的来源两端默认值保持一致。4. 启动 Python 客户端python grpc_main_client.py --host 127.0.0.1 --port 10100 --wav_path /path/to/your_test_wav.wav参数说明参数默认值说明--host127.0.0.1gRPC 服务端 IP--port10100gRPC 服务端端口--wav_path必填待识别的 wav 音频路径运行后日志会依次打印三种解码模式下的[request] audio_data len / is final与[receive] mode / text / is final可直观验证流式分片与is_final语义。七、小结FunASR 的 gRPC ASR 接口以文档runtime/python/grpc/proto/Readme.md定义的Request音频分片 VAD 说话/结束标志与Responseaction状态机 JSON 文本为协议核心配套 paraformer.proto 给出了包含DecodeModeoffline / online / two_pass与chunk_size的现行消息结构grpc_main_client.py 演示了“1000ms 分片、100ms 发送间隔、首包带参数、尾包置 is_final”的完整客户端范式paraformer-server.h 与 run_server.sh 则构成对应服务端的解码线程与模型挂载方式。理解这套协议与配套代码后即可基于 gRPC 双向流快速集成 FunASR 的实时语音识别能力。【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考