目 录CONTENT

文章目录

Open-XiaoAI Bridge:让小爱音箱接入你的 AI Agent

Open-XiaoAI Bridge:让小爱音箱接入你的 AI Agent


📚 相关文章推荐

你可能还想看:

  1. 飞牛NAS部署OpenClaw教程:XXOS大佬一键应用轻松对接QQ机器人
  2. QQ小龙虾机器人接入OpenClaw保姆级教程
  3. 飞牛NAS安装CoPaw教程:国产AI Agent平台平替OpenClaw部署指南
  4. OpenClaw + Claude Code 教程:独立开发者搭建AI Agent系统实现94次/日代码提交

📢 关注「Geek 运维」

了解更多最新 Geek 技术分享!

关注 Geek 运维公众号

长按识别图中二维码,关注「Geek 运维」公众号,获取:

  • 最新 AI 技术资讯
  • 实用技术教程和工具
  • OpenClaw/Skills 使用指南
  • 运维开发最佳实践

🎯 项目概述

Open-XiaoAI Bridge 是一个强大的桥接器,它打破了小爱音箱的封闭生态,让你能够灵活接入多种 AI 服务(OpenClaw、小智 AI 等),并提供 HTTP API 实现远程控制。

核心功能

功能 说明
🦞 OpenClaw 集成 接入 OpenClaw,支持连续对话,可选豆包 TTS 或小爱原生 TTS
🤖 小智 AI 集成 接入 xiaozhi-esp32-server 实时音频流
🎙️ 自定义唤醒词 支持中英文,不同唤醒词可路由到不同 AI 服务或不同 OpenClaw Agent
🧠 多 Agent 路由 一台音箱,多个唤醒词,每个唤醒词对应不同的 OpenClaw Agent Session
💬 连续对话 多轮对话无需反复唤醒,喊"小爱同学"可随时打断
⚡ VAD + KWS 语音活动检测前置,减少无效识别,更省电
🌐 HTTP API 远程播放文字/音频、控制音箱
🧩 模块化 各功能独立开关,按需启用

项目亮点

这个项目由 Open-XiaoAI 的 examples/xiaozhi/ 演进而来,现已成为独立项目。它最大的特点是:

  1. 真正的连续对话:无需反复唤醒,自然流畅的对话体验
  2. 多 Agent 路由:一台音箱可以拥有多个 AI 人格,呼唤不同名字响应不同 Agent
  3. 灵活的 TTS 选择:支持小爱原生 TTS 和豆包语音合成
  4. 完整的 HTTP API:支持远程文字/音频播放、TTS 合成等控制功能

🏗️ 系统架构

整体架构图

┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│  小爱音箱   │ ←→  │ Bridge Server│ ←→  │ OpenClaw    │
│  (Client)   │     │  (Python)    │     │ Gateway     │
└─────────────┘     └──────────────┘     └─────────────┘
                           ↓                    ↓
                    ┌──────────────┐     ┌─────────────┐
                    │  小智 AI      │     │  AI Agent   │
                    │  (可选)      │     │  (自定义)   │
                    └──────────────┘     └─────────────┘

工作流程

1️⃣ 小智唤醒与对话

麦克风 → client → server → XiaoAI → GlobalStream → KWS/小爱 ASR
→ WakeupSessionManager → before_wakeup() → VAD speech/silence
→ XiaoZhi start/stop listening → xiaozhi-esp32-server

2️⃣ OpenClaw 单次对话

小爱指令 "让龙虾 xxx" → before_wakeup() → send_to_openclaw()
→ OpenClawManager → Gateway → Agent
→ 自动 TTS 播报 或 Agent 主动调用 xiaoai-tts skill

3️⃣ OpenClaw 连续对话

唤醒词 "你好龙虾" → WakeupSessionManager → OpenClawConversationController
→ 循环:VAD 检测语音 → SherpaASR 离线识别 → OpenClaw → TTS 播放
→ 说"退出"/"再见"退出

4️⃣ 远程控制

curl POST /api/play/text → API Server → SpeakerManager → 小爱音箱

🚀 快速开始

⚠️ 前置要求

重要:本项目仅包含服务端,需要先在小爱音箱上安装 Client 端。

步骤 1:刷机

更新小爱音箱固件,开启 SSH:

  • 访问刷机教程:https://github.com/idootop/open-xiaoai/blob/main/docs/flash.md
  • 根据你的音箱型号选择合适的刷机方案
  • 确保成功开启 SSH 访问

步骤 2:安装 Client 端

在音箱上运行 Rust Client 端:

  • 访问安装教程:https://github.com/idootop/open-xiaoai/blob/main/packages/client-rust/README.md
  • 按照教程在音箱上部署 Client 程序
  • 验证 Client 端正常运行

步骤 3:下载模型文件

如果你启用小智 AI 或 OpenClaw 连续对话功能,需要下载 VAD + KWS + ASR 模型文件:

  1. 从项目 releases 页面下载模型压缩包
  2. 解压模型文件到指定目录(Docker 部署解压到 ./models,本地编译解压到 core/models/

🐳 Docker Compose 部署(推荐)

1. 下载配置文件

# 创建项目目录
mkdir -p open-xiaoai-bridge
cd open-xiaoai-bridge

# 下载配置文件
curl -O https://raw.githubusercontent.com/coderzc/open-xiaoai-bridge/main/config.py
curl -O https://raw.githubusercontent.com/coderzc/open-xiaoai-bridge/main/docker-compose.yml

2. 准备模型文件

# 创建模型目录
mkdir -p models

# 将下载的模型文件解压到 models 目录
# 确保模型文件在 ./models 路径下

3. 配置环境变量

编辑 config.py 文件,根据你的实际情况修改配置:

APP_CONFIG = {
    # OpenClaw 配置
    "openclaw": {
        "url": "ws://127.0.0.1:18789",  # 修改为你的 OpenClaw WebSocket 地址
        "token": "your_openclaw_token",  # 修改为你的认证令牌
        "session_key": "agent:main:open-xiaoai-bridge",
        "identity_path": "/app/openclaw/identity/device.json",
        "tts_speaker": "xiaoai",  # "xiaoai" = 小爱原生 TTS;填豆包音色 ID 则用豆包 TTS
    },

    # 小智 AI 配置(如不需要可禁用)
    "xiaozhi": {
        "OTA_URL": "http://127.0.0.1:8003/xiaozhi/ota/",
        "WEBSOCKET_URL": "ws://127.0.0.1:8000/xiaozhi/v1/",
        "WEBSOCKET_ACCESS_TOKEN": "",
    },

    # 豆包 TTS 配置(可选)
    "tts": {
        "doubao": {
            "app_id": "你的 App ID",
            "access_key": "你的 Access Key",
            "default_speaker": "zh_female_vv_uranus_bigtts",
        }
    },
}

4. 启动服务

# 启动所有服务
docker compose up -d

# 查看日志
docker compose logs -f

# 停止服务
docker compose down

5. 验证部署

# 检查服务状态
docker compose ps

# 测试 API 端点
curl http://localhost:9092/api/health

💻 本地编译部署

1. 安装依赖

# 克隆项目
git clone https://github.com/coderzc/open-xiaoai-bridge.git
cd open-xiaoai-bridge

# 安装 Python 依赖(需要 uv)
uv sync

# 安装 Rust 依赖(需要 Rust)
cargo build --release

Linux 系统还需要安装:

# Ubuntu/Debian
sudo apt-get install pkg-config patchelf

# CentOS/RHEL
sudo yum install pkg-config patchelf

2. 准备模型文件

# 创建模型目录
mkdir -p core/models

# 将模型文件解压到 core/models/ 目录

3. 启动服务

# 设置环境变量并启动
API_SERVER_ENABLE=1 XIAOZHI_ENABLE=1 OPENCLAW_ENABLED=1 ./scripts/start.sh

⚙️ 环境变量配置

变量名 说明 默认值
XIAOZHI_ENABLE 启用小智 AI 禁用
OPENCLAW_ENABLED 启用 OpenClaw 禁用
API_SERVER_ENABLE 启用 HTTP API 禁用
API_SERVER_HOST API 监听地址 127.0.0.1
API_SERVER_PORT API 监听端口 9092
CONFIG_PATH 自定义配置文件路径 ./config.py
LOGLEVEL 日志级别 INFO

🔌 HTTP API 使用指南

设置 API_SERVER_ENABLE=1 启用 API Server,默认端口 9092

API 端点列表

方法 路径 说明
POST /api/play/text 播放文字(TTS)
POST /api/play/url 播放音频链接
POST /api/play/file 上传并播放音频文件
POST /api/tts/doubao 豆包 TTS 合成并播放
GET /api/tts/doubao_voices 获取可用音色列表
POST /api/wakeup 唤醒小爱音箱
POST /api/interrupt 打断当前播放
GET /api/status 获取播放状态
GET /api/health 健康检查

使用示例

1. 播放文字

curl -X POST http://localhost:9092/api/play/text \
  -H "Content-Type: application/json" \
  -d '{"text": "你好,我是小爱同学"}'

2. 播放音频链接

curl -X POST http://localhost:9092/api/play/url \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/audio.mp3"}'

3. 上传音频文件

curl -X POST http://localhost:9092/api/play/file \
  -F "file=@/path/to/audio.mp3"

4. 豆包 TTS 合成

curl -X POST http://localhost:9092/api/tts/doubao \
  -H "Content-Type: application/json" \
  -d '{"text": "你好", "speaker_id": "zh_female_cancan_mars_bigtts"}'

5. 打断播放

curl -X POST http://localhost:9092/api/interrupt

🦞 OpenClaw 集成详解

通过 OpenClaw 将小爱音箱变成你的 AI Agent 终端。

启用 OpenClaw

设置 OPENCLAW_ENABLED=1 启用 OpenClaw 集成。

三种交互方式

方式一:连续对话

用自定义唤醒词触发后进入多轮对话循环,全程本地处理,不依赖小爱 ASR:

唤醒词 "你好龙虾" → 提示音 → 你说话 → [VAD 检测] → [本地 ASR 识别] 
→ OpenClaw Agent → [TTS 播报] → 提示音 → 你继续说 → ...

特点: - 说"退出"或"再见"退出对话 - 小爱唤醒时自动打断 TTS 并退出 - 退出关键词可自定义

方式二:单次对话(发送并播报)

通过小爱语音指令发送一条消息给 Agent,收到回复后自动 TTS 播报:

# config.py 中的 before_wakeup
if "让龙虾" in text:
    await speaker.abort_xiaoai()
    await app.send_to_openclaw_and_play_reply(text.replace("让龙虾", ""))
    return None  # 框架不做额外处理

使用场景: 用户说"让龙虾查一下明天天气" → 打断小爱 → 发给 Agent → TTS 播报回复。

方式三:单次对话(Agent 自主播报)

只发送消息,不自动播报,由 Agent 调用 xiaoai-tts skill 自主播报:

if "告诉龙虾" in text:
    await speaker.abort_xiaoai()
    await app.send_to_openclaw(text.replace("告诉龙虾", ""))
    return None

使用场景: Agent 需要做复杂处理后再决定是否/如何播报的场景。


🎙️ 自定义唤醒词配置

基础配置

唤醒词在 config.pywakeup.keywords 中定义,支持中英文混合:

"wakeup": {
    "keywords": [
        "你好小智",        # 中文
        "小智小智",
        "hi open claw",    # 英文(全小写)
        "你好龙虾",
        "龙虾你好",
    ],
},

路由到不同 AI 服务

不同唤醒词可以路由到不同 AI 服务,在 before_wakeup 中根据文本内容判断:

async def before_wakeup(speaker, text, source, app):
    if source == "kws":          # 唤醒词触发
        if "龙虾" in text:
            await speaker.play(text="龙虾来了")
            return "openclaw"    # → OpenClaw 连续对话
        if "小智" in text:
            await speaker.play(text="小智来了")
            return "xiaozhi"     # → 小智 AI
        return None              # → 不处理

    if source == "xiaoai":       # 小爱语音指令
        if text == "召唤龙虾":
            await speaker.abort_xiaoai()
            return "openclaw"
        if text == "召唤小智":
            await speaker.abort_xiaoai()
            return "xiaozhi"
    # 返回 None → 交给小爱原生处理

返回值含义: - "openclaw" → 连续对话 - "xiaozhi" → 小智 AI - None → 不处理(用户可自行调用 app.send_to_openclaw() 等方法)


🧠 多 Agent 路由实战

核心概念

set_openclaw_session_key() 让你在发送消息前动态切换目标 Agent Session,无需重连,无性能开销。结合自定义唤醒词,可以实现:

一台音箱,N 个专属 AI 助手,按名字呼唤谁,谁就来响应。

配置示例

# config.py

AGENT_SESSIONS = {
    "龙虾": "agent:assistant:open-xiaoai-bridge",
    "小美": "agent:xiaomei:open-xiaoai-bridge",
    "管家": "agent:butler:open-xiaoai-bridge",
}

async def before_wakeup(speaker, text, source, app):
    if source == "kws":
        for keyword, session_key in AGENT_SESSIONS.items():
            if keyword in text:
                app.set_openclaw_session_key(session_key)  # 切换到对应 Agent
                await speaker.play(text=f"{keyword}来了")
                return "openclaw"                          # 进入连续对话

    if source == "xiaoai":
        for keyword, session_key in AGENT_SESSIONS.items():
            if f"召唤{keyword}" in text:
                app.set_openclaw_session_key(session_key)
                await speaker.abort_xiaoai()
                return "openclaw"

配合唤醒词配置:

"wakeup": {
    "keywords": [
        "你好龙虾", "你好小美", "你好管家",
    ],
},

使用效果

  • 你说"你好龙虾" → 进入龙虾 Agent 的上下文
  • 你说"你好小美" → 进入小美 Agent 的上下文
  • 你说"你好管家" → 进入管家 Agent 的上下文

同一台音箱,完全隔离的多个 AI 人格。

退出时的个性化提示

async def after_wakeup(speaker, source=None, session_key=None):
    if source == "openclaw":
        # session_key 格式:agent:<agentId>:<rest>,第二段即 agentId
        agent_id = session_key.split(":")[1] if session_key else None
        if agent_id == "assistant":
            await speaker.play(text="龙虾,再见")
        elif agent_id == "xiaomei":
            await speaker.play(text="小美,再见")
        elif agent_id == "butler":
            await speaker.play(text="管家,再见")
        else:
            await speaker.play(text="再见")
    if source == "xiaozhi":
        await speaker.play(text="小智,再见")

📝 rule_prompt 配置详解

有两个 prompt 配置,分别用于不同的播报场景:

配置 使用场景 自动追加位置
rule_prompt 自动播放、连续对话 send_to_openclaw_and_play_reply()、连续对话循环
rule_prompt_for_skill Agent 自主播报(方式三) send_to_openclaw()

为什么需要两个 prompt?

  1. rule_prompt:服务端会自动 TTS 播放,只需告诉 Agent 输出纯文字、控制字数
  2. rule_prompt_for_skill:服务端不会自动播放,需要告诉 Agent 主动调用 xiaoai-tts skill 来播报

示例配置

"openclaw": {
    # 自动播放/连续对话用:约束输出格式
    "rule_prompt": "注意:将结果处理成纯文字版,不要返回任何 markdown 格式,也不要包含任何代码块,并将字数控制在 300 字以内",

    # Agent 自主播报用:告诉 Agent 需要调用 skill
    "rule_prompt_for_skill": "注意:这条消息是主人通过小爱音箱发送的,他看不到你回复的文字,调用 `xiaoai-tts` skill 播报出来。字数控制在 300 字以内",
}

不需要可以留空或不设置。


🎵 TTS 音色配置

OpenClaw TTS 音色

openclaw.tts_speaker 支持两种值:

效果 说明
"xiaoai" 小爱原生 TTS 零配置即可使用,音色由设备决定
豆包音色 ID 豆包语音合成 需配置 tts.doubaoapp_idaccess_key

豆包 TTS 配置

1. 开通服务

  • 访问火山引擎语音合成服务:https://www.volcengine.com/docs/6561/1871062
  • 获取 App ID 和 Access Key
  • 参考接入文档:https://www.volcengine.com/docs/6561/1598757?lang=zh

2. 填入配置

"tts": {
    "doubao": {
        "app_id": "你的 App ID",
        "access_key": "你的 Access Key",
        "default_speaker": "zh_female_cancan_mars_bigtts",  # 默认音色
        "stream": True,           # 流式播放,首音延迟更低
        "audio_format": "pcm",    # 局域网推荐,首音更快
    }
}

3. 音色选择

  • 音色库列表:https://www.volcengine.com/docs/6561/1257544?lang=zh
  • 常用音色:zh_female_vv_uranus_bigttszh_female_cancan_mars_bigtts

4. 声音复刻(高级)

  1. 在火山引擎声音复刻控制台上传 10-30 秒音频
  2. 训练完成后到音色库复制音色 ID(格式 S_xxxxxxxx
  3. 重要:确保复刻音色与 tts.doubao.app_id 属于同一个火山引擎项目
  4. 填入配置:
"tts": {
    "doubao": {
        "default_speaker": "S_xxxxxxxx",
    }
}

流式播放配置

支持流式播放,推荐配置:

"tts": {
    "doubao": {
        "stream": True,           # 流式播放,首音延迟更低
        "audio_format": "pcm",    # 局域网推荐,首音更快
        # "audio_format": "auto", # 短文本 PCM,长文本 MP3
    }
}

格式对比: - pcm:首音快,流式稳定,长文本总耗时可能更高 - mp3:传输效率高,长文本更早结束 - auto:折中方案,按文本长度自动选择


❓ 常见问题

🎙️ 唤醒词与连续对话

Q1: 模型文件在哪下载?

启用小智 AI 或 OpenClaw 连续对话功能需要下载 VAD + KWS + ASR 模型文件,详见快速开始章节。

Q2: 如何打断 AI 的回答?

直接喊"小爱同学"即可打断小智或 OpenClaw 的回答。

Q3: 话没说完 AI 就开始回答?

调大 min_silence_duration

APP_CONFIG = {
    "vad": {
        "min_silence_duration": 1000,  # 毫秒
    },
}

Q4: 唤醒词没反应?

尝试以下方法:

  1. 调低 vad.threshold(越小越灵敏,如 0.05
  2. 启动后需等约 30s 加载模型
  3. 英文唤醒词用空格分开(如 "open ai"
  4. 换更易识别的唤醒词

🦞 OpenClaw

Q1: 首次连接出现 pairing required?

正常流程。保持服务在线,到 OpenClaw UI 批准设备:Nodes → Devices → Approve

Q2: 容器重建后需要重新配对?

Docker 部署时挂载 identity_path 目录为持久化卷,否则设备身份丢失需重新配对:

# docker-compose.yml
volumes:
  - ./openclaw:/app/openclaw

Q3: session_key 是什么?

告诉 Gateway 把消息路由到哪个 Agent Session,格式为冒号分隔的层级路径:

agent:<agentId>:<rest>
字段 说明 示例
agent 固定前缀 agent
<agentId> OpenClaw 中配置的 Agent ID(默认为 main) mainassistant
<rest> 会话标识,可自由命名 homeopen-xiaoai-bridge

常见格式举例:

agent:main:open-xiaoai-bridge          # 默认值(本项目)
agent:main:main                        # OpenClaw 原生默认主会话
agent:assistant:open-xiaoai-bridge     # 指定其他 Agent
agent:main:direct:alice                # 按用户隔离

Q4: 如何在运行时动态切换 session_key?

每次唤醒触发 before_wakeup 之前,框架会自动将 session_key 重置为配置文件中的默认值。因此:

  • before_wakeup 中调用 app.set_openclaw_session_key() → 本次唤醒使用指定的 session
  • 不调用 → 自动使用配置文件中的 openclaw.session_key,不会沿用上一次的值

🤖 小智 AI

Q1: 第一次运行提示验证码绑定设备?

打开小智 AI 管理后台(https://xiaozhi.me/),根据提示创建 Agent 绑定设备。验证码会在终端打印或写入 config.py

APP_CONFIG = {
    "xiaozhi": {
        "VERIFICATION_CODE": "首次登录时,验证码会在这里更新",
    },
}

绑定成功后可能需要重启应用。

Q2: 怎样使用自己部署的 xiaozhi-esp32-server?

修改 config.py 中的接口地址:

APP_CONFIG = {
    "xiaozhi": {
        "OTA_URL": "https://your-server/xiaozhi/ota/",
        "WEBSOCKET_URL": "wss://your-server/xiaozhi/v1/",
    },
}

🎬 演示视频


📚 参考资源

资源 链接
🔧 刷机教程 https://github.com/idootop/open-xiaoai/blob/main/docs/flash.md
🛠️ Client 端安装 https://github.com/idootop/open-xiaoai/blob/main/packages/client-rust/README.md
🎙️ 豆包 TTS 音色列表 https://www.volcengine.com/docs/6561/1257544
🤖 小智 AI 管理后台 https://xiaozhi.me/
📦 模型文件下载 https://github.com/coderzc/open-xiaoai-bridge/releases

💡 总结

Open-XiaoAI Bridge 是一个功能强大的小爱音箱桥接器,它让你能够:

✅ 接入 OpenClaw,实现连续对话和多 Agent 路由
✅ 接入小智 AI,使用实时音频流对话
✅ 自定义唤醒词,灵活路由到不同 AI 服务
✅ 使用豆包 TTS,获得更自然的语音合成效果
✅ 通过 HTTP API 远程控制音箱播放

无论是想打造一个智能语音助手,还是想探索多 Agent 协作,这个项目都能为你提供强大的支持。


📢 关注「Geek 运维」

了解更多最新 Geek 技术分享!

关注 Geek 运维公众号

长按识别图中二维码,关注「Geek 运维」公众号,获取:

  • 最新 AI 技术资讯
  • 实用技术教程和工具
  • OpenClaw/Skills 使用指南
  • 运维开发最佳实践
  • 第一手技术资源分享

项目地址:https://github.com/coderzc/open-xiaoai-bridge
作者:coderzc
协议:MIT License

如果这个项目对你有帮助,请给它一颗 ⭐️!

0

评论区