# 语音对话功能说明 ## 🎯 功能概述 完整的语音对话流程已实现,包括: 1. **ASR(语音识别)** - 用户语音 → 文字 2. **LLM(对话生成)** - 文字 → AI 回复文字 3. **TTS(语音合成)** - AI 回复文字 → 语音 4. **前端播放** - 播放 AI 的语音回复 ## 📋 API 端点 ### 1. 仅 ASR 识别(已有) ``` POST /voice/call/asr ``` **请求**: ```json { "audio_data": "base64编码的音频数据", "format": "wav" } ``` **响应**: ```json { "code": 1, "msg": "ok", "data": { "text": "识别的文字" } } ``` ### 2. 完整语音对话(新增) ``` POST /voice/call/conversation ``` **请求**: ```json { "audio_data": "base64编码的音频数据", "format": "wav" } ``` **响应**: ```json { "code": 1, "msg": "ok", "data": { "user_text": "用户说的话", "ai_text": "AI的回复文字", "audio_data": "base64编码的AI语音", "audio_format": "mp3" } } ``` ## 🔄 完整流程 ### 后端处理流程 ``` 用户录音 ↓ 1. 接收 base64 音频数据 ↓ 2. 解码为二进制 ↓ 3. 上传到 OSS ↓ 4. 调用 DashScope ASR ↓ 5. 等待识别结果 ↓ 6. 获取用户文字 ↓ 7. 构建对话上下文(包含恋人人格) ↓ 8. 调用 LLM 生成回复 ↓ 9. 清理回复文本(去除 Markdown) ↓ 10. 获取用户的音色配置 ↓ 11. 调用 TTS 合成语音 ↓ 12. 将语音编码为 base64 ↓ 13. 返回完整结果 ``` ### 前端处理流程 ``` 用户按住说话按钮 ↓ 1. 开始录音 ↓ 2. 松开按钮,停止录音 ↓ 3. 读取录音文件 ↓ 4. 转换为 base64 ↓ 5. 调用 /voice/call/conversation ↓ 6. 显示"对话处理中..." ↓ 7. 接收响应 ↓ 8. 显示用户说的话 ↓ 9. 解码 AI 语音数据 ↓ 10. 保存为临时文件 ↓ 11. 显示 AI 回复文字 ↓ 12. 播放 AI 语音 ↓ 13. 播放完成后清理临时文件 ``` ## 🎨 前端代码示例 ### 发送语音并接收回复 ```javascript async sendAudioToASR(audioBytes) { // 1. 转换为 base64 let base64Audio = '' for (let i = 0; i < audioBytes.length; i++) { base64Audio += String.fromCharCode(audioBytes[i]) } base64Audio = btoa(base64Audio) // 2. 调用 API const response = await uni.request({ url: this.baseURLPy + '/voice/call/conversation', method: 'POST', header: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + uni.getStorageSync("token") }, data: { audio_data: base64Audio, format: 'wav' } }) // 3. 处理响应 const data = response.data.data const userText = data.user_text const aiText = data.ai_text const audioData = data.audio_data // 4. 显示识别结果 uni.showToast({ title: `你说: ${userText}`, icon: 'none' }) // 5. 播放 AI 语音 await this.playAIVoice(audioData, aiText) } ``` ### 播放 AI 语音 ```javascript async playAIVoice(base64Audio, aiText) { // 1. 解码 base64 const binaryString = atob(base64Audio) const bytes = new Uint8Array(binaryString.length) for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i) } // 2. 保存为临时文件 const fs = uni.getFileSystemManager() const tempFilePath = `${wx.env.USER_DATA_PATH}/ai_voice_${Date.now()}.mp3` fs.writeFileSync(tempFilePath, bytes.buffer, 'binary') // 3. 显示 AI 回复文字 uni.showToast({ title: `AI: ${aiText}`, icon: 'none', duration: 3000 }) // 4. 播放音频 const innerAudioContext = uni.createInnerAudioContext() innerAudioContext.src = tempFilePath innerAudioContext.autoplay = true innerAudioContext.onEnded(() => { // 清理临时文件 fs.unlinkSync(tempFilePath) }) } ``` ## 🔧 配置要求 ### 环境变量 ```bash # DashScope API Key(ASR + LLM + TTS) DASHSCOPE_API_KEY=sk-xxx # OSS 配置(存储音频文件) ALIYUN_OSS_ACCESS_KEY_ID=xxx ALIYUN_OSS_ACCESS_KEY_SECRET=xxx ALIYUN_OSS_BUCKET_NAME=xxx ALIYUN_OSS_ENDPOINT=https://oss-cn-hangzhou.aliyuncs.com ALIYUN_OSS_CDN_DOMAIN=https://xxx.oss-cn-hangzhou.aliyuncs.com # LLM 配置 LLM_MODEL=qwen-plus LLM_TEMPERATURE=0.8 LLM_MAX_TOKENS=2000 # TTS 配置 VOICE_CALL_TTS_MODEL=cosyvoice-v2 VOICE_CALL_TTS_VOICE=longxiaochun_v2 VOICE_CALL_TTS_FORMAT=mp3 # ASR 配置 VOICE_CALL_ASR_MODEL=paraformer-v2 VOICE_CALL_ASR_SAMPLE_RATE=16000 ``` ### 数据库表 需要以下表: - `fa_lover` - 恋人信息(personality_prompt, voice_id) - `fa_voice_library` - 音色库(voice_code, gender, is_default) - `fa_user` - 用户信息(nickname, gender) ## 📊 性能指标 ### 预期处理时间 | 步骤 | 时间 | 说明 | |------|------|------| | 录音 | 2-5秒 | 用户说话时间 | | 上传 OSS | 0.5-1秒 | 取决于网络 | | ASR 识别 | 2-5秒 | DashScope 处理 | | LLM 生成 | 1-3秒 | 取决于回复长度 | | TTS 合成 | 1-2秒 | 取决于文本长度 | | 下载播放 | 0.5-1秒 | 取决于网络 | | **总计** | **7-17秒** | 完整对话周期 | ### 优化建议 1. **流式处理** - LLM 和 TTS 可以流式返回,边生成边播放 2. **缓存** - 常见回复可以预先合成并缓存 3. **并行处理** - 某些步骤可以并行执行 4. **CDN 加速** - 使用 CDN 加速音频传输 ## 🎯 用户体验流程 ### 理想的对话体验 ``` 用户: [按住按钮] "今天天气怎么样?" [松开] ↓ 界面: "对话处理中..." ↓ (3-5秒) 界面: "你说: 今天天气怎么样?" ↓ (1秒) 界面: "AI: 今天天气很好哦,阳光明媚,适合出去走走~" ↓ [播放 AI 语音] ↓ 用户: [听完后继续对话] ``` ## 🐛 常见问题 ### 1. 识别结果为空 **原因**: - 录音时间太短 - 环境噪音太大 - 没有说话内容 **解决**: - 确保录音时长 > 1 秒 - 在安静环境测试 - 靠近麦克风说话 ### 2. AI 回复太慢 **原因**: - 网络延迟 - LLM 生成时间长 - TTS 合成时间长 **解决**: - 优化网络连接 - 使用更快的模型(qwen-flash) - 限制回复长度 ### 3. 语音播放失败 **原因**: - 音频格式不支持 - 临时文件写入失败 - 权限问题 **解决**: - 使用标准 MP3 格式 - 检查文件系统权限 - 添加错误处理 ## 🚀 下一步优化 ### 短期优化(1-2周) 1. **流式 TTS** - 边生成边播放,减少等待时间 2. **对话历史** - 保存最近几轮对话,提供上下文 3. **打断功能** - 用户可以打断 AI 的回复 4. **情感识别** - 根据用户语气调整 AI 回复 ### 中期优化(1-2月) 1. **多轮对话** - 完整的对话管理系统 2. **个性化** - 根据用户习惯调整回复风格 3. **语音克隆** - 支持用户自定义音色 4. **实时对话** - WebSocket 实时双向通信 ### 长期优化(3-6月) 1. **多模态** - 结合图像、视频的对话 2. **情感分析** - 深度理解用户情绪 3. **主动对话** - AI 主动发起话题 4. **场景化** - 不同场景的专属对话模式 ## 📝 测试清单 ### 功能测试 - [ ] 录音功能正常 - [ ] ASR 识别准确 - [ ] LLM 回复合理 - [ ] TTS 语音自然 - [ ] 播放功能正常 - [ ] 错误处理完善 ### 性能测试 - [ ] 响应时间 < 15秒 - [ ] 音频质量良好 - [ ] 内存占用合理 - [ ] 网络流量可控 ### 兼容性测试 - [ ] iOS 设备 - [ ] Android 设备 - [ ] 不同网络环境 - [ ] 不同音色 ## 📞 技术支持 如遇问题,请提供: 1. 完整的前端控制台日志 2. 后端服务器日志 3. 录音文件信息 4. 网络环境 5. 设备信息 --- **最后更新**: 2026-03-05 **版本**: v2.0 - 完整语音对话