2026-08-19-stt-design.md 5.4 KB

语音转文字(STT)功能规格

日期: 2026-08-19 状态: 设计审批中 范围: cfc-langgraph(新增)+ cfc-frontend(改造)


背景与目标

小程序现有 diet/exercise/sleep 三个语音打卡页已实现录音功能(mp3 格式,uni.getRecorderManager),但录音仅上传保存,未做文字转写。本次新增 STT 能力,覆盖两个场景:

  1. 打卡语音转文字:录音后自动转写,文字直接保存至记录,用户无感知。
  2. AI 对话语音输入:在聊天界面新增语音按钮,录音 → 转写 → 填入输入框 → 用户确认后发送。

技术选型

项目 选型 理由
STT 引擎 faster-whisper 1.2.1 轻量(base 140MB),中文识别准确,Python 原生支持
模型 whisper-base(Systran/faster-whisper-base) 中英混合识别,CPU 可用,内存 ~256MB(含模型)
模型下载源 hf-mirror.com 国内可访问,避免直连 HuggingFace 超时
音频格式 mp3(16kHz mono,WAV float32 内部处理) 小程序录音输出 mp3,av 库解码
部署方式 模型随镜像构建时缓存至 .cache/,无需运行时下载 避免容器启动慢

架构

[小程序] mp3 录音
    │
    ▼
[langgraph] POST /api/v1/audio/transcribe
    │  body: multipart/form-data (file=audio.mp3)
    ▼
[faster-whisper base] → 转写文字(中文/英文自动检测)
    │
    ▼
{ text: "转写结果", language: "zh", duration: 3.2 }

服务启动流程:

  1. FastAPI 启动 → app/main.py → 初始化 WhisperModel('base') 缓存至全局变量
  2. 请求到达 /api/v1/audio/transcribe → 读取 mp3 → av 解码 → faster-whisper 转写 → 返回 JSON

模型缓存策略:

  • 构建镜像时在 COPY 前用 hf-mirror.com 预下载模型到 /root/.cache/huggingface/hub/models--Systran--faster-whisper-base/
  • 或:启动时首次加载(约 95s),服务就绪前 healthcheck 返回不健康

接口设计

1. langgraph — 语音转写端点

POST /api/v1/audio/transcribe

Request:

Content-Type: multipart/form-data
file: audio.mp3 (≤30s,≤5MB)

Response:

{
  "code": 200,
  "message": "ok",
  "data": {
    "text": "今天早餐吃了鸡蛋和牛奶",
    "language": "zh",
    "language_probability": 0.98,
    "duration": 3.2
  }
}

错误处理:

  • 文件为空/格式不支持 → 400
  • 转写失败 → 500,message 含原因
  • 超时(>30s 音频) → 413

2. frontend — 打卡页改造(diet/exercise/sleep-checkin.vue)

现有流程:录音 → 上传 mp3 → 保存 voicePath → 提交打卡

新增流程:录音 → 调 STT 转写 → 上传 mp3 + 保存 voiceText → 提交打卡

改动点:

  • recorderManager.onStop 回调中新增:调 /api/v1/audio/transcribe 获取文字
  • 表单增加 voiceText 字段(隐藏,用于后端存储)
  • 后端新增字段接收 voiceTextDietCheckinDTO 增加 voiceText: Optional[str]

3. frontend — AI 对话语音输入

在聊天输入框旁新增 🎙️ 按钮,按住录音,松手转写,文字填入输入框。

改动点:

  • 新增语音按钮组件(复用现有 uni.getRecorderManager
  • 录音结束 → 调 STT → 结果写入 this.inputText
  • 用户确认后点击发送(与文字输入相同流程)

数据模型改动

backend(Java)

DietCheckinDTO / ExerciseCheckinDTO / SleepCheckinDTO 增加字段:

private String voiceText; // 语音转写文字

GrowthRecordService 新增字段映射(若统一用 GrowthRecordDTO 则一并增加)。

frontend(小程序)

打卡页表单增加 voiceText 字段,提交时携带。


依赖变更

cfc-langgraph/requirements.txt 新增:

faster-whisper==1.2.1
av==18.1.0

cfc-langgraph/Dockerfile 新增模型缓存步骤:

# 预下载 whisper base 模型(避免启动时慢下载)
RUN HF_ENDPOINT=https://hf-mirror.com \
    pip install faster-whisper==1.2.1 av==18.1.0 && \
    python3 -c "from faster_whisper import WhisperModel; WhisperModel('base', device='cpu', compute_type='int8')"

cfc-langgraph/.env.production 无需新增(模型参数硬编码,不配置)。


非功能性约束

  • 模型加载时间: ~95s(首次),后续请求 <100ms
  • 单次转写耗时: 3 秒语音约 200-500ms(CPU base 模型)
  • 音频时长限制: 最大 60 秒(与现有小程序录音 duration 一致)
  • 并发限制: 单 worker 串行处理转写(避免多请求同时吃 CPU),预计 QPS ≤2

实现顺序建议

  1. langgraph STT 端点 — 独立开发,单接口,测试通过
  2. frontend 打卡页接入 — 三页同步改造,复用同一上传逻辑
  3. frontend 对话语音输入 — 独立 UI 组件,最后接入
  4. backend DTO 字段增加 — 前后端联调时同步

风险与缓解

风险 缓解
容器启动慢(模型加载 95s) healthcheck 初始 delay 延长至 120s
CPU 资源不足(base 模型内存 ~256MB) 确认服务器 ≥512MB 内存可用
转写准确率问题(background noise) 后续可换 medium 模型,本次 base 够用
音频格式兼容(mp3 vs wav) av 库自动处理多格式

审批

  • 架构设计确认
  • 接口设计确认
  • 依赖变更确认
  • 实现顺序确认