feat: 语音流式输入管线 + VAD前端集成 + 插件-工具合并清理

- 前端: VAD语音检测(@ricky0123/vad-web) + useVoiceInput双模式(流式WS/REST)
- Gateway: VoiceStreamManager代理WS流式STT到voice-service
- Voice-service: DashScope REST → Realtime WS → Whisper三级引擎 + ffmpeg转码
- 共享模块: pkg/audio(音频转换) + pkg/dashscope(ASR REST客户端)
- 清理: 移除旧plugin-manager和pkg/plugins,完成插件→工具合并
- 文档: 完善gateway-api.md和voice-service.md语音API文档
- 工具: scripts/voice/ 语音转换脚本集

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-06 11:50:40 +08:00
parent 258cf81b25
commit 6ef9e082a6
91 changed files with 4091 additions and 3929 deletions
+46 -8
View File
@@ -3,9 +3,14 @@
**Base URL:** `http://<host>:8093` | **Auth:**
语音服务封装两层引擎:
- **STT (语音转文字):** DashScope `qwen3-asr-flash-realtime` () + 本地 Whisper (备)
- **STT (语音转文字):** DashScope REST 离线模型 `qwen3-asr-flash-2026-02-10` (主) → DashScope Realtime WS `qwen3-asr-flash-realtime` (流式) 本地 Whisper (备)
- **TTS (文字转语音):** edge-tts (主) + espeak-ng (备)
> **引擎分层说明:**
> - **离线转录** (`POST /api/v1/transcribe`): 使用 DashScope REST API,无需 session 协商和 Server VAD,延迟更低。失败自动回退 Whisper。
> - **流式转录** (`GET /api/v1/stt/stream`): 使用 DashScope Realtime WebSocket,支持实时分片输入和中间结果输出,需客户端发送 PCM 音频。
> - **音频转码**: 所有非 PCM 格式通过 ffmpeg 转码为 16kHz mono PCM 后再识别,支持 WAV/MP3/OGG/FLAC/WebM/Opus/AMR 等格式。
---
## 目录
@@ -24,13 +29,25 @@
**Content-Type:** `multipart/form-data` | **Max body:** 10 MB
### 引擎选择
优先使用 DashScope REST 离线模型 `qwen3-asr-flash-2026-02-10`,失败自动回退本地 Whisper。
```
接收音频 → DashScope REST API (HTTP POST)
↓ 失败
ffmpeg 转码 PCM → 本地 Whisper 引擎
```
### 表单字段
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `audio` | file | 是 | 音频文件。格式从扩展名推断:wav/mp3/ogg/flac/m4a |
| `audio` | file | 是 | 音频文件。支持格式: wav, mp3, ogg, flac, m4a, aac, webm, opus, amr, pcm |
| `language` | string | 否 | 默认 `"zh"`。可选: `zh`, `en`, `ja`, `ko`, `auto` |
> **转码说明:** 非 PCM 格式(含 Opus/WebM/AMR)通过 ffmpeg 自动转码为 16-bit PCM 16000Hz mono 后识别。需部署环境安装 ffmpeg。
### 响应 200
```json
@@ -49,7 +66,7 @@
| 400 | `{"error":"文件过大或解析失败,最大支持 10MB"}` |
| 400 | `{"error":"缺少 audio 文件字段"}` |
| 400 | `{"error":"音频文件为空"}` |
| 400 | `{"error":"不支持的音频格式: <ext>,支持的格式: WAV, MP3, OGG, FLAC, M4A"}` |
| 400 | `{"error":"不支持的语言: <lang>,支持的语言: zh, en, ja, ko, auto"}` |
| 405 | `{"error":"method not allowed"}` |
| 500 | `{"error":"读取音频文件失败"}` |
| 500 | `{"success":false,"error":"<engine error>"}` |
@@ -112,12 +129,23 @@
"service": "voice-service",
"stt": {
"available": true,
"primary": "dashscope",
"dashscope": { "available": true, "model": "qwen3-asr-flash-realtime", "provider": "dashscope" },
"primary": "dashscope_rest",
"dashscope_rest": {
"available": true,
"model": "qwen3-asr-flash-2026-02-10",
"protocol": "rest"
},
"dashscope_ws": {
"available": true,
"model": "qwen3-asr-flash-realtime",
"protocol": "websocket",
"state": "idle"
},
"whisper": {
"available": true,
"binary_available": true,
"model_loaded": true,
"ffmpeg_available": true,
"model_name": "ggml-small.bin"
},
"default_language": "zh",
@@ -138,9 +166,15 @@
| 字段 | 说明 |
|------|------|
| `stt.available` | DashScope 或 Whisper 至少一个可用 |
| `stt.dashscope.available` | DashScope API Key 已配置 |
| `stt.whisper.available` | Whisper 二进制 + 模型文件均存在 |
| `stt.available` | DashScope REST / WS 或 Whisper 至少一个可用 |
| `stt.primary` | 当前优先引擎: `dashscope_rest` |
| `stt.dashscope_rest.available` | DashScope REST API Key 已配置 |
| `stt.dashscope_rest.protocol` | 协议类型: `rest` |
| `stt.dashscope_ws.available` | DashScope Realtime WS 可用 |
| `stt.dashscope_ws.protocol` | 协议类型: `websocket` |
| `stt.dashscope_ws.state` | 连接状态: `idle`, `connected`, `error` |
| `stt.whisper.available` | Whisper 二进制 + 模型文件 + ffmpeg 均存在 |
| `stt.whisper.ffmpeg_available` | ffmpeg 可用于音频转码 |
| `tts.available` | 至少一个 TTS 引擎可用 |
| `tts.engine` | 当前激活引擎: `edge-tts`, `espeak-ng`, `fallback (silent WAV)`, `none` |
@@ -183,6 +217,10 @@
**Query 参数:** `?language=zh&format=pcm` (language 默认 zh, format 默认 pcm)
**Read deadline:** 300s
> **注意:** 此端点使用 DashScope Realtime WebSocket (`qwen3-asr-flash-realtime`),音频帧必须是 PCM 格式。非 PCM 格式应使用 REST 离线转录 (`POST /api/v1/transcribe`)。
>
> **Gateway 代理:** Gateway 的 `voice_stream_*` 消息类型通过此端点与前端 VAD 配合,实现端到端流式语音 → STT → LLM 管道。详见 [Gateway WebSocket 文档](../../gateway-api.md#流式语音输入流程-voice_stream_)。
### 客户端 → 服务端
**Binary 帧:** 原始 PCM 音频 (16-bit LE, 16000Hz, mono)。每帧通过 `input_audio_buffer.append` 转发到 DashScope。