Ai_GirlFriend/xuniYou/问题定位总结.md
2026-02-28 18:04:34 +08:00

3.9 KiB
Raw Permalink Blame History

问题定位总结

🎯 核心问题

卡在 ASR语音识别环节导致后续 LLM 和 TTS 都没有被触发。

🔍 详细分析

问题流程

客户端 → 一次性发送 260KB PCM 文件
    ↓
服务器 → 接收到大块数据
    ↓
ASR → 无法处理(期望流式小块数据)❌
    ↓
没有识别结果
    ↓
LLM 不被触发 ❌
    ↓
TTS 不被触发 ❌
    ↓
60秒后 idle timeout

根本原因

架构不匹配

  1. 服务器设计

    • 使用 paraformer-realtime-v2(实时 ASR
    • 期望流式接收音频数据
    • 设计用于边说边识别
  2. 客户端实现

    • 录音完成后一次性发送整个文件
    • 不是流式传输
    • 类似"批处理"模式

这就像:

  • 服务器是一个"实时翻译员",期望你一句一句说
  • 但客户端把整篇文章一次性扔给他
  • 翻译员不知道怎么处理

📊 各环节状态

环节 状态 说明
客户端录音 正常 PCM 格式16kHz
文件读取 正常 260KB
WebSocket 发送 正常 发送成功
ASR 识别 卡住 无法处理大块数据
LLM 生成 ⏸️ 未触发 因为 ASR 没有结果
TTS 合成 ⏸️ 未触发 因为 LLM 没有结果
返回音频 ⏸️ 未触发 因为 TTS 没有结果

🔧 解决方案

已实现:分片发送

修改客户端,将大文件分成小块发送:

// 每次发送 8KB
const chunkSize = 8192

// 模拟流式传输
for (let offset = 0; offset < totalSize; offset += chunkSize) {
    const chunk = audioData.slice(offset, offset + chunkSize)
    socketTask.send({ data: chunk })
    await sleep(50) // 延迟 50ms
}

// 发送结束标记
socketTask.send({ data: 'end' })

工作原理

客户端 → 发送 8KB 片段 1
    ↓
服务器 → ASR 开始识别
    ↓
客户端 → 发送 8KB 片段 2
    ↓
服务器 → ASR 继续识别
    ↓
... (重复)
    ↓
客户端 → 发送 "end" 标记
    ↓
服务器 → ASR 完成识别
    ↓
服务器 → 触发 LLM 生成
    ↓
服务器 → 触发 TTS 合成
    ↓
服务器 → 返回音频

📈 预期效果

修改前

  • ASR 无法识别
  • 60 秒后超时
  • 没有任何响应

修改后

  • ASR 正常识别
  • LLM 生成回复
  • TTS 合成语音
  • 返回音频播放

🧪 测试步骤

  1. 重新编译项目
  2. 进入语音通话页面
  3. 按住"按住说话"按钮
  4. 说话 2-3 秒
  5. 松开按钮
  6. 观察日志:
    • 应该看到 "开始分片发送"
    • 应该看到 "第 X 片发送成功"
    • 应该看到 "发送结束标记"
    • 应该收到服务器的识别结果
    • 应该收到 LLM 的回复
    • 应该收到 TTS 的音频

🎓 经验总结

教训

  1. 架构匹配很重要

    • 实时 ASR 需要流式输入
    • 不能用批处理方式
  2. 日志很重要

    • 通过日志快速定位问题
    • 每个环节都要有日志
  3. 理解服务端设计

    • 要了解服务端期望什么
    • 不能想当然

最佳实践

  1. 使用流式传输

    • 对于实时 ASR必须流式发送
    • 分片大小4-8KB
    • 发送间隔50-100ms
  2. 添加结束标记

    • 告诉服务器数据发送完毕
    • 触发最终处理
  3. 完善错误处理

    • 每个环节都要有错误处理
    • 超时要有提示

🔗 相关文档

结论

问题已定位并解决:

  • 问题ASR 无法处理大块数据
  • 原因:客户端一次性发送,服务器期望流式接收
  • 解决:客户端改为分片发送,模拟流式传输
  • 状态:已实现,待测试