X XiaoO AI

XiaoO WebSocket API 文档

文档更新时间: 20260713

1. 概述

本文档描述了通过 WebSocket 与服务端进行实时通信的 API。该 API 允许客户端建立持久连接,进行双向通信,主要用于语音识别、文本合成、聊天、IoT、MCP网关,以及私有网关协议调用第三方服务等,通过个性化大模型提示词可满足任意对话场景需求。

该协议兼容小智 AI WebSocket 报文协议。已有小智生态设备进入配网模式后,将 OTA Endpoint 配置为本平台 OTA 地址即可接入本平台服务,并在 Web 管理端激活设备。

本平台理论上支持小智所有版本的固件,因为协议是兼容的,不过未经测试的版本可能存在不稳定的情况,测试过的稳定版本如下(不断增加中):

1.1 平台开放能力

  • 实时音频编解码、降噪、压缩
  • 实时语音识别(Realtime ASR)
  • 实时声音活动检测(Realtime VAD)
  • 多Agent多模态大模型整合
  • 实时语音合成(Realtime TTS)
  • 用户意图识别引擎(Intent Engine)
  • 用户情绪识别引擎(Emotion Engine)
  • 开放MCP网关(整合MCP Tools、Resources、Prompts生态能力)
    • 支持MCP服务器自定义接入
    • 支持终端多MCP服务器调用
  • 私有网关协议,可插拔式对接自有系统(如:歌曲库、知识库等)、第三方平台
  • 物联网(IoT),通过MCP和私有网关协议控制设备
  • 架构灵活,扩展性强,以上能力模块皆可根据需要进行个性化组合

1.2 接入平台的应用形态

只要实现了本通信协议,任何载体都可接入,如:小程序、App、智能体硬件等。

2. 连接信息

3. 认证

方式一:HTTP Headers

在建立 WebSocket 连接时,需要在 HTTP 请求头中包含以下认证信息:

Authorization: Bearer {your_access_token}
Client-Id: {device_unique_id}
Device-Id: {device_mac_address}

字段说明:

当服务端配置 server.enable_auth = true 时,/v1/chat/v1/realtime_chat 都会校验以上信息,并要求设备已激活、令牌未过期且已绑定用户。/v1/vision 可不要求 Client-Id,但 WebSocket 入口要求 Client-Id

连接示例

浏览器原生 WebSocket API 不支持设置自定义 HTTP Header,因此下面示例使用 Node.js ws 客户端;浏览器接入需要通过后端代理、原生 App 容器或其它可设置 Header 的 WebSocket 客户端实现鉴权。

import WebSocket from 'ws';

const socket = new WebSocket('wss://your-server-domain.com/v1/chat', {
  headers: {
    Authorization: 'Bearer your_device_token',
    'Client-Id': 'device_uuid',
    'Device-Id': 'AA:BB:CC:DD:EE:FF'
  }
});

4. 消息格式

所有消息均使用 JSON 格式,分为文本消息和二进制消息两种类型:

文本json消息格式,完整参数详见各API

{
  "type": "message_type",
  ...
}

二进制消息

用于传输音频数据,采用 Opus 编码格式。

5. API清单

连接初始化

客户端 → 服务器

握手

例:

{
  "type": "hello",
  "version": 1,
  "transport": "websocket",
  "features": {
    "mcp": true
  },
  "audio_params": {
    "format": "opus",
    "sample_rate": 16000,
    "channels": 1,
    "frame_duration": 60
  }
}

说明:

  • features.mcp = true 时,服务端会把当前 WebSocket 连接复用为设备侧 MCP Server 通道,并在握手阶段向客户端发送 MCP JSON-RPC 初始化请求;客户端需要支持 type: "mcp" 消息。
  • 客户端上报的 audio_params 目前用于协议表达,服务端会以服务端配置的音频参数返回 hello,客户端应以服务端返回值为准。

语音识别请求

客户端 → 服务器

开始监听

握手成功后,客户端开始向服务端发送二进制音频流。

  • mode: auto,自动循环监听模式。
  • mode: manual,手动监听模式。

例:

{
  "type": "listen",
  "mode": "auto", // 可选值:`auto`, `manual`, `realtime`
  "state": "start",
  "session_id": "xxx" // hello握手成功后,服务端返回的
}

接下来客户端发送二进制音频数据(Opus 编码)

说明:listen start 必须在服务端返回 hello 后发送;普通 /v1/chat 链路会忽略握手前的 listen start

停止监听

例:

{
  "type": "listen",
  "mode": "auto",
  "state": "stop",
  "session_id": "xxx"
}

唤醒词检测

例:

{
  "session_id": "xxx",
  "type": "listen",
  "state": "detect",
  "text": "你好小明"
}

中断说话

reason值可为其他。

例:

{
  "session_id": "xxx",
  "type": "abort",
  "reason": "wake_word_detected"
}

IOT

发送当前设备的物联网相关信息:

  • Descriptors(描述设备功能、属性等)。
  • States(设备状态的实时更新)。

例:

{
  "session_id": "xxx",
  "type": "iot",
  "update": true,
  "descriptors": [
    {
      "name": "Speaker",
      "description": "扬声器",
      "methods": {
        "SetVolume": {
          "description": "设置音量",
          "parameters": {
            "volume": {
              "description": "音量0-100之间的整数",
              "type": "number"
            }
          }
        }
      },
      "properties": {
        "volume": {
          "description": "当前音量值",
          "type": "number"
        }
      }
    },
    { ... }
  ]
}

{
  "session_id": "xxx",
  "type": "iot",
  "update": true,
  "states": [
    {
      "name": "Speaker",
      "state": {
        "volume": 30
      }
    },
    {
      "name": "Screen",
      "state": {
        "brightness": 75,
        "theme": "dark"
      }
    },
    {
      "name": "Battery",
      "state": {
        "charging": false,
        "level": 84
      }
    },
    { ... }
  ]
}

MCP

当客户端在 hello.features.mcp 中声明支持 MCP 后,服务端和客户端通过 type: "mcp" 文本消息传递 JSON-RPC 2.0 payload。

服务端会主动发送 initializetools/listtools/call 等请求;客户端需要把 JSON-RPC 响应放回 payload 字段。

例:

{
  "session_id": "xxx",
  "type": "mcp",
  "payload": {
    "jsonrpc": "2.0",
    "id": "request-id",
    "result": {
      "tools": []
    }
  }
}

OTA

发送当前设备信息

例:

{
  "application": {
    "compile_time": "Mar 31 2025T16:48:23Z",
    "elf_sha256": "bd3ac81a0f6dd726143e93b027a6630684d82cbba681ae0359e212375a516f31",
    "idf_version": "v5.4-dirty",
    "name": "xiaozhi",
    "version": "1.5.5"
  },
  "board": {
    "channel": 3,
    "ip": "192.168.101.232",
    "mac": "b4:3a:45:a6:41:a4",
    "name": "bread-compact-wifi",
    "rssi": -31,
    "ssid": "客厅",
    "type": "bread-compact-wifi"
  },
  "chip_info": {
    "cores": 2,
    "features": 18,
    "model": 9,
    "revision": 2
  },
  "chip_model_name": "esp32s3",
  "flash_size": 16777216,
  "language": "zh-CN",
  "mac_address": "b4:3a:45:a6:41:a4",
  "minimum_free_heap_size": 8298820,
  "ota": {
    "label": "ota_0"
  },
  "partition_table": [
    {
      "address": 36864,
      "label": "nvs",
      "size": 16384,
      "subtype": 2,
      "type": 1
    },
    {
      "address": 53248,
      "label": "otadata",
      "size": 8192,
      "subtype": 0,
      "type": 1
    },
    {
      "address": 61440,
      "label": "phy_init",
      "size": 4096,
      "subtype": 1,
      "type": 1
    },
    {
      "address": 65536,
      "label": "model",
      "size": 983040,
      "subtype": 130,
      "type": 1
    },
    {
      "address": 1048576,
      "label": "ota_0",
      "size": 6291456,
      "subtype": 16,
      "type": 0
    },
    {
      "address": 7340032,
      "label": "ota_1",
      "size": 6291456,
      "subtype": 17,
      "type": 0
    }
  ],
  "uuid": "2dc1510b-4fdb-43ce-b8f1-074309f954bc",
  "version": 2
}
服务器 → 客户端

(语音识别实时状态更新):

Hello

例:

{
  "type": "hello",
  "version": 1,
  "transport": "websocket",
  "session_id": "xxx",
  "audio_params": {
    "format": "opus",
    "sample_rate": 16000,
    "channels": 1,
    "frame_duration": 60
  }
}

STT

表示服务器端识别到了用户语音。(例如语音转文本结果)。

设备可能将此文本显示到屏幕上,后续再进入回答等流程。

例:

{
  "type": "stt",
  "session_id": "xxx",
  "text": "..."
}

LLM

服务器指示设备调整表情动画 / UI 表达。

例:

{
  "type": "llm",
  "session_id": "xxx",
  "emotion": "happy",
  "text": "😀"
}

TTS

服务器准备下发 TTS 音频,客户端进入 "speaking" 播放状态。

  • state: stop,表示本次 TTS 结束。
  • state: sentence_start,让设备在界面上显示当前要播放或朗读的文本片段。
  • state: sentence_end, 停止朗读文本显示。

例:

{
  "type": "tts",
  "session_id": "xxx",
  "state": "start", // 可选值:"start", "stop", "sentence_start"
  "text": "😀"
}

IOT

服务器向设备发送物联网的动作指令,设备解析并执行(如打开灯、设置温度等)。

例:

{
  "type": "iot",
  "session_id": "xxx",
  "commands": [ ... ]
}

MCP

服务端发给客户端的 MCP 消息同样使用 payload 包装原始 JSON-RPC 请求。

例:

{
  "type": "mcp",
  "session_id": "xxx",
  "payload": {
    "jsonrpc": "2.0",
    "id": "request-id",
    "method": "tools/call",
    "params": {
      "name": "tool_name",
      "arguments": {}
    }
  }
}

音频数据:二进制帧

  • 当服务器发送音频二进制帧(Opus 编码)时,客户端解码并播放。
  • 若客户端正在处于 "listening" (录音)状态,收到的音频帧会被忽略或清空以防冲突。

6. 音频编解码

  1. 客户端发送录音数据
    • 音频输入经过可能的回声消除、降噪或音量增益后,通过 Opus 编码打包为二进制帧发送给服务器。
    • 如果客户端每次编码生成的二进制帧大小为 N 字节,则会通过 WebSocket 的 binary 消息发送这块数据。
  2. 客户端播放收到的音频
    • 收到服务器的二进制帧时,同样认定是 Opus 数据。
    • 设备端会进行解码,然后交由音频输出接口播放。
    • 如果服务器的音频采样率与设备不一致,会在解码后再进行重采样。

7. 常见状态流转

以下简述设备端关键状态流转,与 WebSocket 消息对应:

1. Idle → Connecting
用户触发或唤醒后,设备调用 OpenAudioChannel() → 建立 WebSocket 连接 → 发送 "type":"hello"
2. Connecting → Listening
成功建立连接后,若继续执行 SendStartListening(...),则进入录音状态。此时设备会持续编码麦克风数据并发送到服务器。
3. Listening → Speaking
收到服务器 TTS Start 消息 ({"type":"tts","state":"start"}) → 停止录音并播放接收到的音频。
4. Speaking → Idle
服务器 TTS Stop ({"type":"tts","state":"stop"}) → 音频播放结束。若未继续进入自动监听,则返回 Idle;如果配置了自动循环,则再度进入 Listening。
5. Listening / Speaking → Idle(遇到异常或主动中断)
调用 SendAbortSpeaking(...)CloseAudioChannel() → 中断会话 → 关闭 WebSocket → 状态回到 Idle。

8. 错误处理

  1. 连接失败

    如果 Connect(url) 返回失败或在等待服务器 "hello" 消息时超时,触发 on_network_error_() 回调。设备会提示"无法连接到服务"或类似错误信息。

  2. 服务器断开

    如果 WebSocket 异常断开,回调 OnDisconnected()

    • 设备回调 on_audio_channel_closed_()
    • 切换到 Idle 或其他重试逻辑。

9. 其它注意事项

  1. 鉴权

    设备通过设置 Authorization: Bearer <token> 提供鉴权,服务器端需验证是否有效。

    如果令牌过期或无效,服务器可拒绝握手或在后续断开。

  2. 会话控制

    服务端返回 hello 后会分配 session_id。后续客户端消息建议带上该值;当前服务端主要依赖连接内会话状态处理消息,MCP、STT、TTS、LLM 等服务端下发消息会携带 session_id

  3. 音频负载

    代码里默认使用 Opus 格式,并设置 sample_rate = 16000,单声道。帧时长由 OPUS_FRAME_DURATION_MS 控制,一般为 60ms。可根据带宽或性能做适当调整。

  4. IoT 指令

    "type":"iot" 的消息用户端代码对接 thing_manager 执行具体命令,因设备定制而不同。服务器端需确保下发格式与客户端保持一致。

  5. 错误或异常 JSON

    当 JSON 中缺少必要字段,例如 {"type": ...},客户端会记录错误日志(ESP_LOGE(TAG, "Missing message type, data: %s", data);),不会执行任何业务。

10. 连接状态管理

11. 附录

音频规格

  • 采样率: 16kHz
  • 通道数: 单声道
  • 编码格式: Opus
  • 帧大小: 960 (60ms)

实现建议

  1. 确保适当处理网络波动和连接中断
  2. 实现音频缓冲以平滑播放
  3. 在较差的网络条件下使用较低的比特率

问题反馈、技术支持、合作联系

Email: xiao-o_service@odsio.com