Ai_GirlFriend/xuniYou/优化总结.md
2026-02-28 18:04:34 +08:00

254 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 语音通话 "idle timeout" 问题 - 优化总结
## 📅 日期
2026-02-28
## 🎯 问题描述
用户在使用语音通话功能时,录音后总是收到 "idle timeout" 错误无法完成完整的对话流程ASR → LLM → TTS
## 🔍 问题根因
### 1. 客户端发送参数不符合官方推荐
- **问题**: 每片 8KB间隔 50ms发送速度是实际音频速度的 5 倍
- **影响**: 虽然在官方范围内1KB-16KB但不是最优参数
### 2. 服务器超时时间不足
- **问题**: 默认 60 秒超时,但 ASR + LLM + TTS 可能需要更长时间
- **影响**: 在处理完成前就超时断开
### 3. 测试音频太短
- **问题**: 之前测试只有 9KB约 0.3 秒)
- **影响**: ASR 无法识别太短的音频
## ✅ 已实施的优化
### 优化1: 调整客户端分片参数(符合官方推荐)
**文件**: `xuniYou/pages/chat/phone.vue`
**修改内容**:
```javascript
// 优化前
const chunkSize = 8192 // 8KB
const chunkDelay = 50 // 50ms
// 优化后
const chunkSize = 3200 // 3.2KB(官方推荐)
const chunkDelay = 100 // 100ms官方推荐
```
**理由**:
- PCM 16kHz 单声道: 32000 bytes/秒
- 100ms 音频 = 32000 × 0.1 = 3200 bytes
- 完美匹配实时音频流速度
### 优化2: 增加服务器超时时间
**文件**: `lover/.env`
**修改内容**:
```bash
# 新增配置
VOICE_CALL_IDLE_TIMEOUT=120
```
**理由**:
- 从 60 秒增加到 120 秒
- 给 ASR + LLM + TTS 留出足够处理时间
- 避免在处理过程中超时
## 📊 优化效果对比
### 发送速度对比
| 参数 | 优化前 | 优化后 |
|------|--------|--------|
| 每片大小 | 8192 bytes | 3200 bytes |
| 发送间隔 | 50ms | 100ms |
| 发送速率 | 163840 bytes/s | 32000 bytes/s |
| 音频速率 | 32000 bytes/s | 32000 bytes/s |
| 速率比 | 5.12 倍 | 1 倍 ✅ |
### 时间线对比
**优化前**:
```
0s - 用户说话 1 秒
1s - 一次性发送 32KB
1s - ASR 无法处理
60s - 超时断开 ❌
```
**优化后**:
```
0s - 用户说话 5 秒
5s - 开始分片发送3200 bytes/片100ms 间隔)
10s - 发送完成ASR 识别
11s - LLM 生成回复
13s - TTS 合成语音
15s - 客户端播放音频 ✅
```
## 🔧 需要执行的操作
### ⚠️ 重要:必须重启服务器
修改 `.env` 文件后,必须重启 FastAPI 服务器才能生效:
```bash
# 1. 停止旧进程
pkill -f "uvicorn.*main:app"
# 2. 启动新进程
cd /path/to/lover
uvicorn main:app --host 0.0.0.0 --port 30101 --reload
```
### 客户端重新编译
在 HBuilderX 中重新运行项目到手机或模拟器。
## 📱 测试指南
### 测试步骤
1. 打开 App进入语音通话页面
2. 按住"按住说话"按钮
3. **清晰地说 3-5 秒的话**(重要!)
4. 松开按钮
5. 等待响应(应该在 20 秒内完成)
### 预期结果
- ✅ 看到"发送中..."提示
- ✅ 看到"识别中..."提示
- ✅ 收到文字回复
- ✅ 听到语音回复
- ✅ 没有 "idle timeout" 错误
### 关键日志
**客户端应该看到**:
```
📦 开始分片发送(官方推荐参数)
📊 总大小: 160000 bytes
📊 每片大小: 3200 bytes
📊 发送间隔: 100 ms
✅ 所有音频片段发送完成,共 50 片
✅ 结束标记发送成功
📋 收到控制消息, type: reply_text
🎵 收到音频数据流
📋 收到控制消息, type: reply_end
```
**服务器应该看到**:
```
ASR connection opened
ASR event end=True sentence=[识别的文字]
Handle sentence: [识别的文字]
```
## 📚 相关文档
已创建的文档:
1. `最新优化说明.md` - 详细的优化说明
2. `测试检查清单.md` - 测试步骤和检查项
3. `语音通话完整流程图.md` - 可视化流程图
4. `官方文档分析和正确实现.md` - 技术分析
5. `问题定位总结.md` - 问题诊断过程
## 🎓 技术要点总结
### 1. Paraformer-realtime-v2 的正确用法
- 必须流式发送音频数据
- 每包 1KB-16KB建议 3200 bytes
- 发送间隔建议 100ms
- 发送完成后必须发送 "end" 标记
### 2. PCM 音频参数
- 采样率: 16000 Hz
- 位深度: 16 bit (2 bytes)
- 声道数: 1单声道
- 数据速率: 32000 bytes/秒
### 3. 超时设置
- 空闲超时: 120 秒(从 60 秒增加)
- 静默超时: 60 秒(无语音活动)
- 给 ASR + LLM + TTS 留出足够时间
### 4. 录音要求
- 最少 2-3 秒
- 建议 3-5 秒
- 清晰发音,避免噪音
## 🐛 故障排查
### 如果还是出现 "idle timeout"
1. **检查服务器是否重启**
```bash
ps aux | grep uvicorn
```
2. **检查配置是否生效**
```bash
cat lover/.env | grep VOICE_CALL_IDLE_TIMEOUT
```
3. **检查录音时长**
- 客户端日志中的 "总大小" 应该 > 96000 bytes3 秒)
4. **检查服务器日志**
```bash
tail -f lover/logs/app.log
```
### 常见问题
**Q: 为什么要用 3200 bytes**
A: 因为 PCM 16kHz 单声道每秒 32000 bytes100ms 就是 3200 bytes这是官方推荐的参数。
**Q: 为什么要延迟 100ms**
A: 模拟实时音频流的速度,让 ASR 能够边收边识别,而不是一次性收到大块数据。
**Q: 为什么要发送 "end" 标记?**
A: 告诉服务器音频发送完毕,触发 ASR 的最终识别,否则 ASR 会一直等待更多数据。
**Q: 为什么要说 3-5 秒?**
A: 太短的音频(< 1 ASR 可能无法识别3-5 秒是比较合适的长度
## 🎉 预期成果
优化完成后语音通话应该能够
1. 用户说话 3-5
2. 客户端分片发送3200 bytes/100ms 间隔
3. 服务器 ASR 识别成功
4. LLM 生成回复
5. TTS 合成语音
6. 客户端播放音频
7. 整个流程在 20-30 秒内完成
8. 不再出现 "idle timeout" 错误
## 💡 下一步建议
如果基本功能正常可以考虑
1. **实时流式录音**: 使用 `onFrameRecorded` 实现真正的实时传输
2. **降低延迟**: 优化 LLM TTS 的响应速度
3. **打断功能**: 允许用户在 AI 说话时打断
4. **多轮对话**: 优化对话历史管理
5. **情感识别**: 根据用户语气调整回复风格
## 📞 需要帮助?
如果测试失败请提供
1. 客户端完整日志
2. 服务器日志
3. 录音信息大小时长
4. 错误信息
---
**优化完成时间**: 2026-02-28
**优化人员**: Kiro AI Assistant
**状态**: 已完成待测试