Files
blumia d234b9658d docs: refresh docs to match the current state, add GUI/CLI/troubleshooting
The README still listed the settings UI as "todo" and its quick start told
users to download models into the working directory; phase 3 still described
the caption window's close button as "quit" and used the wrong binary name.
Bring the docs up to date and fill the gaps: a GUI guide (first run, settings
tabs, tray, download, verify), a full CLI option reference marking the
test-only flags, a troubleshooting page, the model registry's size/sha256
fields plus a licence/size table, the RTF measurement caveat (llama-cli 0.19
vs the in-process 0.56), and a note that the streaming-ONNX backend has its
own code path. phase0/phase1 experiment docs are marked as historical.

文档与现状对齐:README 的 Phase 4 从「待做」改为完成、快速开始不再让人把模型下到当前
目录;phase3 的 ✕ 说明改为「隐藏到托盘」、用法改用 live-caption;新增 GUI/CLI/排错三份
文档;asr-backends 补上注册表的 size/sha256 字段与模型许可/体积表;phase0 补上 RTF 口径
说明(llama-cli 的 0.19 与程序内的 0.56);phase2 补上「流式 ONNX 走另一条分支」的说明。
2026-10-12 17:29:45 +08:00

3.9 KiB
Raw Permalink Blame History

Phase 1:命令行原型

目标:把 docs/phase0-verification.md 验证过的链路写成一个真正的 C++/Qt/CMake 项目骨架,并在命令行跑通「采集系统输出 → 实时转写 → 打印」。 UI 悬浮窗留到 Phase 2。

历史文档:这里记的是 Phase 1 当时的样子。代码后来重排成了 src/core + src/ui + src/models + apps/{gui,cli},入口是 ./build/live-caption(图形界面)和 ./build/live-caption-cli(命令行);模型改成按注册表 data/models.json 取,不再是手工 传 --model/--mmproj。现行用法见 README 与 docs/cli.md。

目录

src/
├─ main.cpp        # CLI 入口、VAD、滑窗策略、稳定前缀提交
├─ qwen3asr.{h,cpp}# 进程内 Qwen3-ASR 封装(libllama + libmtmd)
├─ audio.{h,cpp}   # WAV 读取 + 默认输出 monitor 采集 + libsamplerate 重采样
└─ transcript.{h,cpp} # 解析 `language X<asr_text>正文`,语言显示名映射

构建

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j

依赖:Qt6 Core、libpulse、libsamplerate、系统 llama.cpp(libllama0/libllama-dev,见 Phase 0 报告里的链接注意事项)。

运行

M=/tmp/opencode/models/Qwen3-ASR-0.6B-Q8_0.gguf
MM=/tmp/opencode/models/mmproj-Qwen3-ASR-0.6B-Q8_0.gguf

# 转写单个文件(不需要采集)
./build/live-caption-cli --model $M --mmproj $MM --file test_16k.wav

# 实时字幕(采集默认输出设备的 monitor)
./build/live-caption-cli --model $M --mmproj $MM --threads 8

# 需要看 llama.cpp 日志时加 --verbose

实时输出约定:~ 是预览行(其中稳定前缀为正常色、不稳定尾部为暗色),= 是提交行。

实测结果

文件模式(16k 单声道):

音频 结果
LibriSpeech 英文 10.4s He hoped there would be stew for dinner—turnips and carrots and bruised potatoes and fat mutton pieces—to be ladled out in thick peppered flour-fatted sauce. ✅
AISHELL 中文 3.35s 不排除购房者可以在互联网上下单。 ✅

实时模式(播放上述音频到默认输出,经 monitor 采集转写):

  • 英文/中文均实时正确,语言标签正确显示「英语」「中文」。
  • 每次推理耗时(0.6B Q8_0,8 线程):
窗口时长 计算耗时 RTF
0.8 s ≈0.30 s 0.42
2.5 s ≈0.55 s 0.22
5.9 s ≈1.06 s 0.18
20 s ≈3.59 s 0.18

短窗口 RTF 差是因为有固定开销(prompt 处理 + 音频编码 + 分词),窗口越长越划算。

过程中发现并修复的两个 bug

  1. 丢样本:工作线程每轮只处理 floor(可用样本/320) 帧并丢弃余数,每次唤醒丢约 160 个样本(~20% 音频),造成假静音和句子被截断。修复:跨批次保留残帧。
  2. VAD 噪声底跟错:原先用均值跟踪噪声底,遇到本身就很轻的音频(AISHELL 峰值 RMS 仅 0.028、中位 0.006)会一路抬升阈值,把 77% 的话音判成静音。修复:改为「快降慢升」的最小值跟踪,阈值 = max(floor*3, 0.0015)。

已知问题(留给后续)

  • 强制切窗会诱发模型编结尾:窗口在词中间被切断(到达 max window 或静音点)时,模型会给尾部补一个看似合理的结尾(例如 ...mutton pieces too.)。已在显示层用「稳定前缀提交」缓解(只把跨多次转写一致的前缀当已定文本),但根治要靠模型原生的流式解码:按官方论文的做法,用动态注意力窗口 + 只固定到倒数第 4 个 chunk,尾部 token 不提交。
  • 目前每段独立转写、每次清空 KV cache,因此段与段之间没有上下文。原生流式(复用 KV cache、滑动删除已提交部分)能同时降低延迟和提升连贯性,是 Phase 2 的核心工作(见 ../../docs/phase2-streaming.md)。