Skill: warm-winter/xiaoai-bridge (version 1.0.0)

--- name: xiaoai-bridge description: 小米小爱音箱语音指令桥接。截取小爱音箱的语音消息，转换为 AI 助手指令，并通过 TTS 回复。支持触发词过滤、自动去重、后台监听。适用于通过小爱音箱语音控制 OpenClaw 助手、智能家居联动、语音任务执行等场景。 version: 1.0.0 author: OpenClaw Community tags: [xiaomi, xiaoai, voice, tts, iot, smart-home] --- # 小爱音箱语音桥接 Skill 通过小米小爱音箱实现 OpenClaw 的语音交互能力。 ## 功能特性 ✅ **语音指令监听** - 实时轮询小爱音箱的语音消息（小米云端语音识别） ✅ **智能触发过滤** - 支持触发词前缀（默认"请"），避免误触发 ✅ **TTS 语音回复** - 将 AI 处理结果通过小爱音箱播报 ✅ **消息去重机制** - 自动跟踪时间戳，避免重复处理 ✅ **后台持续运行** - 支持长期监听，稳定可靠 ✅ **多设备支持** - 支持所有小米 IoT 生态的小爱音箱设备 ## 工作原理 1. **监听** - 轮询小爱音箱获取语音消息（小米云端语音转文字） 2. **处理** - 将语音消息转换为 AI 助手指令 3. **回复** - 通过小爱音箱 TTS 播报处理结果 ## 快速开始 ### 1. 安装依赖 ```bash cd skills/xiaoai-bridge/scripts npm install ``` ### 2. 配置环境变量 复制 `.env.example` 并填写配置： ```bash cp .env.example .env ``` 编辑 `.env` 文件： ```bash MI_USER_ID=1234567890 # 小米账号 ID（纯数字） MI_PASS_TOKEN=your_pass_token # 推荐：使用 passToken # MI_PASSWORD=your_password # 备选：密码（可能触发安全验证） MI_DEVICE_ID=小爱音箱Pro # 设备名称、miotDID 或 MAC 地址 TRIGGER_PREFIX=请 # 触发词前缀（默认"请"） POLL_INTERVAL=1000 # 轮询间隔（毫秒，默认 1000） ``` **获取 passToken**：参考 https://github.com/idootop/migpt-next/issues/4 **查找设备 ID**：运行 `DEBUG=true node scripts/xiaoai-listen.js test` 查看所有设备列表。 ### 3. 测试连接 ```bash node scripts/xiaoai-listen.js test ``` 预期输出： ``` 🔌 正在连接小爱音箱... ✅ 连接成功 ``` ### 4. 启动监听 后台运行监听服务： ```bash node scripts/xiaoai-listen.js > xiaoai.log 2>&1 & ``` 或���用 OpenClaw 进程管理（推荐）。 ## 使用示例 ### 示例 1：后台监听 + 消息处理 启动监听进程并解析 JSON 输出： ```javascript const { exec } = require('child_process'); const listener = exec('node skills/xiaoai-bridge/scripts/xiaoai-listen.js'); listener.stdout.on('data', (data) => { const lines = data.toString().split('\n'); for (const line of lines) { if (!line.trim()) continue; try { const msg = JSON.parse(line); if (msg.type === 'message') { // 处理语音指令 handleVoiceCommand(msg.text); } } catch (e) { // 非 JSON 的状态日志 console.log(line); } } }); async function handleVoiceCommand(text) { // 你的指令处理逻辑 const response = await processCommand(text); // 通过 TTS 回复 await exec(`node skills/xiaoai-bridge/scripts/xiaoai-listen.js speak "${response}"`); } ``` ### 示例 2：直接 TTS 播报 发送文本到小爱音箱： ```bash node scripts/xiaoai-listen.js speak "任务已完成" ``` 代码调用： ```javascript const { exec } = require('child_process'); function speakViaXiaoAi(text) { return new Promise((resolve, reject) => { exec(`node skills/xiaoai-bridge/scripts/xiaoai-listen.js speak "${text}"`, (error, stdout, stderr) => { if (error) reject(error); else resolve(); } ); }); } // 使用 await speakViaXiaoAi("你好，任务已完成"); ``` ### 示例 3：触发词过滤 Skill 自动过滤触发词前缀（默认"请"），只处理符合条件的消息： ```javascript // 用户说："请帮我查天气" → 处理，text = "帮我查天气" // 用户说："今天天气怎么样" → 忽略（无触发词） listener.stdout.on('data', (data) => { const lines = data.toString().split('\n'); for (const line of lines) { try { const msg = JSON.parse(line); if (msg.type === 'message') { // msg.text 已自动去除触发词前缀 console.log(`处理指令: ${msg.text}`); handleVoiceCommand(msg.text); } } catch (e) {} } }); ``` 自定义触发词（在 `.env` 中配置）： ```bash TRIGGER_PREFIX=请 # 默认 # TRIGGER_PREFIX=小助手 # 自定义唤醒词 # TRIGGER_PREFIX= # 空值 = 处理所有消息 ``` ## 消息格式 监听器输出 JSON 格式消息（仅处理符合触发词的消息）： ```json { "type": "message", "text": "查一下天气", "originalText": "请查一下天气", "timestamp": 1708070400000 } ``` **注意**：`text` 字段已自动去除触发词前缀。如需完整消息，使用 `originalText`。 ## API 参考 完整 MiGPT-Next API 文档见 [references/migpt-api.md](references/migpt-api.md)。 ### 脚本命令 ```bash # 启动监听（默认） node scripts/xiaoai-listen.js # TTS 播报文本 node scripts/xiaoai-listen.js speak "要说的话" # 测试连接 node scripts/xiaoai-listen.js test ``` ### 环境变量 | 变量 | 必需 | 说明 | |------|------|------| | `MI_USER_ID` | 是 | 小米账号 ID（纯数字） | | `MI_PASS_TOKEN` | 是* | passToken（推荐） | | `MI_PASSWORD` | 是* | 密码（可能触发安全验证） | | `MI_DEVICE_ID` | 是 | 设备名称、miotDID 或 MAC | | `TRIGGER_PREFIX` | 否 | 触发词前缀（默认"请"） | | `POLL_INTERVAL` | 否 | 轮询间隔（毫秒，默认 1000） | | `DEBUG` | 否 | 调试模式（true/false） | *`MI_PASS_TOKEN` 或 `MI_PASSWORD` 二选一。 ## 故障排查 ### 登录失败 **症状**：`❌ 连接失败: 登录失败` **解决方案**： 1. 使用 `passToken` 替代密码（推荐） 2. 检查 `MI_USER_ID` 是否为纯数字（不是手机号或邮箱） 3. 开启 `DEBUG=true` 查看详细错误信息 ### 找不到设备 **症状**：`❌ 找不到设备` **解决方案**：运行以下命令查看所有设备： ```bash DEBUG=true node scripts/xiaoai-listen.js test ``` 使用设备的 `name`、`miotDID` 或 `mac` 作为 `MI_DEVICE_ID`。 ### 收不到消息 **可能原因**： 1. 消息同步延迟（1-2 秒正常） 2. 设备离线或无响应 3. 自上次轮询后无新消息 ### 需要验证码 **症状**：`❌ 本次登录需要验证码` **解决方案**：必须使用 `passToken` 登录。参考 https://github.com/idootop/migpt-next/issues/4 ## 最佳实践 1. **使用 passToken** - 比密码更稳定，避免安全验证 2. **轮询间隔** - 1-2 秒最佳（平衡响应速度和 API 负载） 3. **消息去重** - 跟踪已处理的时间戳，避免重复处理 4. **错误处理** - 实现重试逻辑应对网络故障 5. **长文本分段** - 将长回复分句播报，提升 TTS 体验 ## 完整集成示例 与 OpenClaw 助手的完整集成： ```javascript const { exec } = require('child_process'); const path = require('path'); class XiaoAiBridge { constructor() { this.listener = null; this.lastTimestamp = Date.now(); } start(onMessage) { const scriptPath = path.join(__dirname, 'skills/xiaoai-bridge/scripts/xiaoai-listen.js'); this.listener = exec(`node ${scriptPath}`); this.listener.stdout.on('data', (data) => { const lines = data.toString().split('\n'); for (const line of lines) { if (!line.trim()) continue; try { const msg = JSON.parse(line); if (msg.type === 'message' && msg.timestamp > this.lastTimestamp) { this.lastTimestamp = msg.timestamp; onMessage(msg.text); } } catch (e) { console.log(line); // 状态日志 } } }); this.listener.stderr.on('data', (data) => { console.error('XiaoAi Error:', data.toString()); }); } async speak(text) { const scriptPath = path.join(__dirname, 'skills/xiaoai-bridge/scripts/xiaoai-listen.js'); return new Promise((resolve, reject) => { exec(`node ${scriptPath} speak "${text}"`, (error) => { if (error) reject(error); else resolve(); }); }); } stop() { if (this.listener) { this.listener.kill(); } } } // 使用示例 const bridge = new XiaoAiBridge(); bridge.start(async (voiceCommand) => { console.log(`收到语音指令: ${voiceCommand}`); // 用你的 AI 助手处理指令 const response = await yourAgentProcess(voiceCommand); // 通过小爱音箱回复 await bridge.speak(response); }); ``` ## 相关资源 - MiGPT-Next 项目：https://github.com/idootop/migpt-next - passToken 获取教程：https://github.com/idootop/migpt-next/issues/4 - API 完整文档：[references/migpt-api.md](references/migpt-api.md) ## 许可证 MIT License ## 贡献 欢迎提交 Issue 和 Pull Request！


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (CRITICAL)