Files
live-caption/docs/asr-backends.md
T
blumia bd921b1ac5 feat(asr): add pluggable ONNX streaming backend and model registry
Add a second backend (sherpa-onnx) alongside llama.cpp, so native
streaming models can be selected by ID from a JSON registry. All such
models share one adapter: only the model files and a few options differ.
Models now live under the app data directory and are fetched by
scripts/fetch-models.sh. Adding a model is a data change, not code.

Measured on the same audio: the streaming backend is ~35x cheaper in CPU
than Qwen3-ASR (0.10-0.12 vs 4.27 core-seconds per audio second), shows
the first caption at 0.48-1.44s, and matches its accuracy for zh/en.

新增 sherpa-onnx 流式后端,与 llama.cpp 并存;模型按注册表 id 从应用
数据目录加载。同族模型共用一个适配器,新增模型只改 data/models.json。
实测流式后端 CPU 约为 Qwen3-ASR 的 1/35,首个字幕 0.48~1.44s,中英
准确率持平。注意预编译库是旧 C++ ABI,必须走其 C API。
2026-10-12 16:06:51 +08:00

4.1 KiB
Raw Blame History

推理后端与模型管理

结构:2 个实现覆盖所有模型

实测确认了一件很重要的事:不同模型不需要各写一套代码。所有流式 ONNX 模型走的是同一套 API,差别只是「指向哪个模型文件 + 几行选项」。

IAsr(src/core/iasr.h)
├─ Qwen3Asr        llama.cpp / ggml      GGUF 模型(Qwen3-ASR)        AsrKind::PrefixRollback
└─ SherpaAsr       sherpa-onnx / onnxruntime
                   ├─ X-ASR-zh-en        中英流式
                   ├─ zipformer-zh-2025  中文流式(k2-fsa 官方)
                   └─ Nemotron-3.5       40 语言流式(含日语)        AsrKind::NativeStreaming

两条路径的区别(StreamingAsr 里按 IAsr::kind() 分流):

PrefixRollback NativeStreaming
模型类型 离线模型(LLM 解码器) 有状态流式识别器
上层要做的 切块 + 前缀回滚 + KV 复用 只喂音频,取当前整句文本
每步成本 随句子长度增长 恒定
已稳定/不稳定 用 token 回滚算 用「与上次的公共前缀」算

模型注册表与存储

新增模型 = 加一条数据,不改代码。

  • 注册表:data/models.json(编译进二进制,同时也给脚本用)
  • 存储位置:~/.local/share/live-caption/models/<id>/ (即 QStandardPaths::GenericDataLocation + /live-caption/models)
  • 下载:scripts/fetch-models.sh [id...] / --all;已存在的文件会跳过
./scripts/fetch-models.sh                # 列出模型与安装状态
./scripts/fetch-models.sh zipformer-zh-2025

用法

# 默认后端:llama.cpp + Qwen3-ASR GGUF
./build/live-caption-cli --model M.gguf --mmproj MM.gguf

# 流式 ONNX 后端:按注册表 id 从模型目录取
./build/live-caption-cli --asr-backend sherpa --asr-model zipformer-zh-2025
./build/live-caption-cli --asr-backend sherpa --asr-model nemotron35-560ms --language ja

# 覆盖模型目录 / 语言提示
./build/live-caption-cli --asr-backend sherpa --asr-model ... --model-dir /path/to/models

实测对比(同一批音频,1 线程)

模型 中文 英文 日语 RTF 核·秒/秒音频 首个字幕 体积 许可
Qwen3-ASR 0.6B(llama) ✅ ✅ ✅ 0.56 4.27 ~2.5s 973MB Apache-2.0
zipformer-zh-2025 ✅ — — 0.098 0.10 0.48s 167MB Apache-2.0
X-ASR-zh-en 480ms ✅ ✅ — 0.122 0.12 1.44s 587MB Apache-2.0
Nemotron 3.5 560ms ⚠️ 漏字 ⚠️ 若干错词 ⚠️ 有错字 0.35 0.35 1.12s 651MB OpenMDW-1.1

静态模型(zipformer-zh-2025)的多线程是负优化:onnxruntime 对小模型开多线程, 同步/自旋开销会让它更慢(8 线程比 1 线程慢 2.6 倍、CPU 高 28 倍)。所以适配器里固定 threads = 1。

两个坑

  1. sherpa-onnx 的预编译库是旧 C++ ABI(_GLIBCXX_USE_CXX11_ABI=0),和 Qt 的新 ABI 冲突, C++ API 链接不上。必须用它的 C API(sherpa-onnx/c-api/c-api.h,extern "C",无名字改写)。
  2. 结束时要补一小段静音(streamFinish() 里补 0.3s)再 InputFinished,否则最后一个字会被截掉。

自动语言识别

模型 自带 LID
Qwen3-ASR ✅ 输出 language X(实测中英都准)
Nemotron 3.5 ✅ language=auto,但实测会串(日语开头吐韩文)
X-ASR / zipformer ❌ 固定语言对,不出语言标签

LID 不必由 ASR 模型提供:Chrome 就带了个独立的 2.5MB ONDEVICE_langid.tflite(我们在它的语言包目录里看到了), Windows 同样。sherpa-onnx 也有专门的语种识别模型。所以**「按语言装包 + 用户选语言或小 LID 模型」**是可行路线。

推荐组合(按语言装包)

语言 实时预览 定稿
中文 zipformer-zh-2025(最快最准) Qwen3-ASR
英文 xasr-zh-en-480 Qwen3-ASR
日语 nemotron35-560ms --language ja(质量一般) Qwen3-ASR(开源日语第一)
其他 — Qwen3-ASR(52 语言兜底)