# 📋 PRD 更新建议

## 当前状态

**PRD 中已有的内容（第 1187-1237 行）:**

```markdown
##### 3.1.1.3 Agent 触发时机

**核心机制：VAD静音检测 + 静默超时**

| 参数 | 默认值 | 说明 |
|------|--------|------|
| 静默超时 | 1.5秒 | 用户说完后等待多久再触发 |
| 最小语句长度 | 0.5秒 | 短于此时长的语音忽略 |
| VAD阈值 | 0.5 | 语音活跃度阈值 |
```

---

## 缺失的内容

| 内容 | PRD 状态 |
|------|---------|
| 帧粒度 (16ms) | ❌ 未记录 |
| TEN VAD 性能 (0.234ms/帧) | ❌ 未记录 |
| 实际参数 (threshold=0.3, min_silence_ms=500) | ❌ 与 PRD 不一致 |
| 三层 Barge-in 架构 | ❌ 未记录 |
| 分句合成逻辑 | ❌ 未记录 |
| 连接预热机制 | ❌ 未记录 |

---

## 建议补充的章节

### 新增：3.1.1.4 VAD 检测细节

```markdown
##### 3.1.1.4 VAD 检测细节

**检测频率：** 每 16ms 检测一帧 (256 samples @ 16kHz)

**性能数据：**
- TEN VAD: 0.234ms/帧 (P50)
- 比 Silero VAD 快 30%
- 库大小: 306KB vs 2.2MB

**检测流程：**
```
每 16ms 检测一帧
    ↓
VAD 判断: is_speech = True/False
    ↓
检测到语音 → 收集到 buffer
检测到静音 → 记录开始时间
    ↓
静音持续 ≥500ms → 判定"用户说完话了"
    ↓
触发 STT → LLM → TTS
```

**参数配置：**
```yaml
vad:
  threshold: 0.3        # 语音活跃度阈值
  min_speech_ms: 300    # 最短语音 300ms (防误触)
  min_silence_ms: 500   # 静音 500ms 判定"说完"
```

**关键决策：500ms vs 1.5s**
- 500ms: 更快响应，适合实时对话
- 1.5s: 更安全，避免误判自然停顿
- **当前选择: 500ms** (可配置)
```

---

### 新增：3.1.1.5 Barge-in 三层架构

```markdown
##### 3.1.1.5 Barge-in 三层架构

**第一层：回声抑制（软件版 AEC）**
- 不暂停 ASR
- 比对播放文本与 ASR 识别结果
- 高度重合 → 判定为回声并丢弃

**第二层：语义判停（轻量分类器）**
- 检测插话意图
- 区分「附和」（嗯/对）vs「真打断」（等等）
- 真打断 → 立刻停止 TTS

**第三层：状态机兜底**
- 任何打断先走统一取消例程
- 中止 TTS 推流、清空播放队列、挂起 ASR 会话
- 防止竞态导致声音重叠（消灭幽灵音频）
```

---

### 新增：3.1.1.6 Pipeline 优化

```markdown
##### 3.1.1.6 Pipeline 优化三板斧

**第一板：分句合成**
- LLM 流式输出遇到句子边界（。！？；\n）立即送 TTS
- 不等完整回复
- 避免按逗号切分导致音频拼接结巴

**第二板：连接预热**
- 会话开始前预建好 ASR 和 TTS 的 WebSocket
- TTS 预合成 20ms 静音片段
- 让播放器提前进入「推流就绪」状态

**第三板：音频参数**
- TTS 采样率: 24kHz (传输字节减半)
- 音频分片: 200ms/chunk
- WebSocket 开压缩但只压协议头不压音频
```

---

## 需要确认的问题

1. **静默阈值**: 代码用 500ms，PRD 写 1.5s — 应以哪个为准？
2. **VAD 阈值**: 代码用 0.3，PRD 写 0.5 — 是否要统一？

---

## 行动项

- [ ] 更新 PRD 第 3.1.1.3 节，添加实际参数
- [ ] 新增 3.1.1.4 - 3.1.1.6 章节
- [ ] 确认静默阈值决策
- [ ] 更新章节编号（3.1.1.3 → 3.1.1.7）
