Files
live-caption/README.md
T
blumia a7a6f3e6b6 feat(gui): drive everything from settings, add tray and in-app download
The GUI no longer needs command line arguments: on first run it opens a
settings dialog that lists the registry, downloads models in-app (mirror
base, HTTP proxy, resume), and picks the active model. The caption window
gains a tray icon (show/hide, settings, quit); its close button hides to
the tray so the window can always be brought back, and the language pill
opens the settings. Appearance (font, opacity, line counts, position) is
persisted. CLI flags remain for automated testing and override settings.

GUI 不再依赖命令行参数:首次启动打开设置对话框,可在应用内下载模型
(下载源/代理/断点续传)、选择当前模型与识别语言;字幕窗增加托盘(显示
隐藏/设置/退出),关闭按钮改为隐藏到托盘以免关掉后无法再打开,语言标签
点击进设置;字号/透明度/行数/位置都会持久化。命令行参数保留作自动化测试。
2026-10-12 16:30:00 +08:00

96 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# live-caption
Linux 桌面实时字幕:采集系统正在播放的声音,实时转写成字幕显示(类似 Chrome 实时字幕)。
技术栈:C++ / Qt6 / CMake / Qwen3-ASR(llama.cpp,纯 C++,无 Python 依赖)。
## 当前进度
| 阶段 | 内容 | 状态 |
|---|---|---|
| Phase 0 | 可行性验证(采集 / 模型 / CPU 实时性) | ✅ 见 [docs/phase0-verification.md](docs/phase0-verification.md) |
| Phase 1 | 命令行原型(进程内推理 + monitor 采集 + 滑窗 + 稳定前缀) | ✅ 见 [experiments/phase1/README.md](experiments/phase1/README.md) |
| Phase 2 | 原生流式解码(8s 切片 + 增量 KV 复用 + 前缀回滚) | ✅ 见 [docs/phase2-streaming.md](docs/phase2-streaming.md) |
| Phase 3 | Qt 悬浮字幕窗(折叠/展开、语言标签、置顶、实时链路) | ✅ 见 [docs/phase3-caption-window.md](docs/phase3-caption-window.md) |
| Phase 4 | 设置界面(模型切换、语言、字体、位置) | 待做 |
| Phase 5 | Wayland 支持、打包、模型分发 | 待做 |
## 关键结论(Phase 0 实测)
- 系统播放音频可从默认输出的 monitor 源采集(PipeWire + pipewire-pulse,走 libpulse,兼容 PulseAudio)。
- `Qwen3-ASR-0.6B` 在本机(i5-13420H,无独显)纯推理 RTF ≈ **0.19**,实时有充足余量。
- 模型与推理运行时**必须锁版本**:只有 ggml-org 官方 GGUF(`general.architecture = qwen3vl`)与系统 llama.cpp 兼容;社区的 Q4 量化用的是 `qwen3asr` / `qwen3_asr`,装不进去。
- 转写原始输出为 `language <LANG><asr_text><正文>`,语言名正好用于 UI 的语言标签。
## 快速开始
```bash
# 1. 准备模型(只需一次;网络可达 hf-mirror.com)
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"
# 2. 构建
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
# 3. 悬浮字幕窗(首次启动会打开设置对话框,引导下载并选择模型)
./build/live-caption
# 完全通过 GUI 操作:
# · 首次启动 → 设置对话框:下载模型 / 选择当前使用 / 选识别语言 / 下载源与代理
# · 点左上角的语言标签 → 再次打开设置
# · 托盘图标:显示/隐藏字幕、设置、退出
# · 窗口的 ✕ = 隐藏到托盘(用托盘菜单可以再显示回来)
# 命令行参数仍保留,仅用于自动化测试(显式给出时覆盖设置),例如:
# ./build/live-caption --asr-backend sherpa --asr-model zipformer-zh-2025 --no-tray
# 4. 命令行:单文件转写 / 流式转写 / 无窗口实时
./build/live-caption-cli --model M --mmproj MM --file some_16k_mono.wav
./build/live-caption-cli --model M --mmproj MM --stream-file some_16k_mono.wav
./build/live-caption-cli --model M --mmproj MM --cli-live
# 5. 单元测试(不需要模型,也不需要显示环境)
ctest --test-dir build --output-on-failure
```
## 推理后端
支持两条后端,用 `--asr-backend` 切换(详见 [docs/asr-backends.md](docs/asr-backends.md)):
- **`llama`(默认)**:llama.cpp/ggml + Qwen3-ASR 的 GGUF 模型 —— 准确率高、52 种语言,但每步成本随段落增长。
- **`sherpa`**:sherpa-onnx + 流式 ONNX 模型(X-ASR / zipformer / Nemotron) —— 原生流式,每步成本恒定,CPU 约为前者的 1/35,中英准确率持平。
模型都放在 `~/.local/share/live-caption/models/`,注册表是 `data/models.json`
(**加模型只加一条数据,不改代码**)。GUI 里可以直接下载(支持设置下载源与代理、
断点续传),命令行下也可以用 `scripts/fetch-models.sh`。
```bash
# 流式后端
./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
```
## 代码结构
```
src/core/ → liblivecaption_core(静态库,**不依赖 Qt**)
iasr.h 推理后端抽象(便于用假实现测流式策略)
transcript.{h,cpp} 输出解析、语言名映射
audio.{h,cpp} monitor 采集 / WAV 读取 / 重采样
qwen3asr.{h,cpp} 进程内推理(libllama + libmtmd)
streamingasr.{h,cpp} 流式策略(8s 切片复用、前缀回滚、分段)
vad.h 能量 VAD
livepipeline.{h,cpp} 实时管线:采集→VAD→分段→流式转写
src/ui/ → liblivecaption_ui(静态库,Qt6::Widgets)
captionwindow.{h,cpp} 悬浮字幕窗
livetranscriber.{h,cpp} LivePipeline 的 Qt 适配器(只转信号)
apps/gui/ → live-caption (悬浮窗程序)
apps/cli/ → live-caption-cli (命令行程序,只链 Qt6::Core)
apps/common/ 两个程序共用的命令行选项
tests/ → 单元测试(QtTest,只链 core)
docs/ 各阶段说明与验证报告
experiments/ Phase 0/1 的验证脚本
```
拆分的意义:**业务逻辑全在 core 且不依赖 Qt**,所以流式策略、VAD、输出解析这些最容易出错的部分可以脱离真模型和显示环境做单元测试;GUI 与 CLI 各自独立演进,CLI 也不再需要链接 Qt Widgets。