游乐游手机版
首页/AI热点日报/热点详情

小智AI复刻第2步:WebSocket协议核心流程图学习

类型:热点整理2026-07-08
在复刻小智AI的过程中,本次重点围绕WebSocket协议的核心流程展开,旨在深入剖析实时通信的底层实现机制。文章将涵盖以下核心内容:基于Arduino框架的复刻背景、WebSocket协议在小智AI通信中的关键作用与数据类型,以及建立连接的详细步骤与配置参数。 前言 本次继续沿用复刻小智AI的技术

在复刻小智AI的过程中,本次重点围绕WebSocket协议的核心流程展开,旨在深入剖析实时通信的底层实现机制。文章将涵盖以下核心内容:基于Arduino框架的复刻背景、WebSocket协议在小智AI通信中的关键作用与数据类型,以及建立连接的详细步骤与配置参数。

复刻小智AI第2步,2张核心流程图学习一下它的WebSocket协议

前言

本次继续沿用复刻小智AI的技术路线,但将开发框架切换为Arduino。

上周已经完成了VSCode + PlatformIO + Arduino环境下ESP32-S3、ESP-SR、ESP-TTS整套开发环境的搭建(详细过程可参阅上一篇文章),并成功实现了语音唤醒、命令识别以及文本转语音功能。接下来的核心任务就是对接小智AI服务端的WebSocket协议。

原项目78/xiaozhi-esp32功能虽然完整,但代码结构较为复杂,阅读门槛相对较高,且实在不想重新搭建IDF编译环境。后续发现了一个Python实现的桌面客户端huangjunsen0406/py-xiaozhi,它不仅带有图形界面,还支持手动与自动对话模式的切换,是一个很好的学习样本,可以一边研究PC端轻量级语音识别的实现,一边深入理解WebSocket通信。

通信过程

小智AI客户端与服务端之间的通信可以选择WebSocket或MQTT,这里我们选择更易于上手的WebSocket协议进行实现。

协议概述

WebSocket负责客户端与服务器之间的实时双向通信,主要涉及以下几类数据:

  • 控制指令:用于开始/停止监听、中断TTS播放等操作。
  • 文本信息:包含LLM响应内容、情绪指令、配置信息等。
  • 音频数据
    • 客户端 → 服务器:传输录制好的Opus编码音频流。
    • 服务器 → 客户端:推送TTS生成的Opus编码音频流。
  • 状态同步:用于同步TTS播放开始/结束等状态。

通信格式分为两种:JSON格式用于传输文本、控制和状态信息;Binary格式用于传输Opus编码的音频数据。

建立连接

  1. 客户端发起连接:根据配置文件中的WEBSOCKET_URL地址,向服务器发起WebSocket连接请求。

  2. 发送头部信息:连接时需附带必要的HTTP头部信息,具体包括:

    • Authorization: Bearer (来源于配置中的WEBSOCKET_ACCESS_TOKEN
    • Protocol-Version: 1
    • Client-Id: 客户端标识
    • Device-Id: 设备标识(通常使用MAC地址)

    目前除了Device-Id需要客户端自行生成外,其他参数均可直接使用示例中的固定值:

    "WEBSOCKET_URL": "wss://api.tenclass.net/xiaozhi/v1/",
    "WEBSOCKET_ACCESS_TOKEN": "test-token",
    "CLIENT_ID": "1dd91545-082a-454e-a131-1c8251375c9c",
  3. 服务器响应:服务器接受连接请求。

  4. 客户端发送hello:连接成功后,客户端需要发送一条JSON格式的hello消息:

    hello_message = {
      "type": "hello",
      "version": 1,
      "transport": "websocket",
      "audio_params": {
        "format": AudioConfig.FORMAT,
        "sample_rate": AudioConfig.SAMPLE_RATE,
        "channels": AudioConfig.CHANNELS,
        "frame_duration": AudioConfig.FRAME_DURATION,
      }
    }

    这里预设的音频编码参数问题不大,服务器后续会推送其实际接受的音频配置。

  5. 服务器响应hello:服务器返回会话ID和初始配置信息:

    {
      "type": "hello",
      "version": 1,
      "transport": "websocket",
      "audio_params": {
        "format": "opus",
        "sample_rate": 24000,
        "channels": 1,
        "frame_duration": 20
      },
      "session_id": "a1f81xs89"
    }

    这里有两点需要特别注意:客户端必须保存返回的session_id,后续所有需要会话标识的消息都会用到它;此外,还需根据audio_params更新本地的Opus编码设置,以确保编解码参数一致。

服务端认证

首次连接到小智AI官方后台时,需要在控制台中添加设备。具体操作非常便捷:当客户端成功连接服务器并发送第一条语音消息时,服务器会返回一条语音,并附带一个6位数的验证码,使用该验证码即可在后台完成设备添加。

至此,WebSocket连接已成功建立,接下来就可以进行后续的对话流程了。

客户端消息

主动发起对话的机制与之前一致——要么通过手动触发录音,要么通过唤醒词触发。

listen (JSON)

用于控制音频监听(录音)的状态。

  • 开始监听
    {
      "session_id": "session-id",
      "type": "listen",
      "state": "start",
      "mode": "manual" | "auto" | "realtime"  // 监听模式
    }
  • 停止监听
    {
      "session_id": "session-id",
      "type": "listen",
      "state": "stop"
    }

wake_word (JSON)

如果通过唤醒词启动对话,需要发送另一种listen消息,告知服务器已检测到唤醒词。这样服务器会立即返回一条语音消息作为回应。

  • 格式
    {
      "session_id": "session-id",
      "type": "listen",
      "state": "detect",
      "text": "你好小智"  // 根据实际唤醒词修改
    }

abort (JSON)

用于请求服务器中断当前正在进行的操作(主要是TTS语音播放)。

  • 格式
    {
      "session_id": "session-id",
      "type": "abort",
      "reason": "wake_word_detected"  // (可选)中断原因
    }

这个功能主要用在当服务器正在输出一段较长的语音,而用户希望重新开始新对话的场景。

audio (Binary)

用于发送录制的音频数据。

  • 格式:二进制数据帧 (Binary Frame)。
  • 内容:根据session_infoaudio_config约定的格式(默认为Opus)编码的音频数据块。

IoT 消息

这部分内容暂时不涉及,留待后续研究具体格式。

服务端消息

小智AI服务端返回的消息同样分为JSON和Binary两种格式,JSON类型通过type字段来区分实际内容。示例JSON格式如下:

{
  "type": "tts",
  "state": "start",
  "sample_rate": 24000,
  "session_id": "session-id"
}

type字段的可能取值包括llmttsstt等。

type=tts (JSON)

这是服务端返回的核心消息类型,其中包含了情绪、语音输出以及语音识别结果等信息。可以说,小智AI的整个交互流程,主要工作都由服务端承担,客户端的实现相对轻量。

根据state字段的不同值,需要进行针对性处理:

state=start

服务器接收到客户端的语音数据后,生成了LLM聊天对话内容,并开始返回语音数据。同时会提供音频sample_rate参数,客户端可根据此参数同步更新播放配置。

{
  "type": "tts",
  "state": "start",
  "sample_rate": 24000,
  "session_id": "session-id"
}

state=sentence_start

表示对话中的一句话开始,text字段包含该句话的文本内容。

{
  "type": "tts",
  "state": "sentence_start",
  "text": "感觉你心情不太好,发生了什么事吗?",
  "session_id": "session-id"
}

state=sentence_end

表示一句话结束。

{
  "type": "tts",
  "state": "sentence_end",
  "text": "感觉你心情不太好,发生了什么事吗?",
  "session_id": "session-id"
}

state=stop

表示服务端对之前收到的语音数据生成的响应内容已整体结束,客户端可以继续录音操作。

{
  "type": "tts",
  "state": "stop",
  "session_id": "session-id"
}

type=llm (JSON)

用于返回大模型回复时需要表达的情绪状态。text字段是一个Emoji表情,emotion字段对应情绪单词。在无法显示Emoji的设备上,可以通过单词映射到对应的图片进行展示。

{
  "type": "llm",
  "text": "
来源:https://www.53ai.com/news/zhinengyingjian/2025041775418.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。