feat: add voice transcription feedback workflow

This commit is contained in:
2026-07-20 10:49:49 +08:00
parent 0a07538dce
commit bed80aa807
17 changed files with 1691 additions and 19 deletions

310
DEBUG_GUIDE.md Normal file
View File

@@ -0,0 +1,310 @@
# 本地调试指南
本文用于在本机启动 PostgreSQL 连接、中文 FunASR、Rust API 和微信小程序,并验证短录音、长录音及多课节汇总。
## 1. 服务关系
```text
微信小程序
-> Rust API127.0.0.1:8080
-> PostgreSQL
-> FunASR127.0.0.1:10095
```
本地录音转写的核心是 FunASR当前组合为
- Paraformer中文语音识别。
- FSMN-VAD检测并切分有效语音。
- CT-Transformer恢复中文标点。
- PyTorchCPU 推理运行时。
Rust API 负责音频保存、持久化任务队列、重试、课节状态和反馈汇总。小程序每 8 分钟自动切片,并每 3 秒无感刷新转写状态。
## 2. 当前主机资源实测
测试主机为 Apple Silicon、10 核 CPU、16 GB 统一内存,配置为 CPU 单并发:
| 项目 | 实测值 |
| --- | --- |
| FunASR 模型缓存 | 约 2.1 GB |
| Python 虚拟环境 | 约 871 MB |
| 模型加载后的物理内存 | 约 2.8 GB |
| 进程历史内存峰值 | 约 4.9 GB |
| 8 分钟、16 kHz、单声道、48 kbps MP3 | 约 44.8 秒完成 |
| 推理期间 CPU | 约 90% 至 132%,即约 1 至 1.3 个 CPU 核 |
8 分钟数据使用重复的清晰中文样本测得,真实课堂中的噪声、停顿和说话人数会影响耗时和识别质量。
容量建议:
- 当前单教师或低并发调试:不需要 GPU当前 16 GB 主机足够。
- CPU 部署最低建议4 vCPU、8 GB 内存8 GB 可能发生交换16 GB 更稳妥。
- 多教师并发:先保持单并发观察队列;若片段持续积压,再考虑增加 CPU 实例或 NVIDIA GPU。
- GPU 是可选优化不是运行前提。CUDA 部署需要单独的 CUDA/PyTorch 镜像,当前 CPU 镜像不能只修改 `ASR_DEVICE=cuda`
- GPU 部署建议从 8 GB 显存起步并用真实课堂录音压测。当前 Apple Silicon 配置没有使用 Apple GPU。
- `ASR_WORKER_CONCURRENCY``ASR_MAX_CONCURRENCY` 应保持一致;每提高一个并发都要重新观察内存和吞吐。
## 3. 首次准备
在项目根目录执行:
```bash
cd /Users/zhangheng/project/ai/miniprogram/teaching-feedback-assistant
```
确认 `server/.env` 存在,并填写可访问的 `DATABASE_URL`。不存在时再复制示例,避免覆盖现有配置:
```bash
test -f server/.env || cp server/.env.example server/.env
```
本地 FunASR 默认配置如下,无需腾讯云密钥:
```env
ASR_PROVIDER=local
LOCAL_ASR_URL=http://127.0.0.1:10095
ASR_REQUEST_TIMEOUT_SECONDS=1800
ASR_WORKER_CONCURRENCY=1
ASR_JOB_LEASE_SECONDS=3600
```
首次准备 Python 环境:
```bash
cd asr-service
python3 -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/python -m pip install -r requirements.txt
cd ..
```
模型首次启动会下载约 2.1 GB 到 `asr-service/.models``.venv``.models` 均已被 Git 和微信小程序打包忽略。
## 4. 启动全部服务
### 4.1 执行数据库迁移
每次拉取到新迁移后执行一次:
```bash
cd server
cargo run --bin migrate
cd ..
```
看到 `PostgreSQL migrations completed` 表示成功。
### 4.2 启动 FunASR
终端一:
```bash
cd asr-service
MODELSCOPE_CACHE=.models .venv/bin/uvicorn app:app \
--host 127.0.0.1 \
--port 10095 \
--no-access-log
```
另一个终端检查:
```bash
curl http://127.0.0.1:10095/health
```
预期结果:
```json
{"status":"ok","model":"paraformer-zh","device":"cpu"}
```
首次下载或缓存加载期间端口可能暂不可用,应等待模型完全加载。
Docker 方式可替代本机 Python
```bash
docker compose -f compose.asr.yml up --build -d
docker compose -f compose.asr.yml logs -f funasr
```
### 4.3 启动 Rust API
终端二:
```bash
cd server
cargo run
```
检查完整链路:
```bash
curl http://127.0.0.1:8080/health | jq .
```
正常状态应包含:
```json
{
"status": "ok",
"database_configured": true,
"speech_configured": true,
"speech_available": true,
"speech_provider": "local-funasr"
}
```
接口文档:<http://127.0.0.1:8080/scalar>
### 4.4 启动微信开发者工具
终端三,在项目根目录执行:
```bash
cli open \
--project /Users/zhangheng/project/ai/miniprogram/teaching-feedback-assistant \
--port 63097 \
--lang zh
```
自动预览编译检查:
```bash
cli auto-preview \
--project /Users/zhangheng/project/ai/miniprogram/teaching-feedback-assistant \
--port 63097 \
--lang zh \
--info-output /tmp/teaching-feedback-preview.json
```
开发者工具模拟器默认访问 `http://127.0.0.1:8080`。进入小程序“我的”页面,应看到“服务、数据库和语音转录正常”。
## 5. 录音测试流程
### 短录音
1. 打开“反馈生成”。
2. 点击“语音录入”,录制 10 至 30 秒中文。
3. 点击“结束录音”。
4. 页面短暂显示“正在处理”。
5. 转写完成后文字应自动加入反馈内容。
短录音条件为不超过 60 秒,且转写文本未超过后端短文本限制。
### 长录音
1. 录制超过 60 秒的中文。
2. 结束后等待状态变成“已就绪”。
3. 主按钮变为“生成反馈”。
4. 点击一次后,转写内容会汇总进反馈草稿。
### 多课节汇总
1. 录制并结束第一节课。
2. 再次点击“语音录入”录制下一节。
3. 重复完成多节录音。
4. 所有课节就绪后点击一次“生成反馈”。
单节录音超过 8 分钟时,小程序会自动结束当前片段并立即开始下一片段,用户无需操作。
## 6. 故障恢复测试
### FunASR 未启动
停止 FunASR 后录音Rust API 仍会保存音频,页面保持“正在处理”。重新启动 FunASR 后,后台队列会自动继续。
### Rust 在推理中退出
任务使用租约避免多个工作线程重复处理。默认租约为 3600 秒。调试崩溃恢复时,可在 `server/.env` 临时设置:
```env
ASR_JOB_LEASE_SECONDS=60
```
重新启动 Rust API 后,超出租约的任务会再次被领取。生产环境应使用足够覆盖最长片段推理时间的租约。
### 转写失败
点击页面中的语音状态,可查看课节状态并重试失败片段。音频保存在 `server/data/audio`,转写失败不会立即删除原文件。
## 7. 常见问题
### `speech_configured=true` 但 `speech_available=false`
- FunASR 尚未启动或模型仍在加载。
- `10095` 端口被占用。
- `LOCAL_ASR_URL` 配置错误。
检查:
```bash
lsof -nP -iTCP:10095 -sTCP:LISTEN
curl http://127.0.0.1:10095/health
```
### `database_configured=false` 或数据接口返回 503
检查 `server/.env` 中的 `DATABASE_URL`,然后重新执行迁移并启动 API。
### 微信模拟器无法连接 API
```bash
lsof -nP -iTCP:8080 -sTCP:LISTEN
curl http://127.0.0.1:8080/health
```
再到小程序“我的”页面确认 API 地址为 `http://127.0.0.1:8080`
### 真机无法访问 `127.0.0.1`
真机中的 `127.0.0.1` 指手机自身。局域网调试时:
1.`server/.env``HOST` 改为 `0.0.0.0`
2. 确认手机和电脑连接同一网络。
3. 在“我的”页面将 API 地址改为 `http://<电脑局域网IP>:8080`
4. 检查系统防火墙和微信开发者工具的域名校验设置。
正式环境必须使用微信允许的 HTTPS 合法域名。
## 8. 代码检查
小程序:
```bash
npm run typecheck
```
Rust
```bash
cd server
cargo fmt --check
cargo test
cargo clippy --all-targets -- -D warnings
```
FunASR 服务:
```bash
python3 -m py_compile asr-service/app.py
asr-service/.venv/bin/python -m pip check
```
## 9. 停止服务
前台运行时,在 FunASR 和 Rust API 各自终端按 `Ctrl+C`
Docker 方式:
```bash
docker compose -f compose.asr.yml down
```
确认端口已经释放:
```bash
lsof -nP -iTCP:8080 -sTCP:LISTEN
lsof -nP -iTCP:10095 -sTCP:LISTEN
```
正常停止服务不会删除 `asr-service/.models` 模型缓存。除非希望重新下载模型,否则不要删除该目录。