ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

FunASR 部署 Qwen3-ASR 流式 WebSocket 服务:serve_qwen3_asr_ws.py 架构解读、VAD 辨析与已知问题排查指南

FunASR 部署 Qwen3-ASR 流式 WebSocket 服务:serve_qwen3_asr_ws.py 架构解读、VAD 辨析与已知问题排查指南 FunASR 部署 Qwen3-ASR 流式 WebSocket 服务serve_qwen3_asr_ws.py 架构解读、VAD 辨析与已知问题排查指南【免费下载链接】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 仓库中 examples/industrial_data_pretraining/qwen3_asr/serve_qwen3_asr_ws.py 及其配套说明文档系统讲解如何把 Qwen3-ASR 的原生流式 APIinit_streaming_state/streaming_transcribe/finish_streaming_transcribe封装成与 Fun-ASR-Nano 同协议的 WebSocket 实时转写服务。读者将掌握该服务的协议与单事件循环架构、VAD 在流式 ASR 中的两种本质不同用途、chunk-size-sec等关键参数的真实影响以及 vllm 版本锁定、模型权重下载、tokenizer 与启动日志等若干踩坑点的根因与处置方案可直接用于生产级实时语音服务的部署与压测。1. 服务全景一条 WebSocket 上的增量流式转写1.1 设计定位serve_qwen3_asr_ws.py把 Qwen3-ASR 官方 example 的原生流式 API 包成一个 WebSocket 服务其协议与 Fun-ASR-Nano 的serve_realtime_ws.py完全一致因此可以直接复用同一套bench_streaming_ws.py压测脚本进行对比评测。架构上刻意对齐单 asyncio 事件循环streaming_transcribe/finish_streaming_transcribe为同步调用、阻塞整个循环——这样压测出来的并发特性才与 Fun-ASR-Nano 那条链路同口径可比生产扩展同样依靠多进程 CUDA MPS nginx见 docs/vllm_guide.md §6.7 的扩展思路。1.2 消息协议服务端与客户端交互共四步客户端连接ws://host:port客户端发送文本START→ 服务端回{event: started}客户端持续发送二进制int16 PCM 块16kHz 单声道→ 服务端随转写增长回{partial: 当前文本}客户端发送文本STOP→ 服务端回{is_final: true, sentences: [{text: 最终文本}]}随后再回{event: stopped}并断开。对应源码中的handle_clientserve_qwen3_asr_ws.py文本消息只处理START/STOP其余忽略二进制消息先经int16_pcm_to_float32把 int16 小端 PCM 除以 32768.0 归一化为 float32[-1, 1)区间streaming_transcribe只接受 float32再送入流式接口partial只在文本发生变化时才发送避免刷屏且不影响压测对首词延迟的统计。1.3 安装与启动pip install -U qwen-asr[vllm]0.0.6 transformers4.57.6 websockets numpy python serve_qwen3_asr_ws.py --port 10095 --gpu-memory-utilization 0.8可选参数--chunk-size-sec控制流式块大小默认 2.0值越小出字越快/越勤但并发开销越大详见下文 2.5 节。1.4 模型加载与流式状态模型全局只加载一次所有连接共用但每个连接各自持有独立的 streaming state源码asr Qwen3ASRModel.LLM(model..., gpu_memory_utilization..., max_new_tokens32)START时每个连接调用一次asr.init_streaming_state(unfixed_chunk_num2, unfixed_token_num5, chunk_size_secCHUNK_SIZE_SEC)。max_new_tokens32是流式场景下的小值设置与官方 example 一致。此外FunASR 的模型层为 Qwen3-ASR 提供了通用接口包装funasr/models/qwen3_asr/model.py中注册了Qwen3ASR别名Qwen/Qwen3-ASR-1.7B、Qwen/Qwen3-ASR-0.6B可通过funasr.AutoModel走非流式推理路径参考 demo.py 的AutoModel(modelQwen/Qwen3-ASR-1.7B, hubhf, dtypebf16)用法但流式 WebSocket 服务必须直接使用qwen_asr包见下文 3.3 节。2. VAD 的两个层次切段 VAD 与端点 VAD不可混为一谈这是最容易困惑的点。VAD语音活动检测在 ASR 中实际服务于两种完全不同的目的A 类切段用的 VAD给非流式 encoder 喂分段。像 Fun-ASR-Nano 这类模型encoder 是非流式的——一次必须看到完整的一段才能编码因此必须靠 VAD 把连续音频切成一句句、每句整体编码解码。这类 VAD 对 Fun-ASR-Nano 等模型是技术必需的不切段就无法编码。B 类端点/轮次检测用的 VAD判断这一轮说完了没。检测说话人停顿如静音 800ms来判定一句话/一轮结束从而触发锁定文本 / 发 is_final / 该回应了。这是产品行为层面的需求与 encoder 是否能流式无关。商用 Qwen3-ASR 的文档/示例中出现的turn_detection设置正是 B 类 VAD 的配置样例turn_detection: { type: server_vad, threshold: 0.2, silence_duration_ms: 800 }而在 Qwen3-ASR 的开源流式 API即本服务所用的qwen-asr[vllm]的init_streaming_state/streaming_transcribe中情况如下。2.1 不需要 A 类切段VADQwen3-ASR 开源流式 API 是增量式流式每次调用只消费新增的一小段音频流式状态向前滚动、连续转写不存在先切句再解码的步骤。哪些字已定、哪些字还会变由unfixed_chunk_num/unfixed_token_num两个参数表达——尾部 N 个 chunk/token 被视为未定、可能被后续音频修正其余视为已确认。这套内置的 partial/锁定机制恰好取代了 A 类 VAD 的切段职责。这就是为什么在开源流式 API 的代码里搜不到vad因为它这一层根本不做切段。2.2 仍然需要 B 类端点VAD——只是开源 API 自己不带自动判断用户停顿 这一轮结束这件事streaming_transcribe本身并不处理。商用服务在 ASR之外包了一层server_vad来做即上面那段turn_detection。本服务当前用客户端显式发送STOP来替代这个端点判断压测时音频放完即发 STOP。若要在真实场景实现自动断句/断轮需要在本服务之外自行接入一个 VAD / 端点检测器角色等同商用的server_vad而不是去 Qwen3-ASR 内部找——它的开源流式 API 不含这一层。一句话总结Qwen3-ASR 增量流式省掉了切段 VADA但**端点/轮次 VADB这一职责依然存在**——商用版用server_vad实现本服务用手动STOP代替。两者并不矛盾。2.3 官方佐证商用 Qwen-ASR-Realtime 的VAD 模式 / Manual 模式阿里云百炼的实时语音识别Qwen-ASR-Realtime官方文档明确把断句由谁做分成两种模式本质就是session.turn_detection开还是关VAD 模式默认turn_detection配置为server_vad服务端自动检测语音起点/终点来断句客户端只管持续发音频流服务端在检测到一句话结束时自动返回最终结果。流程中服务端会发送input_audio_buffer.speech_started/speech_stopped等事件——这正是上文所说的B 类端点 VAD由服务端那一层server_vad实现不是ASR 内核在切段。该模式适用于实时对话、会议记录等场景。Manual 模式turn_detection设为null由客户端控制断句——发完一整句音频后客户端发input_audio_buffer.commit通知服务端边界。适用于客户端能明确判断语句边界的场景如按住说话、聊天应用发语音消息。对应关系本服务serve_qwen3_asr_ws.py用客户端显式发STOP来标记一轮结束等价于商用的Manual 模式turn_detectionnull由客户端控制边界。若要做成服务端自动断句就是去实现商用VAD 模式的那一层端点检测server_vad叠加在本服务的增量转写之外而不是在 Qwen3-ASR 转写内核里找。2.4 增量流式的定位机制在源码中的体现serve_qwen3_asr_ws.py在START分支调用init_streaming_state时显式传入state asr.init_streaming_state( unfixed_chunk_num2, unfixed_token_num5, chunk_size_secCHUNK_SIZE_SEC, )即尾部 2 个 chunk、5 个 token 视为未定后续音频可以修正它们streaming_transcribe(seg, state)每收到一段新音频就推进状态state.text即当前累计转写文本。这组参数来自官方 example 的默认值也是理解为什么流式结果会越说越准的钥匙。2.5chunk-size-sec流式块大小的并发权衡--chunk-size-sec控制流式块大小默认2.0 秒直接传给init_streaming_state的chunk_size_sec。取值越小出字越快、输出越频繁但并发开销越大。仓库配套说明记录了一组实测数据在 L20 上、29 秒音频、48 路并发条件下chunk-size-sec1.0时全部请求失败而2.0时全部通过。这组对比清楚展示了块大小对并发能力的影响调参时需根据实际并发目标在出字延迟与吞吐容量之间取舍。3. 必须用 vllm 0.14不要用 0.19rope_scaling / thinker_config 警告3.1 症状本服务需要 vllm 加速而qwen-asr[vllm]在依赖中锁定vllm0.14.0。若换成更新的 vllm 版本如 0.19.x启动时会打印两条日志Unrecognized keys in rope_scaling for rope_typedefault: {mrope_section, mrope_interleaved, interleaved} thinker_config is None. Initializing thinker model with default values3.2 根因mrope 被改写为 default多模态位置编码退化vllm 在 0.14 → 0.19 之间两版 transformers 均为 4.57.6可排除 transformers 因素config 解析里的patch_rope_scaling_dict会把rope_type从mrope改写成default——它把 mrope 当作 legacy 处理假设由 vllm 内部消化mrope_section等字段elif rope_scaling[rope_type] mrope: assert mrope_section in rope_scaling rope_scaling[rope_type] default # ← 改写但 Qwen3-ASR 自带的Qwen3ASRThinkerTextRotaryEmbedding期望从rope_scaling里读到mrope才走多模态 RoPE 分支self.rope_type config.rope_scaling.get(rope_type, default)被 vllm 改写成default后它走了普通 RoPE 分支mrope_section/mrope_interleaved/interleaved这几个键无人认领 → 打印 Unrecognized keys 警告且音频/文本的多模态位置编码退化。thinker_config is None那条同源0.19 的加载路径没有正确解析 Qwen3-ASR 的 thinker 子配置回退到默认参数。3.3 影响与抉择在 0.19 上服务能起、也能出字两条日志分别是 WARNING/INFO不是 ERROR抽查几条转写看着也正常但位置编码退化对长音频/复杂内容可能有害且仓库未做 CER 定量对比无法判定等价。保守起见固定使用qwen-asr[vllm]自带的vllm0.14.0不要在服务环境中自行升级 vllm。配套的离线长音频说明文档 transcribe_vllm_offline_notes_en.md 同样强调qwen-asr[vllm]0.0.6锁定vllm0.14.0并建议用独立虚拟环境隔离。3.4 vllm 加速必须用 Qwen3ASRModelFunASR 的AutoModelVLLM无法加速 Qwen3-ASR必须直接使用from qwen_asr import Qwen3ASRModel asr Qwen3ASRModel.LLM( modelargs.model, gpu_memory_utilizationargs.gpu_memory_utilization, max_new_tokens32, )这一点同时解答了 FunASR 仓库#3026的疑问也与 transcribe_vllm_offline_notes_en.md 中离线 vLLM 路径同样不使用AutoModelVLLM它面向 FunASR 原生模型、当前不支持 Qwen3-ASR的说明互相印证。此外FunASR 模型层还内置了依赖一致性检查_check_qwen3_asr_dependencies()funasr/models/qwen3_asr/model.py它会核对qwen-asr0.0.6声明的transformers4.57.6约束若环境中的 transformers 版本不匹配会抛出ImportError并提示pip install -U qwen-asr0.0.6 transformers4.57.6 accelerate——这能提前暴露诸如AttributeError: Qwen3ASRConfig object has no attribute thinker_config一类的兼容性错误对应测试见 tests/test_qwen3_asr_dependency_check.py。3.5 模型权重下载若运行环境无法在线下载或无法访问 Hugging Face官方推荐先手动把权重下载到本地目录再把本地路径传给--model# 方式一ModelScope国内推荐 pip install -U modelscope modelscope download --model Qwen/Qwen3-ASR-1.7B --local_dir ./Qwen3-ASR-1.7B # 方式二Hugging Face pip install -U huggingface_hub[cli] huggingface-cli download Qwen/Qwen3-ASR-1.7B --local-dir ./Qwen3-ASR-1.7B # 启动时指定本地模型目录 python serve_qwen3_asr_ws.py --model ./Qwen3-ASR-1.7B ...注意事项仅设置VLLM_USE_MODELSCOPETrue并安装modelscope只能接管一部分下载流程。vLLM 会从 ModelScope 拉取 config、tokenizer、merges、vocab、model.safetensors.index.json等文件日志中可见Downloading Model from https://www.modelscope.cn ... Finish downloading 10 files但真正解析权重的model.safetensors仍可能回退到 huggingface.co 拉取。仓库记录的真实日志片段如下Downloading Model from https://www.modelscope.cn to directory: /home/vllm/.cache/modelscope/hub/models/Qwen/Qwen3-ASR-1.7B 2026-06-28 10:15:56,301 - modelscope - INFO - Got 10 files, start to download ... Downloading [configuration.json]: 100%| ... INFO 06-28 10:15:59 [model.py:530] Resolved architecture: Qwen3ASRForConditionalGeneration (MaxRetryError(HTTPSConnectionPool(host\huggingface.co\, port443): Max retries exceeded with url: /Qwen/Qwen3-ASR-1.7B/resolve/main/model.safetensors (Caused by NewConnectionError(HTTPSConnection(host\huggingface.co\, port443): Failed to establish a new connection: [Errno 101] Network is unreachable))), ...)这是 Qwen-ASR 当前下载链路的一个已知问题最稳妥的做法是先用modelscope download --local_dir把完整权重落盘到本地目录再以本地路径启动服务不要依赖VLLM_USE_MODELSCOPE的环境变量兜底。4. tokenizer 的fix_mistral_regex警告无害可忽略4.1 症状与原因启动时可能出现The tokenizer you are loading from .../Qwen3-ASR-1.7B with an incorrect regex pattern ... This will lead to incorrect tokenization. You should set the fix_mistral_regexTrue flag when loading this tokenizer to fix this issue.原因Qwen3-ASR 的 tokenizer 沿用了某类带已知 regex 问题的分词器实现底层库检测到该 regex 模式后给出提醒建议加fix_mistral_regexTrue修正切分。本服务通过 qwen-asr 的高层 API 加载模型、并不直接构造 tokenizer因此没有暴露这个开关这条提醒按原样打印出来。4.2 影响与处置实测对中文 ASR 转写结果无可见影响抽查多条转写正常未做 CER 量化。该 regex 修正主要影响某些特殊 token 的边界切分对语音转写路径未观察到差异属于提醒级噪音可以直接忽略。若要彻底消除需在更底层自行加载 tokenizer 时传fix_mistral_regexTrue但 qwen-asr 高层 API 当前不直接支持且没有实测必要性。5. 顺带另外两条启动日志均无害Error retrieving safetensors: Repo id must be in the form ...这是把本地模型路径当成了 HF 仓库 id 去查询线上元数据失败后重试 2 次、回退本地加载不影响功能。可通过设置环境变量HF_HUB_OFFLINE1消除。Downcasting torch.float32 to torch.bfloat16权重以 fp32 存储、按 bf16 加载正常节省显存/提速bf16 与 fp32 的指数位宽度相同精度损失几乎可忽略。这是 INFO 级别日志不是错误。6. 源码级保障与测试佐证该示例并非一次性脚本仓库为其提供了结构化保障协议一致性serve_qwen3_asr_ws.py的握手/收尾语义与 Fun-ASR-Nano 的serve_realtime_ws.py对齐压测口径可比相关压测工具与基准见 examples/industrial_data_pretraining/fun_asr_nano/realtime_ws_benchmark.py 与 docs/benchmark/realtime_ws_benchmark.md。健壮性测试tests/test_qwen3_asr_ws_example.py 通过 AST 静态分析断言handle_client必须捕获通用Exception并调用logging.exception记录对应源码handle_client末尾的except Exception: logging.exception(...)确保单个连接异常不会打垮整个事件循环同时校验配套说明文档不含审查占位语。依赖一致性测试tests/test_qwen3_asr_dependency_check.py 覆盖了 transformers 版本不匹配时_check_qwen3_asr_dependencies抛错、版本匹配时放行、包名大小写不敏感匹配、非 PEP440 版本不崩溃四条路径。多语言能力模型层包装类注释明确 Qwen3-ASR 支持 52 种语言的自动检测、上下文识别与可选的字符级时间戳强制对齐funasr/models/qwen3_asr/model.py并提供 0.6B约 4GB 显存更轻量与 1.7B约 8GB 显存更准确两个规模可选。7. 实战部署清单综合以上全部要点一个可复现的部署路径为环境隔离python -m venv .venv-qwen3-vllm建独立环境pip install -U qwen-asr[vllm]0.0.6 transformers4.57.6 websockets numpy不要升级 vllm锁定 0.14.0。权重就绪无外网环境先用modelscope download --model Qwen/Qwen3-ASR-1.7B --local_dir ./Qwen3-ASR-1.7B落盘完整权重启动时以本地路径传入--model。启动服务python serve_qwen3_asr_ws.py --port 10095 --gpu-memory-utilization 0.8按并发目标调整--chunk-size-sec默认 2.0压测前先验证并发余量。客户端交互START→ int16 PCM16kHz 单声道音频流 → 收取partial→ 音频放完发STOP收is_final最终结果真实业务中如需自动断轮在服务外部自行接入端点 VAD等价商用的server_vad角色。日志甄别rope_scaling/thinker_config/fix_mistral_regex/Error retrieving safetensors/Downcasting五类启动日志均无害或已在上述小节给出处置建议无需恐慌。【免费下载链接】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),仅供参考
返回列表