# 超级小智-ESP32 (中文 | English(编写中) | 日本語(编写中)) 基于 https://github.com/78/xiaozhi-esp32 改良的船新版本 ## 💡介绍 这是一个由虾哥开源的 ESP32 项目,以 MIT 许可证发布,允许任何人免费使用,或用于商业用途。 我们希望通过这个项目,能够帮助大家了解 AI 硬件开发,将当下飞速发展的大语言模型应用到实际的硬件设备中。 如果你有任何想法或建议,请随时提出 Issues 或加入 QQ 群:暂无,Telegram群:暂无。 项目主要贡献者:小霜霜Meow(抖音、B站UP)、空白泡泡糖果(B站UP),硅灵造物科技(B站UP) 贡献者说明:引入部分其它贡献者在其它项目上的代码,并进行了部分修改。 音乐服务器、相关源码提供者(为爱发电):小霜霜Meow 音乐服务器源码请见 https://github.com/IntelligentlyEverything/MeowMusicServer ### ❕注意事项 1. 如果小智说找不到歌曲怎么办? 进入[小智后台](https://xiaozhi.me/),找到对应设备,修改角色配置 - 选择 DeepSeekV3 大语言模型 - 在人物介绍中填入 - 收到音乐相关的需求时,只使用 MPC tool self.music.play_song 工具,同时禁止使用 search_music 功能。 2. 内置API调用失败怎么办? 请查看具体错误代码后,加入QQ群:865754861,或电报群 http://t.me/MeowMusicServer 给出错误代码和日志,等待我们修复。 3. 歌曲播放时唤醒词不生效怎么办? 把main\application.cc文件的AddAudioData方法改成如下代码 ``` c++ void Application::AddAudioData(AudioStreamPacket&& packet) { auto codec = Board::GetInstance().GetAudioCodec(); if (device_state_ == kDeviceStateIdle && codec->output_enabled()) { // packet.payload包含的是原始PCM数据(int16_t) if (packet.payload.size() >= 2) { size_t num_samples = packet.payload.size() / sizeof(int16_t); std::vector pcm_data(num_samples); memcpy(pcm_data.data(), packet.payload.data(), packet.payload.size()); // 检查采样率是否匹配,如果不匹配则进行简单重采样 if (packet.sample_rate != codec->output_sample_rate()) { // ESP_LOGI(TAG, "Resampling music audio from %d to %d Hz", // packet.sample_rate, codec->output_sample_rate()); // 验证采样率参数 if (packet.sample_rate <= 0 || codec->output_sample_rate() <= 0) { ESP_LOGE(TAG, "Invalid sample rates: %d -> %d", packet.sample_rate, codec->output_sample_rate()); return; } std::vector resampled; // 使用浮点数计算精确的重采样比率Add commentMore actions float ratio = static_cast(packet.sample_rate) / codec->output_sample_rate(); if (packet.sample_rate > codec->output_sample_rate()) { // 降采样:按精确比率跳跃采样 size_t expected_size = static_cast(pcm_data.size() / ratio + 0.5f); resampled.reserve(expected_size); for (float i = 0; i < pcm_data.size(); i += ratio) { size_t index = static_cast(i + 0.5f); // 四舍五入 if (index < pcm_data.size()) { resampled.push_back(pcm_data[index]); } } ESP_LOGD(TAG, "Downsampled %d -> %d samples (ratio: %.3f)", pcm_data.size(), resampled.size(), ratio); } else { // 上采样:线性插值 float upsample_ratio = codec->output_sample_rate() / static_cast(packet.sample_rate); size_t expected_size = static_cast(pcm_data.size() * upsample_ratio + 0.5f); resampled.reserve(expected_size); for (size_t i = 0; i < pcm_data.size(); ++i) { // 添加原始样本 resampled.push_back(pcm_data[i]); // 计算需要插值的样本数 int interpolation_count = static_cast(upsample_ratio) - 1; if (interpolation_count > 0 && i + 1 < pcm_data.size()) { int16_t current = pcm_data[i]; int16_t next = pcm_data[i + 1]; for (int j = 1; j <= interpolation_count; ++j) { float t = static_cast(j) / (interpolation_count + 1); int16_t interpolated = static_cast(current + (next - current) * t); resampled.push_back(interpolated); } } else if (interpolation_count > 0) { // 最后一个样本,直接重复 for (int j = 1; j <= interpolation_count; ++j) { resampled.push_back(pcm_data[i]); } } } ESP_LOGI(TAG, "Upsampled %d -> %d samples (ratio: %.2f)", pcm_data.size(), resampled.size(), upsample_ratio); } pcm_data = std::move(resampled); } // 确保音频输出已启用 if (!codec->output_enabled()) { codec->EnableOutput(true); } // 发送PCM数据到音频编解码器 codec->OutputData(pcm_data); // 更新最后输出时间,防止OnAudioOutput自动禁用音频 { std::lock_guard lock(mutex_); last_output_time_ = std::chrono::steady_clock::now(); } } } } ``` ### ⚙️已支持硬件芯片系列 - ESP32 - ESP32-S2 - ESP32-S3 - ESP32-C2 - ESP32-C3 - ESP32-C5 - ESP32-C6 - ESP32-C61 - ESP32-H2 - ESP32-H4 - ESP32-H21 - ESP32-P4 ❕大部分硬件由于没有进行完整测试,可能会存在一些问题,属于正常现象,具体可提交issues进行反馈。 ### 项目改动范围 新增: - main/boards/common/music.h - main/boards/common/esp32_music.h - main/boards/common/esp32_music.cc 修改: - main/audio/audio_codec.h - main/audio/audio_codec.cc - main/audio/audio_service.h - main/audio/audio_service.cc - main/boards/common/board.h - main/boards/common/board.cc - main/display/display.h - main/display/display.cc - main/display/lcd_display.h - main/display/lcd_display.cc - main/application.h - main/application.cc - main/idf_component.yml - main/mcp_server.cc ### 基于 MCP 控制万物 小智 AI 聊天机器人作为一个语音交互入口,利用 Qwen / DeepSeek 等大模型的 AI 能力,通过 MCP 协议实现多端控制。 ![通过MCP控制万物](docs/mcp-based-graph.jpg) ### 已实现功能 - Wi-Fi / ML307 Cat.1 4G - 离线语音唤醒 [ESP-SR](https://github.com/espressif/esp-sr) - 支持两种通信协议([Websocket](docs/websocket.md) 或 MQTT+UDP) - 采用 OPUS 音频编解码 - 基于流式 ASR + LLM + TTS 架构的语音交互 - 声纹识别,识别当前说话人的身份 [3D Speaker](https://github.com/modelscope/3D-Speaker) - OLED / LCD 显示屏,支持表情显示 - 电量显示与电源管理 - 支持多语言(中文、英文、日文) - 支持 ESP32-C3、ESP32-S3、ESP32-P4 芯片平台 - 通过设备端 MCP 实现设备控制(音量、灯光、电机、GPIO 等) - 通过云端 MCP 扩展大模型能力(智能家居控制、PC桌面操作、知识搜索、邮件收发等) 本项目新增功能: - 新增音乐播放功能,支持播放本地音乐(开发中,敬请期待)、云端音乐(完善中)。 ## 硬件 ### 面包板手工制作实践 详见飞书文档教程: 👉 [《小智 AI 聊天机器人百科全书》](https://ccnphfhqs21z.feishu.cn/wiki/F5krwD16viZoF0kKkvDcrZNYnhb?from=from_copylink) 面包板效果图如下: ![面包板效果图](docs/v1/wiring2.jpg) ### 支持 70 多个开源硬件(仅展示部分) - 立创·实战派 ESP32-S3 开发板 - 乐鑫 ESP32-S3-BOX3 - M5Stack CoreS3 - M5Stack AtomS3R + Echo Base - 神奇按钮 2.4 - 微雪电子 ESP32-S3-Touch-AMOLED-1.8 - LILYGO T-Circle-S3 - 虾哥 Mini C3 - 璀璨·AI 吊坠 - 无名科技 Nologo-星智-1.54TFT - SenseCAP Watcher - ESP-HI 超低成本机器狗 ## 软件 ### 固件烧录 新手第一次操作建议先不要搭建开发环境,直接使用免开发环境烧录的固件。 固件默认接入 [xiaozhi.me](https://xiaozhi.me) 官方服务器,个人用户注册账号可以免费使用 Qwen 实时模型。 👉 [新手烧录固件教程](https://ccnphfhqs21z.feishu.cn/wiki/Zpz4wXBtdimBrLk25WdcXzxcnNS) ### 开发环境 - Cursor 或 VSCode - 安装 ESP-IDF 插件,选择 SDK 版本 5.4 或以上 - Linux 比 Windows 更好,编译速度快,也免去驱动问题的困扰 - 本项目使用 Google C++ 代码风格,提交代码时请确保符合规范 ### 开发者文档 - [自定义开发板指南](main/boards/README.md) - 学习如何为小智 AI 创建自定义开发板 - [MCP 协议物联网控制用法说明](docs/mcp-usage.md) - 了解如何通过 MCP 协议控制物联网设备 - [MCP 协议交互流程](docs/mcp-protocol.md) - 设备端 MCP 协议的实现方式 - [MQTT + UDP 混合通信协议文档](docs/mqtt-udp.md) - [一份详细的 WebSocket 通信协议文档](docs/websocket.md) ## 大模型配置 如果你已经拥有一个小智 AI 聊天机器人设备,并且已接入官方服务器,可以登录 [xiaozhi.me](https://xiaozhi.me) 控制台进行配置。 👉 [后台操作视频教程(旧版界面)](https://www.bilibili.com/video/BV1jUCUY2EKM/) ## 相关开源项目 在个人电脑上部署服务器,可以参考以下第三方开源的项目: - [xinnan-tech/xiaozhi-esp32-server](https://github.com/xinnan-tech/xiaozhi-esp32-server) Python 服务器 - [joey-zhou/xiaozhi-esp32-server-java](https://github.com/joey-zhou/xiaozhi-esp32-server-java) Java 服务器 - [AnimeAIChat/xiaozhi-server-go](https://github.com/AnimeAIChat/xiaozhi-server-go) Golang 服务器 使用小智通信协议的第三方客户端项目: - [huangjunsen0406/py-xiaozhi](https://github.com/huangjunsen0406/py-xiaozhi) Python 客户端 - [TOM88812/xiaozhi-android-client](https://github.com/TOM88812/xiaozhi-android-client) Android 客户端 - [100askTeam/xiaozhi-linux](http://github.com/100askTeam/xiaozhi-linux) 百问科技提供的 Linux 客户端 - [78/xiaozhi-sf32](https://github.com/78/xiaozhi-sf32) 思澈科技的蓝牙芯片固件 - [QuecPython/solution-xiaozhiAI](https://github.com/QuecPython/solution-xiaozhiAI) 移远提供的 QuecPython 固件 ## Star History Star History Chart