Add a C++/Qt6/CMake CLI prototype that captures the default sink monitor through libpulse and transcribes it in-process with Qwen3-ASR via libllama/libmtmd. Add phase 0/1 verification docs. 新增实时字幕命令行原型:libpulse 采集默认输出 monitor,进程内用 libllama/libmtmd 跑 Qwen3-ASR 推理。附阶段 0/1 验证文档。
5.9 KiB
5.9 KiB
Phase 0 验证报告
结论:方案成立。系统播放音频可采集、Qwen3-ASR 可在这套系统库上运行、CPU 实时性有充足余量。可以进入实现阶段。
验证日期:2026-10-12 设备:i5-13420H / 15GB / Intel UHD(无独显)/ Deepin 25 / X11
1. 验证结论一览
| # | 假设 | 结论 | 证据 |
|---|---|---|---|
| 1 | 系统播放的声音可采集 | ✅ | 默认 sink 的 .monitor 源录到真实音频(mean −29.6dB / max −6.7dB) |
| 2 | Qwen3-ASR 能在本机跑 | ✅ | 主模型 arch qwen3vl ← libllama 的 llama_model_qwen3vl;mmproj clip+qwen3a ← libmtmd 的 clip_graph_qwen3a |
| 3 | 端到端链路可用 | ✅ | 播放 → monitor 采集 → 16k 单声道 → 转写,文本正确 |
| 4 | 中文可用 + 语言自动检测 | ✅ | language Chinese<asr_text>不排除购房者可以在互联网上下单。 |
| 5 | CPU 实时性够用 | ✅ | 纯推理 RTF ≈ 0.19;2s 音频约 0.3s |
| 6 | 纯 C++、无 Python | ✅ | 全程 llama.cpp C/C++ 库 |
2. 关键实测数据
环境:-t 8(i5-13420H 8 核),模型 Qwen3-ASR-0.6B-Q8_0 + mmproj-...-Q8_0。
| 项目 | 结果 |
|---|---|
| 模型加载(一次性) | ≈ 4.6 s |
| 纯推理 RTF | ≈ 0.19(约 3.8× 实时) |
| 62.6s 音频总耗时 | 16.48 s(含加载) |
| 单块 2s 音频 | 墙钟 ≈ 4.9 s − 加载 4.6 s ⇒ 计算 ≈ 0.3 s |
| 英文准确率 | 与 LibriSpeech 标准答案逐词一致 |
| 中文准确率 | 与 AISHELL-1 标准答案一致(仅多了标点) |
流式含义:模型常驻内存时,处理 2 秒窗口约 0.3 s,滑动窗口 + 提交策略下端到端延迟可做到 ~1 s 级,与 Chrome 实时字幕同量级。
2.1 0.6B vs 1.7B 实测对比
均为 Q8_0 主模型 + Q8_0 mmproj,-t 8。
| 指标 | 0.6B | 1.7B |
|---|---|---|
| 加载耗时 | 4.6 s | 6.2 s |
| 纯推理 RTF | 0.19(≈3.8× 实时) | 0.385(≈2.6× 实时) |
| 62.6s 音频墙钟 | 16.5 s | 30.2 s |
| 单块 2s 计算量 | ≈0.3 s | ≈0.77 s |
| 内存(主+mmproj) | ≈0.97 GB | ≈2.42 GB |
| 中文 | ✅ 正确 | ✅ 正确 |
| 英文 | flour-fatted sauce ✅ |
flour-fattened sauce ❌ |
结论:
- 两个尺寸在本机都能实时,1.7B 余量更小(2.6× 实时)。
- 1.7B 在这段英文上反而不如 0.6B(
flour-fatted→flour-fattened)。单样本不能定论,但足以说明默认应选 0.6B,1.7B 作为可选并加性能/内存提示。 - 若某台机器连 0.6B 都吃力,可自行用
llama-quantize从官方 Q8_0/bf16 转 Q4_K_M(注意:不能直接用社区量化,架构标记不兼容)。
3. 转写输出格式(接入时必须清洗)
原始输出形如:
language English<asr_text>He hoped there would be stew for dinner...
language Chinese<asr_text>不排除购房者可以在互联网上下单。
解析规则:language <LANG><asr_text><正文>。<LANG> 直接喂给 UI 左上角的语言标签,正文才算字幕。注意 <LANG> 在中文时是 Chinese,需做 中文 一类的显示映射。
4. 兼容性风险(重要)
Qwen3-ASR 的 GGUF 架构标记正在变动,各家不一致:
| 来源 | general.architecture |
发行版 b9951 |
|---|---|---|
| ggml-org/Qwen3-ASR-0.6B / 1.7B(官方转换) | qwen3vl |
✅ 可加载 |
| cstr/qwen3-asr-0.6b-q4_k | qwen3asr |
❌ unknown model architecture |
| handy-computer/Qwen3-ASR-0.6B-* | qwen3_asr |
❌ unknown model architecture |
**结论:模型与推理运行时必须成对锁定版本。**只使用 ggml-org 官方 GGUF,或自行用同版本的 llama-quantize 从官方 GGUF 转换。
Q4_K_M(590MB)这类小体积量化目前只有社区版,不兼容;llama-quantize 可用(在 llama.cpp-tools 里),需要时自行从官方 Q8_0/bf16 转换。当前 Q8_0 的 RTF 0.19 已足够,Q4 非必需。
5. 环境与工具链实测
- 音频:PipeWire 1.6.4 + pipewire-pulse;
libpulse17.0 开发包齐全。用 libpulse 而非 PipeWire 原生 API → 同时兼容 PipeWire / PulseAudio。 - llama.cpp:系统包
9951+dfsg-1deepin1(libllama0含libllama/libmtmd/libllama-common;libllama-dev含llama.h/mtmd.h/mtmd-helper.h)。 - 无免密 sudo:不能装包。但
llama.cpp-tools的 deb 可直接dpkg-deb -x解包使用,无需 root。开发期靠这个。 - CMake 集成注意:
llama-config.cmake在非标准路径/usr/lib/x86_64-linux-gnu/llama/cmake-private/(find_package(llama)默认找不到)。- 同目录有
pkgconfig/llama.pc,但只列了-lggml -lggml-base -lllama,缺-lmtmd,需要手动补。 ggml的 cmake config 和ggml.pc在标准位置,正常可找到。
- 网络:只有
hf-mirror.com可达(huggingface.co / github.com 不通)。下载用 aria2c 多连接:19 MiB/s vs 单连接 3 MiB/s。
6. 踩过的坑
llama-cli会挂住:不给-st且不让 stdin EOF 时,生成完会回到交互读取循环。解法:-st --simple-io </dev/null+ 外层timeout。- Debian 的
llama-cli内部其实跑的是 server(错误日志里出现srv load_model、llama_server exited)。这提示:Phase 1 若不想自己驱动 libllama 的解码循环,用llama-server子进程 + 本地接口也是合理选项。 - 下载大文件时不要开两个 curl 并行(互相拖累到 ~0.3MB/s)。
7. 对后续设计的影响
- 采集层:
libpulse+ 默认 sink 的 monitor,需订阅设备变更事件跟随默认输出。 - 推理层:
AsrBackend接口;先用 ggml-org 的qwen3vl版 GGUF;模型+mmproj 成对管理;输出解析要处理language/asr_text前缀。 - 延迟策略:模型常驻,2s 滑窗,每 ~0.5–1s 提交一次;目标是端到端 ~1s。
- 打包:模型体积(Q8_0 768MB + mmproj 205MB)需要下载或按需获取策略;不能默认内置进包。
8. 复现
见 ../../experiments/phase0/README.md。