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 走另一条分支」的说明。
This commit is contained in:
1 parent
370c869ad0
commit
d234b9658d
12 files changed
+512
-57
No files matched your search
+36
-6
@@ -29,13 +29,44 @@ IAsr(src/core/iasr.h)
|
||||
- 注册表:`data/models.json`(编译进二进制,同时也给脚本用)
|
||||
- 存储位置:`~/.local/share/live-caption/models/<id>/`
|
||||
(即 `QStandardPaths::GenericDataLocation + /live-caption/models`)
|
||||
- 下载:`scripts/fetch-models.sh [id...]` / `--all`;已存在的文件会跳过
|
||||
- 下载:GUI 的「模型 → 下载」,或 `scripts/fetch-models.sh [id...]` / `--all`;已存在的文件会跳过
|
||||
|
||||
```bash
|
||||
./scripts/fetch-models.sh # 列出模型与安装状态
|
||||
./scripts/fetch-models.sh zipformer-zh-2025
|
||||
```
|
||||
|
||||
一条模型长这样:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "zipformer-zh-2025",
|
||||
"name": "中文流式(k2-fsa 官方 2025-06-30)",
|
||||
"backend": "sherpa-online", // llama-cpp | sherpa-online
|
||||
"languages": ["zh"],
|
||||
"license": "Apache-2.0",
|
||||
"note": "167MB,最快最准的中文流式模型",
|
||||
"files": {
|
||||
"encoder": { "name": "encoder.int8.onnx", "url": "https://...", "size": 161000000, "sha256": "5ac5..." },
|
||||
"tokens": { "name": "tokens.txt", "url": "https://...", "size": 3000, "sha256": "6193..." }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`size` / `sha256` 就是完整性校验的依据:**打开/选择模型时只比大小**(快),
|
||||
「校验完整性」或 `--verify-model` 才**重算 sha256**(慢,但能发现内容损坏)。
|
||||
|
||||
## 模型清单
|
||||
|
||||
| id | 语言 | 后端 | 许可 | 体积 | sha256(首个文件,前 16 位) |
|
||||
|---|---|---|---|---|---|
|
||||
| `qwen3-asr-0.6b-q8` | 52 语言 | llama-cpp | Apache-2.0 | 1019MB | `bca259818b50ca7c…` |
|
||||
| `zipformer-zh-2025` | zh | sherpa-online | Apache-2.0 | 167MB | `5ac51e27981bb4da…` |
|
||||
| `xasr-zh-en-480` | zh, en | sherpa-online | Apache-2.0 | 615MB | `0c3454033d249081…` |
|
||||
| `nemotron35-560ms` | 16 语言(含 ja) | sherpa-online | OpenMDW-1.1 | 682MB | `012e9321373af990…` |
|
||||
|
||||
分发包模型时记得带上许可(尤其 Nemotron 是 OpenMDW-1.1,不是 Apache-2.0)。
|
||||
|
||||
## 用法
|
||||
|
||||
```bash
|
||||
@@ -65,14 +96,13 @@ IAsr(src/core/iasr.h)
|
||||
|
||||
## 设置对话框
|
||||
|
||||
三个页签(模型 / 显示 / 高级),底部三个按钮:
|
||||
|
||||
- **应用**:应用设置但**不关闭**对话框,方便实时预览(改不透明度、字号时会立刻看到效果);
|
||||
- **取消**:放弃本次改动;
|
||||
- **确定**:应用并关闭。
|
||||
三个页签(模型 / 显示 / 高级),底部三个按钮 **应用 / 取消 / 确定** ——
|
||||
「应用」= 应用但不关闭,方便实时预览(改不透明度、字号时会立刻看到效果)。
|
||||
|
||||
只有**模型 / 识别语言 / 采集设备**变化才会重启识别后端;透明度、字号、行数、位置这类外观改动是即时生效的,不会打断正在进行的转写。
|
||||
|
||||
各设置项的完整说明见 [gui.md](gui.md)。
|
||||
|
||||
## 采集设备选择
|
||||
|
||||
默认跟随系统默认输出;也可以在设置里指定某个输出设备(`--list-devices` 可列出):
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
# 命令行选项
|
||||
|
||||
两个程序:
|
||||
|
||||
- **`live-caption`** —— 图形界面(悬浮窗 + 托盘 + 设置)。**日常使用不需要任何参数**;
|
||||
下面的参数里,它只关心「后端与模型」「流式参数」「GUI 专用 / 测试专用」几节。
|
||||
- **`live-caption-cli`** —— 命令行版,只链 Qt6::Core,适合无显示环境、脚本、CI。
|
||||
|
||||
两边共用的选项定义在 `apps/common/appcli.h`。
|
||||
`--help` 会用「(默认 X)」把默认值印在说明里。
|
||||
|
||||
## 后端与模型
|
||||
|
||||
| 选项 | 默认 | 说明 |
|
||||
|---|---|---|
|
||||
| `--asr-backend <kind>` | `llama` | `llama`(Qwen3-ASR GGUF)或 `sherpa`(流式 ONNX) |
|
||||
| `--asr-model <id>` | — | 模型注册表(`data/models.json`)里的 id;sherpa 后端用它定位文件,llama 后端也可用它走注册表 |
|
||||
| `--model <path>` | — | 主模型 GGUF 路径(架构须为 `qwen3vl`) |
|
||||
| `--mmproj <path>` | — | mmproj GGUF 路径(clip + qwen3a) |
|
||||
| `--model-dir <dir>` | `~/.local/share/live-caption/models` | 覆盖模型存储目录 |
|
||||
| `--language <lang>` | 空 = 自动 | 语言提示(`zh` / `en` / `ja` …),多语言模型需要 |
|
||||
| `--threads <n>` | `8` | 推理线程数(只影响 Qwen3-ASR;流式模型固定单线程) |
|
||||
| `--verbose` | 关 | 输出 llama.cpp / mtmd 的详细日志 |
|
||||
|
||||
> 模型「未安装」时会提示缺失的文件名,并给出 `scripts/fetch-models.sh <id>` 的提示。
|
||||
|
||||
## 流式参数
|
||||
|
||||
参数的选择与实测见 [docs/phase2-streaming.md](phase2-streaming.md)。
|
||||
**这些参数只影响 `llama` 后端**(Qwen3-ASR);`sherpa` 的流式模型只用到「提交粒度」一个参数。
|
||||
|
||||
| 选项 | 默认 | 说明 |
|
||||
|---|---|---|
|
||||
| `--stream-chunk <sec>` | `2.0` | 累积多少秒音频跑一步(提交粒度) |
|
||||
| `--stream-mode <mode>` | `incremental` | `incremental`(增量 KV 复用)/ `append`(追加式)/ `window`(滑窗) |
|
||||
| `--stream-window <sec>` | `16` | 滑窗上限;仅 `window` 模式,`0` = 不滑窗 |
|
||||
| `--stream-segment <sec>` | `30` | 单段最长时长,超过就提交并重置上下文;`0` = 不限 |
|
||||
| `--unfixed-tokens <n>` | `5` | 前缀回滚:丢掉最后 N 个 token(这些算「不稳定尾部」) |
|
||||
| `--unfixed-chunks <n>` | `2` | 前 N 个 chunk 不带前缀(冷启动) |
|
||||
| `--max-tokens <n>` | `256` | 单段最多生成 token 数 |
|
||||
|
||||
## 运行模式(仅 `live-caption-cli`)
|
||||
|
||||
| 选项 | 说明 |
|
||||
|---|---|
|
||||
| `--file <path>` | 整段转写一个 WAV 后退出(离线精度基线) |
|
||||
| `--stream-file <path>` | 以流式模式转写一个 WAV 后退出(验证流式策略) |
|
||||
| `--cli-live` | 实时转写并只在命令行输出(不开窗口),用于无显示环境 |
|
||||
|
||||
## 采集
|
||||
|
||||
| 选项 | 说明 |
|
||||
|---|---|
|
||||
| `--device <sink>` | 采集源(输出设备的 sink 名);留空 = 跟随系统默认输出 |
|
||||
| `--list-devices` | 列出可选的采集设备后退出(仅 `live-caption-cli`) |
|
||||
|
||||
```bash
|
||||
./build/live-caption-cli --list-devices
|
||||
# alsa_output...HiFi__Speaker__sink ... Speaker [默认]
|
||||
# alsa_output...HiFi__HDMI1__sink ... HDMI / DisplayPort 1 Output
|
||||
./build/live-caption-cli --asr-model zipformer-zh-2025 --cli-live --device alsa_output...HiFi__HDMI1__sink
|
||||
```
|
||||
|
||||
## 辅助
|
||||
|
||||
| 选项 | 说明 |
|
||||
|---|---|
|
||||
| `--verify-model <id>` | 重算 sha256 校验模型完整性后退出(仅 `live-caption-cli`) |
|
||||
|
||||
```bash
|
||||
./build/live-caption-cli --verify-model zipformer-zh-2025
|
||||
# ✅ 中文流式(k2-fsa 官方 2025-06-30) 校验通过
|
||||
```
|
||||
|
||||
## GUI 专用 / 测试专用
|
||||
|
||||
这些只在 `live-caption` 上有效。**除 `--opacity` 外都是给自动化测试用的**,
|
||||
平时不需要:界面本身提供这些功能。
|
||||
|
||||
| 选项 | 默认 | 说明 |
|
||||
|---|---|---|
|
||||
| `--opacity <n>` | — | 背景不透明度(20–100),覆盖设置里的值 |
|
||||
| `--no-tray` | — | 不创建托盘图标(测试用;此时 `✕` 会直接退出) |
|
||||
| `--screenshot <path>` | — | 启动后自动截图并退出;同时截折叠态与展开态(`-expanded.png`) |
|
||||
| `--screenshot-delay <sec>` | `6` | 截图前等待秒数 |
|
||||
| `--screenshot-settings <path>` | — | 打开设置对话框、截图后退出 |
|
||||
| `--settings-autoclose <how>` | — | 自动操作设置对话框:`reject` / `close` / `accept` / `ok` / `apply`(`ok`/`apply` 是真的去点按钮) |
|
||||
| `--quit-after <sec>` | — | 运行若干秒后优雅退出(测退出路径) |
|
||||
|
||||
`--settings-autoclose` + `--quit-after` 是当初定位「点确定程序就退出」崩溃时留下的复现手段,
|
||||
也可以当作界面交互的冒烟测试:
|
||||
|
||||
```bash
|
||||
for how in reject close accept ok apply; do
|
||||
./build/live-caption --asr-model zipformer-zh-2025 --no-tray \
|
||||
--settings-autoclose $how --quit-after 8
|
||||
echo "$how → 退出码 $?"
|
||||
done
|
||||
```
|
||||
|
||||
## 退出码
|
||||
|
||||
| 码 | 含义 |
|
||||
|---|---|
|
||||
| `0` | 正常结束(含 `--screenshot*`、`--quit-after` 的优雅退出) |
|
||||
| `1` | 启动失败:模型没加载起来(`live-caption-cli` 的 `--verify-model` 校验失败也是 1) |
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
# 图形界面(Phase 4)
|
||||
|
||||
`live-caption` 是图形界面程序:悬浮字幕窗 + 系统托盘 + 设置对话框。
|
||||
**不用任何命令行参数就能完整使用**;命令行参数只保留给自动化测试(显式给出时覆盖设置)。
|
||||
|
||||
## 首次运行
|
||||
|
||||
首次启动时如果还没有「已下载且被选中」的模型,程序会先弹出**设置对话框(标题为
|
||||
「实时字幕 — 首次配置」)**,并挡住主流程 —— 下载一个模型、在「当前使用」里选中它,
|
||||
点「确定」之后才会出现字幕窗。
|
||||
|
||||
```
|
||||
第一次启动 → 设置对话框 → 下载模型 → 选择「当前使用」 → 确定 → 悬浮字幕窗
|
||||
```
|
||||
|
||||
## 字幕窗
|
||||
|
||||
| 操作 | 行为 |
|
||||
|---|---|
|
||||
| 拖动 | 移动窗口;位置会被记住 |
|
||||
| 左上角语言标签 | 点击 → 打开设置对话框 |
|
||||
| 底部箭头 `⌄` / `⌃` | 折叠(2 行)/ 展开(8 行) |
|
||||
| 右上角 `✕` | **隐藏到托盘**(不是退出;用托盘菜单可以再显示回来) |
|
||||
|
||||
窗口的文本分两段显示:**已稳定**部分是白色,**尚未稳定**的尾部是灰色。这就是 Chrome
|
||||
实时字幕那种「字一个个长出来、末尾会改」的观感。
|
||||
|
||||
> 没有托盘时(`--no-tray`,或桌面环境不支持托盘)`✕` 会直接退出程序。
|
||||
|
||||
## 托盘
|
||||
|
||||
托盘菜单有三项:
|
||||
|
||||
- **显示/隐藏字幕**
|
||||
- **设置…**
|
||||
- **退出**
|
||||
|
||||
单击托盘图标也会切换字幕窗的显示/隐藏。
|
||||
|
||||
## 设置对话框
|
||||
|
||||
三个页签(模型 / 显示 / 高级),底部三个按钮:
|
||||
|
||||
| 按钮 | 行为 |
|
||||
|---|---|
|
||||
| **应用** | 应用设置但**不关闭**对话框 —— 方便实时预览(改不透明度、字号时立刻能看到效果) |
|
||||
| 取消 | 放弃本次改动(已经用「应用」生效过的改动不会被回滚) |
|
||||
| 确定 | 应用并关闭 |
|
||||
|
||||
**哪些改动要重启识别后端?** 只有**模型 / 识别语言 / 采集设备**这三项变化时才会重建后端并重启转写;
|
||||
透明度、字号、行数、灰色尾部这类外观改动是即时生效的,不会打断正在进行的转写。
|
||||
|
||||
### 模型页
|
||||
|
||||
- **模型表格**:列出注册表里的所有模型(名称 / 语言 / 许可 / 状态)。第一列是注册表 id,
|
||||
状态列显示「已安装 / 未安装」,未安装时鼠标悬停会列出缺失的文件名。
|
||||
- **下载**:把选中的模型下到 `~/.local/share/live-caption/models/<id>/`。
|
||||
支持设置下载源(镜像)与代理、断点续传、实时进度。下载完成会自动刷新列表。
|
||||
- **校验完整性**:对选中模型的所有文件**重算 sha256**,与注册表里的期望值比对;
|
||||
失败会列出损坏的文件名(可删除后重新下载)。文件大时需要几秒。
|
||||
- **删除**:删掉该模型已下载的文件。如果删的正是「当前使用」的模型,选择会被清空。
|
||||
- **打开模型目录**:在文件管理器里打开模型存储目录。
|
||||
- **采集设备**:默认「跟随系统默认输出」(即当前默认输出的 monitor)。
|
||||
也可以指定某个具体输出设备(如 HDMI);列不出来或没列全时见
|
||||
[troubleshooting.md](troubleshooting.md)。
|
||||
- **当前使用**:选择实际生效的模型(只列出**已安装**的)。
|
||||
- **识别语言**:语言提示,多语言模型用它(例如 Nemotron 需要指定语言才不出错);
|
||||
「自动检测」= 留空。目前提供 自动/中文/英文/日语。
|
||||
- **下载源**:默认 `https://hf-mirror.com`(网络可达性最好的镜像);可改成其它镜像或官方源。
|
||||
- **代理**:不使用 / 跟随系统 / 手动设置(主机、端口、用户名、密码)。
|
||||
|
||||
### 显示页
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| 字号 | 字幕文字大小(9–40) |
|
||||
| 用灰色显示尚未稳定的尾部 | 关掉后就只显示已稳定的文本 |
|
||||
| 折叠行数 / 展开行数 | 折叠态与展开态各显示几行 |
|
||||
| 背景不透明度 | 20%–100%,默认 84%(纯黑底,保证任何桌面背景下文字都可读) |
|
||||
|
||||
### 高级页
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| 更新粒度(秒) | 累积多少秒音频跑一步;「自动」= 由后端决定(流式模型 0.32s) |
|
||||
| 线程数 | 推理线程数;**只影响 Qwen3-ASR**,流式模型固定单线程(多线程反而更慢) |
|
||||
|
||||
## 配置文件
|
||||
|
||||
所有设置存在 `QSettings` 里:`~/.config/live-caption/live-caption.conf`,组名 `[app]`。
|
||||
|
||||
```ini
|
||||
[app]
|
||||
modelId=zipformer-zh-2025 ; 当前使用的模型 id
|
||||
language= ; 空 = 自动
|
||||
captureDevice= ; 空 = 跟随系统默认输出
|
||||
opacity=84 fontSize=15 ; 外观
|
||||
showUnstableTail=true
|
||||
collapsedLines=2 expandedLines=8
|
||||
windowX=179 windowY=725 ; 拖动后记录的位置
|
||||
mirrorBase=https://hf-mirror.com
|
||||
proxyMode=0 ; 0=不使用 1=跟随系统 2=手动
|
||||
chunkSec=0 threads=8 ; 高级
|
||||
```
|
||||
|
||||
删掉这个文件(或其中某个键)就回到默认值。模型文件在
|
||||
`~/.local/share/live-caption/models/<id>/`,不受这个文件影响。
|
||||
|
||||
## 自动化测试钩子(仅测试用)
|
||||
|
||||
界面本身的行为可以完全用命令行脚本驱动,这些选项平时用不到:
|
||||
|
||||
```bash
|
||||
# 打开设置对话框并截图后退出
|
||||
./build/live-caption --screenshot-settings /tmp/settings.png
|
||||
|
||||
# 自动关掉设置对话框,用来测「关闭/确定/取消/应用」各条路径是否崩溃
|
||||
./build/live-caption --asr-model zipformer-zh-2025 --no-tray \
|
||||
--settings-autoclose {reject|close|accept|ok|apply} --quit-after 8
|
||||
|
||||
# 字幕窗自截图(折叠态 + 展开态)
|
||||
./build/live-caption --asr-model zipformer-zh-2025 --no-tray \
|
||||
--screenshot /tmp/win.png --screenshot-delay 6
|
||||
```
|
||||
|
||||
完整列表见 [cli.md](cli.md)。
|
||||
@@ -32,6 +32,11 @@
|
||||
|
||||
> 流式含义:模型常驻内存时,处理 2 秒窗口约 0.3 s,滑动窗口 + 提交策略下端到端延迟可做到 **~1 s 级**,与 Chrome 实时字幕同量级。
|
||||
|
||||
> **口径提示**:本页的 RTF ≈ 0.19 是 **`llama-cli` 纯生成**(`-t 8`)的数字。
|
||||
> 程序内走 `libmtmd` 音频编码的实现,实测 RTF ≈ **0.56**(单线程,见
|
||||
> [asr-backends.md](asr-backends.md#实测对比同一批音频1-线程));两个口径都远低于 1.0,
|
||||
> 但引用数字时要注意区分。另外流式 ONNX 后端的 CPU 占用比它低约 35 倍。
|
||||
|
||||
### 2.1 0.6B vs 1.7B 实测对比
|
||||
|
||||
均为 Q8_0 主模型 + Q8_0 mmproj,`-t 8`。
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
状态:**完成**。准确率与离线转写一致,单步计算稳定在 2s 预算内。
|
||||
|
||||
> 本文讲的这套「切块 + 前缀回滚 + 增量 KV 复用」是 **llama 后端(Qwen3-ASR)** 的路径
|
||||
> (`IAsr::AsrKind::PrefixRollback`)。Phase 3.5 加的流式 ONNX 后端走的是另一条分支
|
||||
> (`NativeStreaming`:模型自己有状态,上层只喂音频、取当前整句),
|
||||
> 见 [asr-backends.md](asr-backends.md)。GUI 会按所选模型自动选这两条路径,不用手动切。
|
||||
|
||||
## 两种流式模式(实测对比)
|
||||
|
||||
代码里实现了两条流式路径,用 `--stream-mode` 切换。它们对应一个**无法同时满足的三选二**:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Phase 3:Qt 悬浮字幕窗
|
||||
|
||||
状态:**完成**。悬浮窗可用,已接入实时采集 + 流式转写。
|
||||
(窗口之外的交互 —— 托盘、设置对话框、应用内下载 —— 属于 Phase 4,见
|
||||
[docs/gui.md](gui.md)。本文记录 Phase 3 当时的形态,并在末尾列出后续变化。)
|
||||
|
||||

|
||||
|
||||
@@ -14,10 +16,15 @@
|
||||
|
||||
- **悬浮窗**:无边框、半透明深色圆角、始终置顶、不接受焦点(`Qt::FramelessWindowHint | WindowStaysOnTopHint | Tool | WindowDoesNotAcceptFocus`),可拖动。
|
||||
- **折叠 / 展开**:折叠两行、展开八行,底部箭头切换(折叠态 `⌄`、展开态 `⌃`)。
|
||||
- **语言标签**:左上角圆角 pill,显示识别到的语言(英语 / 中文 …);点击会发 `languageClicked` 信号,设置界面留到 Phase 4。
|
||||
行数可在设置里改(Phase 4)。
|
||||
- **语言标签**:左上角圆角 pill,显示识别到的语言(英语 / 中文 …);点击发 `languageClicked`
|
||||
—— Phase 4 起就是用它打开设置对话框。
|
||||
- **稳定/不稳定区分**:已稳定文本白色,不稳定尾部灰色 —— 与 CLI 版一致,也是 Chrome 那种"字长出来"的观感。
|
||||
- **背景**:**黑色 + 可调不透明度**(不是全透明;纯黑底才能保证任何桌面背景下文字都可读)。默认 84%,范围限制 20~100,`--opacity` 或 `setPanelOpacity()` 可调,Phase 4 接到设置里即可。
|
||||
- **关闭**:右上角 `✕` 退出。
|
||||
灰色尾部可以用设置里的「用灰色显示尚未稳定的尾部」关掉(Phase 4)。
|
||||
- **背景**:**黑色 + 可调不透明度**(不是全透明;纯黑底才能保证任何桌面背景下文字都可读)。
|
||||
默认 84%,范围限制 20~100,设置界面里是可拖的滑块(Phase 4),`--opacity` / `setPanelOpacity()` 也可调。
|
||||
- **关闭**:右上角 `✕`。Phase 4 起它的行为是**隐藏到托盘**(否则关掉就没法再打开了);
|
||||
只有在 `--no-tray` 或托盘不可用时才真正退出。
|
||||
- **实时链路**:采集默认输出的 monitor → 流式转写 → 信号推给窗口,全部在主线程外的工作线程里跑。
|
||||
|
||||
## 实时分段
|
||||
@@ -29,7 +36,7 @@ Phase 2 的结论是段不能无限长(解码器对 KV 的注意力随总长
|
||||
- **静音期间完全不送音频**:早期版本会把静音也喂进模型,模型对静音产生了幻觉(英文语音前冒出一个 `嗯。`);
|
||||
- 静音超过 0.8s 就收束这一段(提交文本、清空 KV),下一段重新开始。
|
||||
|
||||
`--stream-segment`(默认 30s)仍作为兜底上界。
|
||||
`--stream-segment`(默认 30s)仍作为兜底上界,设置界面对应「高级 → 单段最长时长」。
|
||||
|
||||
## 代码结构
|
||||
|
||||
@@ -37,12 +44,15 @@ Phase 2 的结论是段不能无限长(解码器对 KV 的注意力随总长
|
||||
src/
|
||||
├─ captionwindow.{h,cpp} # 悬浮窗
|
||||
├─ livetranscriber.{h,cpp} # 采集 + VAD + 分段 + 流式引擎(QObject)
|
||||
├─ streamingasr.{h,cpp} # 流式策略(前缀回滚、8s 切片、分段)
|
||||
├─ streamingasr.{h,cpp} # 流式策略(前缀回滚、切片、分段)
|
||||
├─ qwen3asr.{h,cpp} # 进程内推理(libllama + libmtmd)
|
||||
├─ audio.{h,cpp} # WAV 读取 + monitor 采集 + 重采样
|
||||
└─ transcript.{h,cpp} # 输出解析与语言名映射
|
||||
```
|
||||
|
||||
> 目录后来重排过:`captionwindow` / `livetranscriber` 现在在 `src/ui/`,
|
||||
> 其余在 `src/core/`,模型管理独立成 `src/models/`。见 [README 的代码结构](../README.md#代码结构)。
|
||||
|
||||
## 过程中踩的坑
|
||||
|
||||
1. **静音幻觉**:第一版把采集到的静音也喂给了模型,模型对静音产生幻觉,英文语音前面冒出一个 `嗯。`。改为静音期间完全不送音频。
|
||||
@@ -53,25 +63,32 @@ src/
|
||||
## 用法
|
||||
|
||||
```bash
|
||||
# 默认就是悬浮窗模式
|
||||
./build/live-caption-cli --model MODEL --mmproj MMPROJ
|
||||
# 悬浮窗程序(图形界面,Phase 4 起带托盘与设置)
|
||||
./build/live-caption
|
||||
|
||||
# 调整背景不透明度(20-100)
|
||||
./build/live-caption-cli --model MODEL --mmproj MMPROJ --opacity 60
|
||||
# 调整背景不透明度(20-100)—— 这是 GUI 程序的选项
|
||||
./build/live-caption --opacity 60
|
||||
|
||||
# 无窗口、纯命令行实时(便于在无显示环境调试)
|
||||
./build/live-caption-cli --model MODEL --mmproj MMPROJ --cli-live
|
||||
./build/live-caption-cli --asr-backend sherpa --asr-model zipformer-zh-2025 --cli-live
|
||||
|
||||
# 自截图(验证渲染,不依赖外部截图工具);会依次截折叠态与展开态
|
||||
./build/live-caption-cli --model MODEL --mmproj MMPROJ \
|
||||
--screenshot out.png --screenshot-delay 12
|
||||
./build/live-caption --asr-backend sherpa --asr-model zipformer-zh-2025 \
|
||||
--no-tray --screenshot out.png --screenshot-delay 12
|
||||
```
|
||||
|
||||
> 自截图产物带 alpha 通道;要判断不透明度是否正确,**直接看像素 alpha**,不要靠肉眼看合成效果。
|
||||
> 所有选项见 [docs/cli.md](cli.md)。
|
||||
|
||||
## Phase 3 之后的变化(Phase 4)
|
||||
|
||||
- ✕ 从「退出」改成「隐藏到托盘」,并加了托盘图标与菜单;
|
||||
- 语言标签点击 → 打开设置对话框(模型下载/选择、语言、显示、采集设备、下载源与代理、校验);
|
||||
- 背景不透明度、字号、行数、灰色尾部、窗口位置全部进了设置界面并持久化(`QSettings`);
|
||||
- **采集设备可选**(原来固定跟随启动时的默认输出,切到 HDMI 不会跟着变);
|
||||
- 细节见 [docs/gui.md](gui.md)。
|
||||
|
||||
## 已知限制 / 后续
|
||||
|
||||
- X11 下置顶与定位都正常;Wayland 下需要 layer-shell,属于 Phase 5。
|
||||
- 语言标签点击暂无设置界面(Phase 4)。
|
||||
- 采集跟随的是**启动时**的默认输出设备;设备切换(例如切到 HDMI)暂未处理。
|
||||
- X11 下置顶与定位都正常;Wayland 下需要 layer-shell,属于 Phase 5(见 [docs/troubleshooting.md](troubleshooting.md))。
|
||||
- 界面尚未做 HiDPI 之外的适配(当前主屏宽度 72%、最大 900 逻辑像素)。
|
||||
+39
-6
@@ -5,9 +5,10 @@
|
||||
| 目标 | 依赖 | 说明 |
|
||||
|---|---|---|
|
||||
| `livecaption_core` | 无 Qt | 全部业务逻辑;单元测试只依赖它 |
|
||||
| `livecaption_ui` | Qt6::Widgets | 悬浮窗与 Qt 适配层 |
|
||||
| `live-caption` | ui | 悬浮窗程序 |
|
||||
| `live-caption-cli` | core + Qt6::Core | 命令行程序(**不链接 Qt Widgets**) |
|
||||
| `livecaption_models` | Qt6::Core / Network | 注册表、安装检查、sha256 校验、应用内下载 |
|
||||
| `livecaption_ui` | Qt6::Widgets | 悬浮窗、设置对话框、Qt 适配层 |
|
||||
| `live-caption` | ui + models | 悬浮窗程序 |
|
||||
| `live-caption-cli` | core + models + Qt6::Core | 命令行程序(**不链接 Qt Widgets**) |
|
||||
| `tst_*` | core + Qt6::Test | 单元测试 |
|
||||
|
||||
## 运行
|
||||
@@ -17,7 +18,14 @@ cmake -S . -B build && cmake --build build -j
|
||||
ctest --test-dir build --output-on-failure # 也可以单独跑 build/tests/tst_xxx
|
||||
```
|
||||
|
||||
单元测试**不需要模型文件,也不需要显示环境**,秒级完成。
|
||||
单元测试**不需要模型文件,也不需要显示环境**,秒级完成。目前 4 套:
|
||||
|
||||
| 测试 | 覆盖 |
|
||||
|---|---|
|
||||
| `tst_streamingasr` | 流式策略:拼接、分段、已稳定/不稳定尾部、冷启动前缀 |
|
||||
| `tst_livepipeline` | 实时管线:静音过滤、不规则 chunk 不丢样本、静音分段 |
|
||||
| `tst_vad` | 能量 VAD(轻话音的检测) |
|
||||
| `tst_transcript` | 输出解析与语言名映射 |
|
||||
|
||||
## 为什么能这样测
|
||||
|
||||
@@ -48,14 +56,38 @@ ctest --test-dir build --output-on-failure # 也可以单独跑 build/tests/t
|
||||
|
||||
写测试的过程中还**抓到一个真 bug**:段恰好结束在 chunk 边界(没有待处理音频)时,`flush()` 只提交"已稳定"部分,最后几个词会被丢掉。已修(用完整文本 `lastRawFull_` 提交)。
|
||||
|
||||
## 界面 / 集成测试钩子
|
||||
|
||||
界面与真实音频链路不做单元测试,但留有可脚本化的入口(全部选项见 [cli.md](cli.md)):
|
||||
|
||||
```bash
|
||||
# 设置对话框各条退出路径的冒烟测试(当初定位「点确定就退出」的崩溃就是靠它)
|
||||
for how in reject close accept ok apply; do
|
||||
./build/live-caption --asr-model zipformer-zh-2025 --no-tray \
|
||||
--settings-autoclose $how --quit-after 8
|
||||
echo "$how → 退出码 $?"
|
||||
done
|
||||
|
||||
# 界面渲染自截图(折叠态 + 展开态),不依赖外部截图工具
|
||||
./build/live-caption --asr-model zipformer-zh-2025 --no-tray \
|
||||
--screenshot /tmp/win.png --screenshot-delay 6
|
||||
./build/live-caption --screenshot-settings /tmp/settings.png
|
||||
|
||||
# 模型完整性与采集设备(不需要显示环境)
|
||||
./build/live-caption-cli --verify-model zipformer-zh-2025
|
||||
./build/live-caption-cli --list-devices
|
||||
```
|
||||
|
||||
崩溃时用 `coredumpctl list` / `coredumpctl info <PID>` 看调用栈。
|
||||
|
||||
## 尚未覆盖
|
||||
|
||||
以下几类需要真模型或真实音频设备,属于集成测试,没放进单元测试:
|
||||
|
||||
- **8s 编码切片对齐**:这是准确率的决定性因素(切 2s 会明显掉准确率),但必须用真模型跑才能验证。
|
||||
- **增量 KV 复用的单步延迟**:需要真模型才能测。
|
||||
- 采集链路(PulseAudio/PipeWire 的 monitor 源)。
|
||||
- GUI 渲染。
|
||||
- 采集链路(PulseAudio/PipeWire 的 monitor 源、设备枚举)。
|
||||
- GUI 渲染的**像素级断言**(目前只有人工看截图)。
|
||||
|
||||
这些目前靠 `experiments/` 下的脚本与实机验证(见 `docs/phase0..3`)。
|
||||
|
||||
@@ -63,3 +95,4 @@ ctest --test-dir build --output-on-failure # 也可以单独跑 build/tests/t
|
||||
|
||||
- 给需要模型的集成测试打 CTest label(如 `model`),默认跳过,用环境变量指模型路径时才跑。
|
||||
- GUI 的渲染回归:已有的 `--screenshot` 自截图,可以断言面板像素 alpha(`(0,0,0,214)`),避免再次出现"样式表背景对自定义 QWidget 不生效 → 明明想半透明结果全透明"这类问题。
|
||||
- 给 `ModelStore::verify` 加一个用临时文件构造损坏模型的单元测试(现在只在集成层面手工验证过)。
|
||||
@@ -0,0 +1,94 @@
|
||||
# 常见问题
|
||||
|
||||
## 点 `✕` 之后窗口不见了
|
||||
|
||||
这是设计如此:**`✕` 是隐藏到托盘**,不是退出(否则关掉就再也没法打开了)。
|
||||
用托盘菜单的「显示/隐藏字幕」或单击托盘图标可以再显示回来;要退出用托盘菜单的「退出」。
|
||||
|
||||
如果连托盘图标也没有(桌面环境不支持托盘,或用 `--no-tray` 启动),`✕` 会直接退出程序。
|
||||
|
||||
## 首次启动弹出设置对话框
|
||||
|
||||
没有「已下载且被选中」的模型时,程序必须先让你准备一个模型才能工作,所以会先弹设置。
|
||||
在「模型」页选一个模型点「下载」,然后在「当前使用」里选中它,点「确定」即可。
|
||||
直接点「取消」= 放弃启动(程序退出)。
|
||||
|
||||
## 没有字幕 / 转写全是空白
|
||||
|
||||
按顺序排查:
|
||||
|
||||
1. **系统真的在播放声音吗?** 采集的是「正在播放的音频」,没有播放就没有字幕。
|
||||
2. **采集设备是否选错?** 默认跟随**系统默认输出**。如果声音是从 HDMI 出去的、而默认输出是
|
||||
Speaker(或反过来),就会采到静音。用 `--list-devices` 看有哪些设备,在设置里显式指定一个。
|
||||
```bash
|
||||
./build/live-caption-cli --list-devices
|
||||
```
|
||||
3. **音量和静音状态**:确认系统和该应用的音量不为 0、没有静音。
|
||||
4. 从终端启动看输出,采集/加载失败会打印原因:
|
||||
```bash
|
||||
./build/live-caption # 或 ./build/live-caption-cli --cli-live ...
|
||||
```
|
||||
|
||||
## 提示「模型未安装」/ 缺失某些文件
|
||||
|
||||
模型文件不完整。两种办法:
|
||||
|
||||
- 在设置对话框里选中该模型 → 「校验完整性」看哪些文件坏了 → 「删除」后重新「下载」;
|
||||
- 命令行:`./build/live-caption-cli --verify-model <id>` 查看,`./scripts/fetch-models.sh <id>` 重新下。
|
||||
|
||||
## 「校验失败,损坏的文件: …」
|
||||
|
||||
说明文件内容与注册表里的 sha256 对不上(下载被截断、磁盘问题等)。在设置里**删除该模型再重新下载**
|
||||
即可。下载支持断点续传,网络抖动不会前功尽弃。
|
||||
|
||||
## 下载很慢 / 下载失败
|
||||
|
||||
- 默认下载源是 `https://hf-mirror.com`(实测可达性最好)。可在设置里换成别的镜像或官方源。
|
||||
- 需要走代理时,在设置里把「代理」设为「跟随系统」或「手动设置」并填主机/端口/账号。
|
||||
- 大模型有几百 MB~1GB,首次下载慢是正常的;同一个文件不会重复下载。
|
||||
|
||||
## 日语 / 其它语言效果不好
|
||||
|
||||
这是模型能力问题,不是 bug。结论见 [asr-backends.md](asr-backends.md#推荐组合按语言装包) 的推荐组合:
|
||||
|
||||
| 语言 | 建议 |
|
||||
|---|---|
|
||||
| 中文 | `zipformer-zh-2025`(最快最准)或 X-ASR |
|
||||
| 英文 | `xasr-zh-en-480` |
|
||||
| 日语 | `nemotron35-560ms` + 设置里把「识别语言」改成**日语**(不指定语言会串) |
|
||||
| 其它 | `qwen3-asr-0.6b-q8`(52 语言兜底,CPU 占用高但最准) |
|
||||
|
||||
注意:多语言模型(Nemotron / Qwen3-ASR)**要在设置里选对语言**,否则「自动」可能识别成别的语言。
|
||||
|
||||
## Wayland 下窗口不置顶 / 位置不对
|
||||
|
||||
X11 下正常。Wayland 没有通用的「置顶悬浮层」协议,需要 `wlr-layer-shell`,属于 Phase 5。
|
||||
当前建议在 X11 会话下使用。
|
||||
|
||||
## 构建时警告「未找到 sherpa-onnx,流式 ONNX 后端将不可用」
|
||||
|
||||
正常,说明流式后端被跳过了。要启用:
|
||||
|
||||
```bash
|
||||
ls ~/.local/opt/sherpa-onnx/include/sherpa-onnx/c-api/c-api.h
|
||||
cmake -S . -B build -DSHERPA_ONNX_ROOT=$HOME/.local/opt/sherpa-onnx
|
||||
```
|
||||
|
||||
它需要自带的 `libonnxruntime.so`(`ldd build/live-caption` 可以确认解析到了)。
|
||||
|
||||
## 启动时打印 `setHighDpiScaleFactorRoundingPolicy must be called…`
|
||||
|
||||
与本事无关:一个 5 行的空白 Qt 程序在同样的会话里也会打印。是桌面会话设了
|
||||
`QT_SCALE_FACTOR_ROUNDING_POLICY` 导致的,可以忽略。
|
||||
|
||||
## Qwen3-ASR 的 GGUF 装不进去(加载失败)
|
||||
|
||||
模型与运行时**必须锁版本**:只有 ggml-org 官方 GGUF(`general.architecture = qwen3vl`)能用;
|
||||
社区量化常见的是 `qwen3asr` / `qwen3_asr`,不兼容。细节见
|
||||
[phase0-verification.md](phase0-verification.md)。
|
||||
|
||||
## 点了「确定」程序就退出了
|
||||
|
||||
这是早期版本的一个 bug(`QApplication` 默认「最后一个窗口关闭 = 退出」,而首次启动时设置对话框
|
||||
正是唯一窗口),**已经修好**。如果还在复现,请重新构建后再试;仍复现请附上
|
||||
`coredumpctl info <PID>` 的调用栈。
|
||||
Reference in new issue
Block a user