Files
server/docs/VOICE_CHAT_INTERACTION.md
2025-12-06 22:41:44 +08:00

5.5 KiB
Raw Blame History

语音对话接口交互文档

本文档详细描述了前端 webUI 与后端 server 之间关于语音对话功能(/voice-chat)的交互流程、参数传递及返回值结构。

1. 概述

语音对话功能允许用户录制一段语音,前端将其上传至后端。后端依次执行以下操作:

  1. STT (Speech-to-Text):将语音转换为文本。
  2. LLM (Large Language Model):将识别出的文本作为输入,获取 AI 的文本回复。
  3. TTS (Text-to-Speech):将 AI 的文本回复转换为语音。

最终后端将用户识别文本、AI 回复文本及合成的语音数据一次性返回给前端。

2. 前端调用 (WebUI)

前端主要涉及的文件为 webUI/src/components/ChatBox.vuewebUI/src/utils/api.js

2.1 调用方式

ChatBox.vue 中,当用户完成录音后,调用 handleVoiceModeMessage 方法,进而调用 voiceAPI.voiceChat

底层通过 uni.uploadFile 发起 multipart/form-data 类型的 POST 请求。

2.2 请求参数

前端向后端发送的请求包含 文件表单数据 (FormData)

  • URL: /api/chat/voice-chat (由 config.js 中的 VOICE_CHAT 常量定义)

  • Method: POST

  • Header: Authorization: Bearer <token>

  • 文件部分:

    • name: "audio"
    • filePath: 录音文件的本地路径 (e.g., .aac.wav)
  • 表单数据 (FormData):

参数名 类型 必填 说明 来源
sessionId String 会话 ID用于保持上下文 conversationId.value
modelId Integer 模型 ID characterConfig.modelId
templateId Integer 模板 ID characterConfig.templateId
voiceStyle String 语音风格 (用于 TTS) options.voiceStyle
ttsConfigId Integer TTS 配置 ID aiConfig.ttsId
sttConfigId Integer STT 配置 ID aiConfig.sttId
useFunctionCall Boolean 是否使用函数调用 默认为 false

2.3 响应处理

前端接收到后端返回的 JSON 数据后,进行如下解析:

  1. 用户文本: 从 sttResult.text 获取,显示在聊天界面右侧。
  2. AI 回复: 从 llmResult.response 获取,显示在聊天界面左侧。
  3. 语音播放: 优先使用 ttsResult.audioBase64 (Base64 编码音频),如果没有则使用 ttsResult.audioPath (音频 URL) 进行播放。

3. 后端处理 (Server)

后端入口为 server/src/main/java/com/xiaozhi/controller/ChatController.java,核心逻辑在 ChatSessionServiceImpl.java

3.1 接口定义

  • Controller: ChatController
  • Path: /api/chat/voice-chat
  • Consumes: multipart/form-data

3.2 处理流程

  1. 接收文件: 后端支持字段名为 audioFile, file, 或 audio 的文件上传 (前端使用 audio)。
  2. 参数解析: 解析 sessionId, modelId 等参数。
  3. 文件验证: 检查文件大小 (1KB - 50MB)、格式 (支持 mp3, wav, m4a, aac 等) 和 MIME 类型。
  4. 音频处理:
    • 将上传的音频文件保存为临时文件。
    • 使用 AudioUtils 将音频转换为 PCM 16k 单声道 格式(适配 STT 引擎)。
  5. 业务逻辑 (ChatSessionService.voiceChat):
    • STT: 调用配置的 STT 服务识别语音,得到 recognizedText
    • LLM: 如果识别到文本,调用 syncChat 获取 AI 回复 chatResponse
    • TTS: 调用 TTS 服务将 AI 回复转换为语音,生成音频文件并读取为 Base64。
  6. 结果封装: 将 STT、LLM、TTS 的结果封装到 Map 中返回。

4. 接口规范

4.1 请求结构

POST /api/chat/voice-chat Content-Type: multipart/form-data

Body:

  • audio: [二进制文件数据]
  • sessionId: "session_12345"
  • modelId: 10
  • templateId: 6
  • ...

4.2 响应结构

Content-Type: application/json

{
  "code": 200,
  "message": "语音对话成功",
  "data": {
    "sessionId": "session_12345",
    "timestamp": 1717660000000,
    
    // 1. STT 结果
    "sttResult": {
      "text": "你好,请介绍一下你自己。",  // 用户语音识别结果
      "audioSize": 32000,
      "sttProvider": "vosk"
    },
    
    // 2. LLM 结果
    "llmResult": {
      "response": "你好我是蔚AI很高兴为你服务。", // AI 回复文本
      "inputText": "你好,请介绍一下你自己。"
    },
    
    // 3. TTS 结果
    "ttsResult": {
      "audioBase64": "UklGRi...", // Base64 编码的音频数据 (用于直接播放)
      "audioPath": "audio/output/...", // 服务器音频文件路径
      "timestamp": 1717660005000
    },
    
    // 性能统计 (耗时: ms)
    "sttDuration": 500,
    "llmDuration": 1200,
    "ttsDuration": 800,
    
    // 文件元数据
    "originalFileName": "temp_audio.aac",
    "fileSize": 15000,
    "contentType": "audio/aac",
    "description": null
  }
}

4.3 错误响应

{
  "code": 400, // 或 500
  "message": "请求参数错误: 音频文件不能为空",
  "data": null
}

5. 总结

  • 交互模式: 同步一次性交互。前端发送音频,等待后端完成所有处理(识别+对话+合成)后,一次性接收所有数据。
  • 音频格式: 前端通常录制 aacwav,后端统一转码为 pcm 进行处理。
  • 回退机制: 如果后端处理失败,前端 ChatBox.vue 会捕获异常并提示用户,或使用本地模拟回复(在未登录等特定情况下)。