feat(tools-pve/asr-pipeline): multi-backend ASR web app with LiteLLM routing
This commit is contained in:
@@ -1,51 +1,55 @@
|
||||
# ASR Pipeline on tools-pve
|
||||
# Meeting ASR
|
||||
|
||||
独立的录音转写、精修、人工审核和导出服务。WebUI 与 Agent API 共用 `192.168.50.49:8788`;worker 调用 unRaid 上的 Qwen3-ASR/CAM++ 服务以及 ZenMux 模型 API。
|
||||
独立的会议/通话录音转写与整理 Web 应用(`asrservice` + `asrpipe`)。支持本地 GPU 声纹服务(`qwen3cam`)与云端多模型语音识别(`soniox`、`gemini`、`openai`、`grok`),可通过 Arcane 部署到本地 VM(`tools-pve`)或外网 VPS。
|
||||
|
||||
## 数据边界
|
||||
## 核心架构
|
||||
|
||||
- `/mnt/truenas/personal/ASR-Pipeline` → 容器 `/data`:原始录音、转写、ASR 原始响应、草稿、正式稿、日志和 SQLite 在线备份。
|
||||
- `/opt/asr-pipeline/state` → 容器 `/state`:活动 SQLite、worker heartbeat、revision queue。SQLite WAL 不放在 NFS。
|
||||
- `/srv/asr/inbox`:指向 TrueNAS inbox 的宿主机链接,供 `scp`/`sftp` 上传。
|
||||
- Secret 只存在于 Arcane Project 环境和 tools-pve 的 `0600` 恢复副本,不进入 Git。
|
||||
1. **Web 控制与审核面(`asrservice.web`)**
|
||||
- 极简零构建服务端渲染 HTML + 原生 JS(深浅色自适应)。
|
||||
- 上传录音时可按任务切换 ASR 引擎(`qwen3cam` / `soniox` / `gemini` / `openai` / `grok`)。
|
||||
- 任务详情页内置支持 HTTP Range 的音频播放器、失败一键切换模型重试、草稿与纪要 Markdown 在线编辑。
|
||||
- `/review/` 提供低置信度词语、关系确认与说话人身份确认(本地 `qwen3cam` 自动注册声纹至 `:10099`,线上多说话人模型直接更新草稿与词库而不依赖 `:10099`)。
|
||||
- `/lexicon` 提供热词、同音纠错、人物关系管理与 Obsidian 词库一键同步。
|
||||
- `/settings` 展示全部 ASR 引擎、LiteLLM 网关、Obsidian 与 Hindsight 实时就绪状态。
|
||||
- 支持可选 `ASR_WEB_PASSWORD` Cookie 鉴权(外网 VPS 部署时自动保护 `/ui/*` 与 `/review/*`)。
|
||||
|
||||
SSH 大文件建议先上传为 `.part`,完成后在同一目录原子改名为受支持扩展名:
|
||||
2. **后台消费与修订队列(`asrservice.worker`)**
|
||||
- 监控 `.asr-inbox/`(Web 上传或目录投递)并认领 `intake.db` 任务。
|
||||
- 调用统一多引擎层 `asrpipe.providers.transcribe_audio()` 生成带结构化注释头的原始转写。
|
||||
- 执行 `asr-refine draft`:结合 SQLite 词库、Obsidian Vault(`People/`、`Companies/`、`Projects/`、`minutes/`、`_glossary.md`)与 Hindsight(`personal-context`)进行分段去口语化、保真检查与会议纪要生成。
|
||||
- 监控 `state/revision-queue/` 处理 Web 审核提交的修订重跑请求,确认通过后发布正式纪要至 Obsidian 并可选执行 Git 自动提交推送。
|
||||
|
||||
3. **语音识别(ASR)与大模型网关边界**
|
||||
- **LLM 后处理**:彻底移除 ZenMux,统一通过 **LiteLLM**(内网 `http://192.168.50.49:4000/v1` / 外网 `https://api.opfo.xyz/v1`)调用:
|
||||
- `ASR_CLEAN_MODEL` / `ASR_KEYWORD_MODEL`:默认 `aistudio/gemini-flash-lite-latest`
|
||||
- `ASR_DRAFT_MODEL`:默认 `codex/gpt-sol-latest`
|
||||
- **ASR 引擎**:
|
||||
- `qwen3cam`(内网默认):对接局域网 GPU `Qwen3-ASR 1.7B + CAM++`(`http://192.168.50.100:10099/asr`),支持声纹特征比对与增量注册。
|
||||
- `soniox`(线上高精度首选):因 LiteLLM 同步 `/v1/audio/transcriptions` 不支持 Soniox 异步 Files API、结构化 `context` 热词注入与逐词 `speaker` 分离且有 180s 超时限制,由 `asrpipe.providers` 通过 `SONIOX_API_KEY` 直连 Soniox `stt-async-v5`(自动注入 SQLite 词库热词与任务背景,完成后自动清理云端临时音频)。
|
||||
- `gemini`:通过 LiteLLM 统一网关调用 `aistudio/gemini-3.5-transcribe`(长音频自动 `ffmpeg` 切片)。
|
||||
- `openai`:通过 LiteLLM 统一网关调用 `openai/gpt-4o-transcribe-diarize`(支持 `diarized_json` 角色分离与 >23MB 自动压缩切片)。
|
||||
- `grok`:通过 `XAI_API_KEY` 调用 xAI `grok-voice-transcribe-2.0`(支持多说话人分离)。
|
||||
|
||||
## 目录结构
|
||||
|
||||
- `asrpipe/`:核心转写引擎适配(`providers.py`)、词库召回(`lexicon.py`)、分段去口语化(`segment.py`、`refine.py`)、审核流(`review.py`)与 Obsidian/Hindsight 集成。
|
||||
- `asrservice/`:容器化 Web 服务(`web.py`)、后台 Worker(`worker.py`)、SQLite 任务状态机(`db.py`)、Webhook 通知(`notify.py`)与健康检查(`healthcheck.py`)。
|
||||
- `recordings/bin/`:录音监听与 CLI 转写脚本(兼容 `MEETING_ASR_BACKEND` 多引擎调度)。
|
||||
- `termbank/`:专业词库源数据。
|
||||
- `tests/`:核心管线、多引擎契约与 Web 服务单元测试。
|
||||
- `Dockerfile` & `compose.yaml`:面向 Arcane 部署的单镜像双角色(`asr-web` + `asr-worker`)容器编排。
|
||||
|
||||
## 本地开发与测试
|
||||
|
||||
```bash
|
||||
scp call.m4a tools@192.168.50.49:/srv/asr/inbox/call.m4a.part
|
||||
ssh tools@192.168.50.49 'mv /srv/asr/inbox/call.m4a.part /srv/asr/inbox/call.m4a'
|
||||
python3 -m venv .venv
|
||||
.venv/bin/pip install -e .
|
||||
ASR_NOTIFY=0 ASR_GIT_SYNC=0 .venv/bin/python -m unittest discover -s tests -v
|
||||
```
|
||||
|
||||
## Agent API
|
||||
## Arcane 部署(内网 VM / 外网 VPS)
|
||||
|
||||
所有 `/api/v1/*` 路由使用 `Authorization: Bearer $ASR_AGENT_TOKEN`。
|
||||
|
||||
```bash
|
||||
curl -X POST http://192.168.50.49:8788/api/v1/jobs \
|
||||
-H "Authorization: Bearer $ASR_AGENT_TOKEN" \
|
||||
-H 'X-Filename: call.m4a' -H 'X-Title: 项目通话' \
|
||||
-H 'X-Context: 参与人和项目背景' --data-binary @call.m4a
|
||||
|
||||
curl -H "Authorization: Bearer $ASR_AGENT_TOKEN" \
|
||||
http://192.168.50.49:8788/api/v1/jobs/JOB_ID
|
||||
```
|
||||
|
||||
路由:
|
||||
|
||||
- `POST /api/v1/jobs`:上传并创建异步任务。
|
||||
- `GET /api/v1/jobs?limit=&offset=&status=`:分页查询。
|
||||
- `GET /api/v1/jobs/{id}`:任务详情、事件时间线与产物链接。
|
||||
- `GET /api/v1/jobs/{id}/artifacts/{transcript|draft|result}`:读取产物。
|
||||
- `GET /api/v1/jobs/{id}/reviews`:待人工确认项。
|
||||
- `POST /api/v1/jobs/{id}/reviews/{question_id}`:JSON `{"answer":"..."}`。
|
||||
- `POST /api/v1/jobs/{id}/retry`:重试失败任务。
|
||||
|
||||
`/healthz` 仅表示 Web 进程存活;`/readyz` 同时检查数据库与 worker heartbeat。
|
||||
|
||||
## 通知
|
||||
|
||||
`ASR_NOTIFY_BACKEND=none|telegram|hermes`。Telegram 需要 `TELEGRAM_BOT_TOKEN` 与 `TELEGRAM_CHAT_ID`;Hermes 需要一个明确存在的签名 webhook URL 与共享密钥。发送失败只影响提醒,不改变任务结果。
|
||||
|
||||
## 运维
|
||||
|
||||
项目由 Arcane Git Sync 管理,自动同步、自动 pull 和自动 redeploy 均关闭。Compose 变更先在 Git 中验证,再对 tools-pve 的准确 Sync 手动同步。活动数据库每小时通过 SQLite backup API 写到 `/data/backups/*.latest`。
|
||||
1. 复制 `.env.example` 为 `.env`,按环境配置:
|
||||
- **内网 VM(`tools-pve`)**:`MEETING_ASR_BACKEND=qwen3cam`(同时可配 `SONIOX_API_KEY` 等以便在 Web UI 按需切换)、`LITELLM_BASE_URL=http://192.168.50.49:4000/v1`、`HINDSIGHT_URL=http://192.168.50.47:8888`。
|
||||
- **外网 VPS**:`MEETING_ASR_BACKEND=soniox`(或 `gemini` / `openai` / `grok`)、`LITELLM_BASE_URL=https://api.opfo.xyz/v1`、设置 `ASR_WEB_PASSWORD` 开启 Web 登录保护。
|
||||
2. 使用 `compose.yaml` 启动 `asr-web`(默认 `:8788`)与 `asr-worker`。
|
||||
|
||||
Reference in New Issue
Block a user