Files
live-caption/experiments/phase0
blumia 18dbc9c8d3 feat: add real-time caption CLI prototype with Qwen3-ASR
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 验证文档。
2026-10-12 11:40:59 +08:00
..

Phase 0 验证实验

目标:在动手写 C++/Qt 之前,先证实三个关键假设。

  1. 系统播放音频可采集:默认 sink 的 monitor 源能被读到。
  2. Qwen3-ASR 能在这套系统库上跑起来:发行版自带的 llama.cpp 支持 Qwen3-ASR。
  3. CPU 实时性够用:0.6B 量化模型在这台没有独显的机器上能否做到近实时。

环境(实测)

项 值
系统 Deepin 25 (crimson), X11
CPU i5-13420H, 8 核 12 线程
GPU Intel UHD(无 CUDA)
音频 PipeWire 1.6.4 + pipewire-pulse,libpulse 17.0
llama.cpp 系统包 9951+dfsg-1deepin1(libllama0 / libmtmd / libggml0)

关键结论(细节见 ../../docs/phase0-verification.md)

  • 主模型 GGUF 的 general.architecture = qwen3vl → 系统 libllama 有 llama_model_qwen3vl,能加载。
  • mmproj 的 clip.audio.projector_type = qwen3a → 系统 libmtmd 有 clip_graph_qwen3a / mtmd_audio_preprocessor_qwen3a,音频编码器也支持。
  • 转写中英均正确,language <X><asr_text>... 前缀里带语言识别。
  • 稳态 RTF ≈ 0.19(纯推理),实时绰绰有余。

复现步骤

1. 拿到 llama.cpp 的 CLI(不需要 root)

系统只装了库,没装工具,且本机没有免密 sudo。直接从 deb 解包:

cd /tmp/opencode
apt-get download llama.cpp-tools
mkdir -p llama-tools && dpkg-deb -x llama.cpp-tools_*.deb llama-tools
# 运行时必须指定 LD_LIBRARY_PATH(包含 /usr/lib/x86_64-linux-gnu/llama)

2. 下载模型

网络只通了 hf-mirror.com,用 aria2c 多连接(单连接约 3MB/s,多连接可到 19MB/s):

B=https://hf-mirror.com/ggml-org/Qwen3-ASR-0.6B-GGUF/resolve/main
aria2c -x16 -s16 -k4M -o Qwen3-ASR-0.6B-Q8_0.gguf      "$B/Qwen3-ASR-0.6B-Q8_0.gguf"
aria2c -x16 -s16 -k4M -o mmproj-Qwen3-ASR-0.6B-Q8_0.gguf "$B/mmproj-Qwen3-ASR-0.6B-Q8_0.gguf"

换模型时 主模型 + mmproj 必须成对替换。

3. 验证

# 音频采集链路(播放的同时录 monitor)
./loopback_test.sh <某个音频> /tmp/captured_48k.wav
ffmpeg -y -i /tmp/captured_48k.wav -ar 16000 -ac 1 -c:a pcm_s16le /tmp/captured_16k.wav

# 转写 + 测 RTF
./bench.sh /tmp/captured_16k.wav

# 换量化模型对比
MODEL=/tmp/opencode/models/Qwen3-ASR-0.6B-Q4_K_M.gguf ./bench.sh some.wav

# 只读 GGUF 头部元数据(不下载整个文件)
python3 gguf_head.py

已知坑

  • llama-cli 会挂住:不给 -st / 不让 stdin EOF 时,生成完会回到交互读取循环。bench.sh 已用 -st --simple-io </dev/null + 外层 timeout 处理。
  • 输出需清洗:结果形如 language English<asr_text>正文,接入时要把语言名与正文分开(语言名正好喂给 UI 的语言标签)。
  • 发行版 CMake config 路径非标准:/usr/lib/x86_64-linux-gnu/llama/cmake-private/llama-config.cmake,find_package(llama) 默认找不到;它有配套的 pkgconfig/llama.pc,走 pkg-config 更稳。