# 语音交互

## 概述

语音交互全链路：**VAD（语音活动检测）** → **STT（语音转文字）** → **LLM 推理** → **TTS（文字转语音）**。

用户感知延迟 = VAD 响应 + STT 耗时 + LLM 首 token + TTS 首包。人类对话中停顿超过 300ms 就会感到"对方在想"。

**延迟目标**：端到端 **1.5~2 秒**（用户说完话到听到 AI 回应）；流式 TTS 下，LLM 开始生成后 **0.5 秒**听到第一个词。

## 全链路

```
麦克风 → VAD → STT → LLM → TTS → 扬声器
```

> 后端 AI 编排基于 Eino Graph 声明式 DAG 实现：`START → STT → History → ChatModel → Msg2Str → Splitter → TTS → Done → END`。详见 [11-Eino框架技术文档](11-Eino框架技术文档.md)。

## 环节一：VAD（语音活动检测）

从持续音频流中检测"人什么时候在说话"，避免将环境噪音当作有效输入。**浏览器端完成**，节省 ~70% 带宽。

```typescript
import { MicVAD } from "@ricky0123/vad-web";

const vad = await MicVAD.new({
  onSpeechStart: () => console.log("用户开始说话"),
  onSpeechEnd: (audio) => {
    // audio: Float32Array，送入 STT
    sendToSTT(audio);
  },
  positiveSpeechThreshold: 0.5,  // 检测灵敏度
  negativeSpeechThreshold: 0.35, // 结束灵敏度
  minSpeechMs: 250,              // 最短语音时长 ms
  redemptionMs: 300,             // 语音结束确认时间 ms
  preSpeechPadMs: 300,           // 语音前填充 ms
});

vad.start();
```

## 环节二：STT（语音转文字）

| 方案 | 延迟 | 成本 | 特点 |
|------|------|------|------|
| **MiMo ASR**（默认） | ~1s | 按量计费 | 国产替代，兼容 OpenAI 格式，HTTP 非流式 |
| **Deepgram** | <500ms | 按分钟计费 | 流式识别，延迟极低 |
| Whisper API | 1-3s | 按分钟计费 | 准确率高，支持多语言 |
| 浏览器原生 | ~1s | 免费 | 中文效果一般 |

当前实现为**一次性语音识别**（非流式）：前端 VAD 检测到用户说完后，将完整音频片段发送到后端，后端通过 Eino Graph 的 STT Lambda 节点调用 `stt.Recognize()` 一次性返回识别结果。流式 STT 为未来优化方向。

音频编码格式：前端 `audio.ts` 将 Float32Array 转为 Int16 PCM（16kHz, pcm_s16le）再编码为 Base64。

## 环节三：TTS（文字转语音）

流式 TTS：检测 LLM 输出中的句子边界，每检测到一句就立即送入 TTS 合成并播放，不必等全部生成完。

句子切分规则：按中文标点（`。！？`）、英文标点（`. ! ?`）和换行符切分。

当前实现参数：Voice `"mimo_default"`（可通过配置切换）、Speed `1.0`、OutputFmt `"mp3"`、SampleRate `24000`。

方案选择：
- **MiMo TTS**（默认）：国产替代，模型 mimo-v2.5-tts，通过配置切换
- **OpenAI TTS**：音质好，延迟中等，按字符计费，模型 tts-1
- **Edge TTS**（待实现）：微软免费方案，音质不错，延迟略高

## 延迟优化要点

- VAD 浏览器端处理（减少无效传输）
- 流式 STT（边说边识别）
- LLM 流式输出
- TTS 句子级流式合成
- STT 与上下文准备并行处理
