2026-10-12 11:40:59 +08:00
|
|
|
|
# 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) |
|
2026-10-12 13:01:26 +08:00
|
|
|
|
| Phase 2 | 原生流式解码(8s 切片 + 增量 KV 复用 + 前缀回滚) | ✅ 见 [docs/phase2-streaming.md](docs/phase2-streaming.md) |
|
2026-10-12 13:32:16 +08:00
|
|
|
|
| Phase 3 | Qt 悬浮字幕窗(折叠/展开、语言标签、置顶、实时链路) | ✅ 见 [docs/phase3-caption-window.md](docs/phase3-caption-window.md) |
|
2026-10-12 11:40:59 +08:00
|
|
|
|
| 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
|
|
|
|
|
|
|
2026-10-12 16:30:00 +08:00
|
|
|
|
# 3. 悬浮字幕窗(首次启动会打开设置对话框,引导下载并选择模型)
|
|
|
|
|
|
./build/live-caption
|
|
|
|
|
|
|
|
|
|
|
|
# 完全通过 GUI 操作:
|
|
|
|
|
|
# · 首次启动 → 设置对话框:下载模型 / 选择当前使用 / 选识别语言 / 下载源与代理
|
|
|
|
|
|
# · 点左上角的语言标签 → 再次打开设置
|
|
|
|
|
|
# · 托盘图标:显示/隐藏字幕、设置、退出
|
|
|
|
|
|
# · 窗口的 ✕ = 隐藏到托盘(用托盘菜单可以再显示回来)
|
|
|
|
|
|
# 命令行参数仍保留,仅用于自动化测试(显式给出时覆盖设置),例如:
|
|
|
|
|
|
# ./build/live-caption --asr-backend sherpa --asr-model zipformer-zh-2025 --no-tray
|
2026-10-12 13:43:50 +08:00
|
|
|
|
|
|
|
|
|
|
# 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
|
2026-10-12 11:40:59 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-10-12 16:06:51 +08:00
|
|
|
|
## 推理后端
|
|
|
|
|
|
|
|
|
|
|
|
支持两条后端,用 `--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`
|
2026-10-12 16:30:00 +08:00
|
|
|
|
(**加模型只加一条数据,不改代码**)。GUI 里可以直接下载(支持设置下载源与代理、
|
|
|
|
|
|
断点续传),命令行下也可以用 `scripts/fetch-models.sh`。
|
2026-10-12 16:06:51 +08:00
|
|
|
|
|
|
|
|
|
|
```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
|
2026-10-12 17:03:20 +08:00
|
|
|
|
|
|
|
|
|
|
# 辅助
|
|
|
|
|
|
./build/live-caption-cli --list-devices # 列出可选采集设备
|
|
|
|
|
|
./build/live-caption-cli --cli-live --device <sink> # 指定采集源
|
|
|
|
|
|
./build/live-caption-cli --verify-model <id> # 校验模型完整性
|
2026-10-12 16:06:51 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-10-12 13:43:50 +08:00
|
|
|
|
## 代码结构
|
2026-10-12 11:40:59 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
2026-10-12 13:43:50 +08:00
|
|
|
|
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 的验证脚本
|
2026-10-12 11:40:59 +08:00
|
|
|
|
```
|
2026-10-12 13:43:50 +08:00
|
|
|
|
|
|
|
|
|
|
拆分的意义:**业务逻辑全在 core 且不依赖 Qt**,所以流式策略、VAD、输出解析这些最容易出错的部分可以脱离真模型和显示环境做单元测试;GUI 与 CLI 各自独立演进,CLI 也不再需要链接 Qt Widgets。
|