2026-06-12 17:08:20 +08:00
|
|
|
|
# 语音交互
|
|
|
|
|
|
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
|
|
|
|
|
|
语音交互全链路:**VAD(语音活动检测)** → **STT(语音转文字)** → **LLM 推理** → **TTS(文字转语音)**。
|
|
|
|
|
|
|
|
|
|
|
|
用户感知延迟 = VAD 响应 + STT 耗时 + LLM 首 token + TTS 首包。人类对话中停顿超过 300ms 就会感到"对方在想"。
|
|
|
|
|
|
|
|
|
|
|
|
**延迟目标**:端到端 **1.5~2 秒**(用户说完话到听到 AI 回应);流式 TTS 下,LLM 开始生成后 **0.5 秒**听到第一个词。
|
|
|
|
|
|
|
|
|
|
|
|
## 全链路
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
麦克风 → VAD → STT → LLM → TTS → 扬声器
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 环节一:VAD(语音活动检测)
|
|
|
|
|
|
|
|
|
|
|
|
从持续音频流中检测"人什么时候在说话",避免将环境噪音当作有效输入。**浏览器端完成**,节省 ~70% 带宽。
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
import { MicVAD } from "@ricky0123/vad-web";
|
|
|
|
|
|
|
|
|
|
|
|
const vad = await MicVAD.new({
|
|
|
|
|
|
onSpeechStart: () => console.log("用户开始说话"),
|
|
|
|
|
|
onSpeechEnd: (audio) => {
|
|
|
|
|
|
// audio: Float32Array,送入 STT
|
|
|
|
|
|
sendToSTT(audio);
|
|
|
|
|
|
},
|
2026-06-14 08:52:36 +08:00
|
|
|
|
positiveSpeechThreshold: 0.5, // 检测灵敏度
|
|
|
|
|
|
negativeSpeechThreshold: 0.35, // 结束灵敏度
|
|
|
|
|
|
minSpeechMs: 250, // 最短语音时长 ms
|
|
|
|
|
|
redemptionMs: 300, // 语音结束确认时间 ms
|
|
|
|
|
|
preSpeechPadMs: 300, // 语音前填充 ms
|
2026-06-12 17:08:20 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
vad.start();
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 环节二:STT(语音转文字)
|
|
|
|
|
|
|
|
|
|
|
|
| 方案 | 延迟 | 成本 | 特点 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| Whisper API | 1-3s | 按分钟计费 | 准确率高,支持多语言 |
|
2026-06-14 08:52:36 +08:00
|
|
|
|
| **Deepgram**(默认) | <500ms | 按分钟计费 | 流式识别,延迟极低 |
|
|
|
|
|
|
| **MiMo ASR**(小米) | ~1s | 按量计费 | 国产替代,兼容 OpenAI 格式,HTTP 非流式 |
|
2026-06-12 17:08:20 +08:00
|
|
|
|
| 浏览器原生 | ~1s | 免费 | 中文效果一般 |
|
|
|
|
|
|
|
2026-06-14 08:52:36 +08:00
|
|
|
|
当前实现为**一次性语音识别**(非流式):前端 VAD 检测到用户说完后,将完整音频片段发送到后端,后端调用 `stt.Recognize()` 一次性返回识别结果。流式 STT 为未来优化方向。
|
2026-06-12 17:08:20 +08:00
|
|
|
|
|
2026-06-14 08:52:36 +08:00
|
|
|
|
音频编码格式:前端 `audio.ts` 将 Float32Array 转为 Int16 PCM(16kHz, pcm_s16le)再编码为 Base64。
|
2026-06-12 17:08:20 +08:00
|
|
|
|
|
|
|
|
|
|
## 环节三:TTS(文字转语音)
|
|
|
|
|
|
|
|
|
|
|
|
流式 TTS:检测 LLM 输出中的句子边界,每检测到一句就立即送入 TTS 合成并播放,不必等全部生成完。
|
|
|
|
|
|
|
2026-06-14 08:52:36 +08:00
|
|
|
|
句子切分规则:按中文标点(`。!?`)、英文标点(`. ! ?`)和换行符切分。
|
|
|
|
|
|
|
2026-06-19 14:58:43 +08:00
|
|
|
|
当前实现参数:Voice `"mimo_default"`(可通过配置切换)、Speed `1.0`、OutputFmt `"mp3"`、SampleRate `24000`。
|
2026-06-14 08:52:36 +08:00
|
|
|
|
|
2026-06-12 17:08:20 +08:00
|
|
|
|
方案选择:
|
2026-06-14 08:52:36 +08:00
|
|
|
|
- **OpenAI TTS**(默认):音质好,延迟中等,按字符计费,模型 tts-1
|
|
|
|
|
|
- **MiMo TTS**(小米):国产替代,通过配置切换
|
|
|
|
|
|
- **Edge TTS**(规划中):微软免费方案,音质不错,延迟略高
|
2026-06-12 17:08:20 +08:00
|
|
|
|
|
|
|
|
|
|
## 延迟优化要点
|
|
|
|
|
|
|
|
|
|
|
|
- VAD 浏览器端处理(减少无效传输)
|
|
|
|
|
|
- 流式 STT(边说边识别)
|
|
|
|
|
|
- LLM 流式输出
|
|
|
|
|
|
- TTS 句子级流式合成
|
|
|
|
|
|
- STT 与上下文准备并行处理
|