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

6.3 KiB
Raw Permalink Blame History

语音通话 "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

修改内容:

// 优化前
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

修改内容:

# 新增配置
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 服务器才能生效:

# 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. 检查服务器是否重启

    ps aux | grep uvicorn
    
  2. 检查配置是否生效

    cat lover/.env | grep VOICE_CALL_IDLE_TIMEOUT
    
  3. 检查录音时长

    • 客户端日志中的 "总大小" 应该 > 96000 bytes3 秒)
  4. 检查服务器日志

    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
状态: 已完成,待测试