Skip to content

ASR 模块

src/lab/asr/ — 语音识别,当前支持 Sherpa-ONNX ParaformerQwen3-ASR(OpenVINO INT8) 两套引擎。

目录结构

asr/
├── asr_base_model.py    # ASRBaseModel 抽象基类
├── combiner.py          # 句子合并(短间隔句子拼接)
├── converter.py         # 通用结果转换工具
├── cutter.py            # 句子切分(长停顿处拆句)
├── types.py             # 共享类型定义(Sentence / Word)
├── sherpa/
│   ├── engine.py        # Sherpa-ONNX Paraformer 推理引擎
│   ├── probe.py         # 模型探测与验证
│   └── utils.py         # 音频预处理工具
└── qwen_asr/
    ├── engine.py        # Qwen3-ASR OpenVINO 推理引擎(支持 0.6B / 1.7B)
    ├── processor.py     # 音频预处理(特征提取)
    └── forced_aligner.py # ForcedAligner(词级时间戳对齐,**必须配置**)

核心概念

ASRBaseModel

抽象基类,定义三个接口:

  • init_model() — 加载模型权重
  • reload_model() — 热重载
  • forward(input_path) — 推理

sherpa/engine.py 中的 Sherpa 引擎和 qwen_asr/engine.py 中的 Qwen3-ASR 引擎均实现此接口。

Sherpa-ONNX Paraformer

  • 模型:Paraformer-zh(中文)
  • 后端:sherpa-onnx,推理延迟极低(RTF ≈ 0.007,比实时快 ~140 倍)
  • VAD:内置 Silero VAD,支持分段检测
  • 配置:[asr.sherpa]

为什么保留 Sherpa?

Sherpa-ONNX Paraformer 在纯中文场景下速度极快。以同一句「那年长街春意正浓,策马同游」为例,Sherpa 仅需约 0.23s(CPU),而 Qwen3-ASR-1.7B 同等硬件下约需 2–3s。对于中文实时流场景,这个差距非常显著。

但 Sherpa 存在明确的语言局限性:不支持英文和日文——英文会乱码,日文会空返回。因此:

  • 纯中文场景 → 优先考虑 Sherpa(速度优先)
  • 中英/中日混合或多语言场景 → 必须用 Qwen3-ASR

Qwen3-ASR(OpenVINO INT8)

  • 模型:Qwen3-ASR 0.6B / 1.7B,OpenVINO INT8 量化
  • 后端:OpenVINO Runtime,CPU 推理
  • ForcedAligner:必须配置,提供词级时间戳对齐能力;未配置或路径不存在时启动即报错
  • 配置:[asr.qwen_asr]

两个引擎可通过 [package] 开关独立启用,互不干扰,各自注册不同的 API 路由。

OpenVINO 推理延迟与预热

OpenVINO CPU plugin 首次推理时触发 JIT kernel 编译(thread warm-up),之后进入稳定状态。以 i7-12th Gen(2022 年,CPU 散热未清灰)为例:

请求Qwen3-ASR-1.7B
第 1 次(冷启动 JIT)~20.7s
第 2 次(已预热)~2.9s
第 3 次(已预热)~2.2s

预热完成后,推理延迟稳定在 2–3s(~10s 音频片段)。

关于重启后的冷启动: 首次冷启动(JIT 编译)约 20s。启用 cache_dir 后,编译结果会持久化到 {model_dir}/.ov_cache/,后续重启可跳过 JIT 阶段,冷启动时间显著缩短。

关于 idle 导致的重新预热(已修复): 原实现使用同步 request.infer(),OpenVINO CPU thread pool 在约 30s 无请求后会 idle-down,下次推理重新触发预热(表现为突然变慢 10s 以上)。当前实现已改为 start_async() + wait() + thread pinning,worker thread 保持 event-wait 状态,idle 后不再重新预热,对实时对话场景友好。

Intel GPU 推理

设置 device = "GPU" 可启用 Intel GPU 加速推理。

支持的硬件:

  • Intel HD/UHD Graphics(第 6 代 Core 及以上,约 2015 年起)
  • Intel Iris Xe Graphics
  • Intel Arc 独显(全系)

驱动要求:

  • Windows:通常随 Intel 显卡驱动内置,无需额外安装。
  • Linux:需安装 OpenCL runtime:sudo apt install intel-opencl-icd

GPU 缓存目录: GPU 编译缓存默认存储在 {model_dir}/.ov_cache_gpu/,可通过 gpu_cache_dir 自定义路径。

配置示例:

toml
[asr.qwen_asr]
device = "GPU"
gpu_cache_dir = ""  # 空 = 使用默认路径

长音频 benchmark(example2.m4a,~4m 13s,中英混合)

硬件:i7-12th Gen(2022 笔记本),ForcedAligner 放在 GPU 上跑

Metric数值
总耗时68.8s
ASR 总计59.3s(28 个 chunk)
Aligner 总计6.7s(GPU)
平均每 chunk(~10s 音频)~2.5s ASR + ~0.3s align

典型 chunk 耗时:

[226910,236910] dur=10000ms  asr=3.257s  align=0.330s
[236910,246910] dur=10000ms  asr=2.498s  align=0.296s
[246910,253454] dur=6544ms   asr=1.589s  align=0.072s

0.6B vs 1.7B 速度差:以同一段长音频(~4m 13s)为例,0.6B 总 ASR 耗时约 40s,1.7B 约 60s,差距约 1.5×,小于参数量比例(1.7B / 0.6B ≈ 2.8×)。推测原因是 audio encoder(两个模型共享相近架构)的耗时在 per-chunk 中占比较高,decoder 参数量的差异被稀释了。

ForcedAligner 放 GPU 的收益

ForcedAligner CPU 推理延迟与 ASR 本身相当,严重拖慢整体速度。放到 GPU(forced_aligner_device = "cuda")后,align 耗时降至 0.07–0.33s,几乎可以忽略不计。

建议:有独显的机器一律把 ForcedAligner 放 GPU。

关于 OpenVINO Intel GPU 推理(device = "GPU")

OpenVINO 支持将推理调度到 Intel GPU(iGPU 核显或 Arc 独显),但对 Qwen3-ASR 场景实测性能反而更差,不建议使用。

原因:

Qwen3-ASR decoder 是逐 token autoregressive 推理,每次 decode 只处理 1 个 token,单次计算量极小。GPU 的优势在大 batch 和大矩阵,但此场景下:

  • 每次推理数据量极小,CPU → GPU 显存的调度开销远大于计算收益
  • iGPU(核显)EU 数量有限,并行度优势无法发挥
  • 实测同一硬件(i7-12th Gen)CPU RTF ≈ 0.3,GPU RTF ≈ 1.0(勉强实时)

结论:

推理设备场景建议
device = "CPU"Qwen3-ASR decoder(autoregressive)✅ 推荐,默认值
device = "GPU"Qwen3-ASR decoder❌ 实测更慢,不建议
forced_aligner_device = "cuda"ForcedAligner(PyTorch)✅ 强烈推荐,收益显著

如果想压榨 GPU 利用率,正确姿势是把 ForcedAligner 放到 CUDA GPU,而不是把 OpenVINO 推理切到 Intel GPU。

句子后处理

ASR 输出的原始句子需要经过后处理才能用于字幕显示:

  1. Cutter — 根据 cut_line(停顿阈值)将长句拆成短句
  2. Combiner — 根据 combine_line 将间隔过短的句子合并

两者互为反向操作,建议只启用其中一个。如果同时启用,需要 combine_line > cut_line

数据结构

ASR 结果统一为 Sentence 结构(定义在 types.py),包含:

  • 文本内容
  • 词级时间戳(Word 列表)
  • 起止时间

各引擎的内部输出均会转换为统一的 Sentence 格式,供上层逻辑消费。

与其他模块的关系

  • api/routes/asr_sherpa.py 暴露 Sherpa-ONNX HTTP 接口
  • api/routes/asr_qwen.py 暴露 Qwen3-ASR HTTP 接口
  • api/routes/asr_reload.py 暴露热重载接口
  • api/logic/sherpa_asr.py / api/logic/qwen_asr.py 封装推理逻辑
  • api/clients/asr_client.py 提供客户端封装

魔女の实验室