Ai_GirlFriend/xuniYou/最新优化说明.md
2026-02-28 18:04:34 +08:00

5.8 KiB
Raw Permalink Blame History

语音通话最新优化说明

📅 优化时间

2026-02-28

🎯 优化目标

解决 "idle timeout" 问题确保语音通话流程完整运行ASR → LLM → TTS

已完成的优化

1. 服务器端优化

增加超时时间

  • 文件: lover/.env
  • 修改: 添加 VOICE_CALL_IDLE_TIMEOUT=120
  • 说明: 从默认的 60 秒增加到 120 秒,给 ASR + LLM + TTS 处理留出足够时间
  • 重要: 修改后需要重启 FastAPI 服务器才能生效

2. 客户端优化

使用官方推荐参数

  • 文件: xuniYou/pages/chat/phone.vue
  • 修改: sendAudioInChunks() 方法
  • 参数调整:
    • 每片大小: 8192 bytes → 3200 bytes(官方推荐)
    • 发送间隔: 50ms → 100ms(官方推荐)

为什么使用 3200 bytes

根据官方文档和音频参数计算:

PCM 音频参数:
- 采样率: 16000 Hz
- 位深度: 16 bit = 2 bytes
- 声道数: 1单声道

每秒数据量 = 16000 × 2 × 1 = 32000 bytes

官方建议每包 100ms 音频:
100ms 数据量 = 32000 × 0.1 = 3200 bytes

这就是官方示例代码中使用 f.read(3200) 的原因!

📊 优化效果对比

优化前

每片: 8KB
间隔: 50ms
速率: 8192 / 0.05 = 163840 bytes/s = 160 KB/s
实际音频速率: 32000 bytes/s = 31.25 KB/s
速率比: 5.12 倍(发送太快)

优化后

每片: 3.2KB
间隔: 100ms
速率: 3200 / 0.1 = 32000 bytes/s = 31.25 KB/s
实际音频速率: 32000 bytes/s = 31.25 KB/s
速率比: 1 倍(完美匹配实时音频流)

🔧 如何测试

1. 重启服务器(必须)

# 在服务器上
cd /path/to/lover

# 停止旧进程
pkill -f "uvicorn.*main:app"

# 启动新进程
uvicorn main:app --host 0.0.0.0 --port 30101 --reload

2. 重新编译客户端

在 HBuilderX 中:

  1. 选择运行 → 运行到手机或模拟器
  2. 或者制作自定义调试基座

3. 测试步骤

  1. 打开 App进入语音通话页面
  2. 按住"按住说话"按钮
  3. 清晰地说 3-5 秒的话(重要!之前测试只有 1 秒太短)
  4. 松开按钮
  5. 观察日志和响应

4. 预期日志

客户端日志

📦 开始分片发送(官方推荐参数)
📊 总大小: 160000 bytes
📊 每片大小: 3200 bytes
📊 发送间隔: 100 ms
📊 预计发送时间: 5000 ms
📤 发送第 1 片,大小: 3200 bytes
✅ 第 1 片发送成功
...
✅ 所有音频片段发送完成,共 50 片
📊 实际发送时间: 5000 ms
📤 发送结束标记 "end"
✅ 结束标记发送成功,等待服务器处理...

服务器日志

ASR connection opened
ASR event end=False sentence=...
ASR event end=True sentence=你好,我想问一个问题
ASR complete
Handle sentence: 你好,我想问一个问题
[LLM 生成回复]
[TTS 合成语音]

客户端收到响应

📋 收到控制消息, type: reply_text
📋 完整消息: {"type":"reply_text","text":"你好呀,有什么问题尽管问我~"}
🎵 收到音频数据流, 当前缓存数量: 1
🎵 收到音频数据流, 当前缓存数量: 2
...
📋 收到控制消息, type: reply_end
[开始播放音频]

⚠️ 注意事项

1. 录音时长要求

  • 最少 2-3 秒:太短的音频 ASR 可能无法识别
  • 建议 3-5 秒:足够的语音内容,识别率更高
  • 最多 10 秒:避免单次录音过长

2. 录音环境

  • 安静环境,减少背景噪音
  • 清晰发音,不要含糊不清
  • 正常语速,不要太快或太慢

3. 网络要求

  • 稳定的网络连接
  • WebSocket 保持连接
  • 如果网络不稳定,会自动重连

🐛 问题排查

如果还是出现 "idle timeout"

1. 检查服务器是否重启

# 查看进程
ps aux | grep uvicorn

# 查看日志
tail -f /path/to/lover/logs/app.log

2. 检查 .env 配置是否生效

# 在服务器上
cd /path/to/lover
cat .env | grep VOICE_CALL_IDLE_TIMEOUT

应该显示:

VOICE_CALL_IDLE_TIMEOUT=120

3. 检查录音时长

查看客户端日志中的 "总大小"

📊 总大小: 160000 bytes

计算时长:

时长 = 总大小 / 32000
160000 / 32000 = 5 秒 ✅ 足够

如果只有 9000 bytes
9000 / 32000 = 0.28 秒 ❌ 太短

4. 检查服务器日志

如果服务器日志中没有 "ASR event",说明 ASR 没有收到数据或无法识别。

可能原因:

  • 音频格式不对(应该是 PCM 16kHz 单声道)
  • 音频太短
  • 音频质量太差(噪音太大)

📚 参考文档

🎉 预期结果

优化后,语音通话应该能够:

  1. 录音正常PCM 格式16kHz
  2. 分片发送3200 bytes/片100ms 间隔)
  3. ASR 识别成功(收到识别结果)
  4. LLM 生成回复(收到文本回复)
  5. TTS 合成语音(收到音频数据)
  6. 播放音频(听到 AI 的声音)
  7. 不再出现 "idle timeout" 错误

💡 下一步优化建议

如果基本功能正常,可以考虑:

  1. 实时流式录音:使用 onFrameRecorded 实现真正的实时传输
  2. 降低延迟:优化 LLM 和 TTS 的响应速度
  3. 打断功能:允许用户在 AI 说话时打断
  4. 多轮对话:优化对话历史管理
  5. 情感识别:根据用户语气调整回复风格

📞 技术支持

如果遇到问题,请提供:

  1. 客户端完整日志(从按下按钮到收到响应)
  2. 服务器日志ASR/LLM/TTS 相关)
  3. 录音时长和文件大小
  4. 网络状态和 WebSocket 连接状态