2025-4-11 16:01:31 只看该作者
1272浏览
查看: 1272|回复: 0
打印 上一主题 下一主题

[ESP8266/ESP32] ESP32-S3 AI CAM——自主可控的人工智能多模态LLM

[复制链接]
本帖最后由 kylinpoet 于 2025-4-11 16:21 编辑

一、【项目背景】

DF的ESP32-S3 AI CAM产品(产品链接)板载200W像160°广角红外夜视摄像头,MEMS麦克风和功放喇叭,以及基于ESP32的SOC芯片,妥妥的人工智能多模态交互利器。本项目预计通过网络大语言模型实现包括但不限于:语音识别、实时拍照、AI理解生成、语音合成等功能,做一个自主可控的多模态交互机器人。可用于实际生活的学习交流、视障人士环境理解等。

二、【功能实现】

1. 代码简析:

ESP32-S3 AI CAM的文档提供了一个OpenAI图像问答)点击访问,为节约成功,我们可以直接套用。但因为原作者的Github发布时间为2年前,有些代码需要更新修改,再加上网络原因,我们需要对其进行一些改造。
ESP32-S3 AI CAM——自主可控的人工智能多模态LLM图1

1)参数自定义
因为源码是使用 openai 的接口,这里可以根据实际情况进行参数自选。我修改了里面的 system 提示词,和 Temperature 让它的输出更可控点。
  1. system提示词:An Artificial Intelligence Big Language Model for Everyday Communication,always response in chinese,Your answer should focus on the key and be concise and comprehensive.
复制代码
文件名称:imageAnswering.ino
ESP32-S3 AI CAM——自主可控的人工智能多模态LLM图2

2)OpenAI.h 头文件的修改

原作者在代码里硬编码了openai的官网地址,但因为众所周知的原因,我们难以访问。因此我在OpenAI类的构造函数里添加了 openai_base_url,作为基址参数。这样可以自定义 openai 通用接口进行访问。
ESP32-S3 AI CAM——自主可控的人工智能多模态LLM图3

然后修改 OpenAI.CPP 主函数部分。注意的是每个函数都要修改。(因为原作者每个函数都硬编码了一遍),你可以搜索替换。

ESP32-S3 AI CAM——自主可控的人工智能多模态LLM图4

3)还有个需要修改的地方是 OpenAI::audio_post 函数。我们看到代码里作者也是硬编码了 wav 格式的播放。因为我的自定义接口不是以流的方式返回,并且返回的只有mp3格式,所以,这里就不处理 流 的问题,而是等它全部返回后直接处理。(这也是,我待会的演示视频里语音播放会慢的原因)。和小智对话机器人相比,我没有使用 websocket进行语音流接收,因此不是实时对话。(当然这只是演示实现,具体功能可后期再完善)

ESP32-S3 AI CAM——自主可控的人工智能多模态LLM图5

esp32的 I2S 包含库里有现成了 I2S::playMP3 和 I2S::playWAV 包装函数可以直接使用。因此,我们播放代码就大大简化了。

ESP32-S3 AI CAM——自主可控的人工智能多模态LLM图6

2. 完整代码:
完整代码,涉及 4 个文件,其中 camera.h 不做修改,其它文件请各位自行下载修改。这里只给出 OpenAI::audio_post 语音合成的代码作为实例:

  1. int OpenAI::audio_post(const String& endpoint, const String& jsonBody) {
  2.   log_d(""%s": %s", endpoint.c_str(), jsonBody.c_str());
  3.   // 初始化I2S
  4.   I2SClass i2s;
  5.   i2s.setPins(45, 46, 42);
  6. // pinMode(41, OUTPUT);
  7.   if (!i2s.begin(I2S_MODE_STD, 24000, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO)) {
  8.     log_e("MAX98357 initialization failed!");
  9.     return -1;
  10.   }
  11.   // WiFiClientSecure client;
  12.   HTTPClient http;
  13.   http.setTimeout(60000);
  14.   http.useHTTP10(true);
  15.   http.begin(base_url + endpoint);
  16.   //http.begin("" + endpoint);
  17.   http.addHeader("Content-Type", "application/json");
  18.   http.addHeader("Authorization", "Bearer " + api_key);
  19.   int httpCode = http.POST(jsonBody);
  20.   int totalBytesRead = 0; // 记录总共读取的字节数
  21.   if (httpCode != HTTP_CODE_OK) {
  22.     log_e("HTTP_ERROR: %d", httpCode);
  23.     http.end();
  24.     return -1;
  25.   }
  26.   // 获取响应内容
  27.   int contentLength = http.getSize();
  28.   uint8_t *audioData = (uint8_t *)malloc(contentLength); // 动态分配内存用于存储音频数据
  29.   if (audioData == nullptr) {
  30.     Serial.println("Failed to allocate memory");
  31.     return -1;
  32.   }
  33.   WiFiClient* stream = http.getStreamPtr();
  34.   // 读取完整的响应内容
  35.   int bytesRead = stream->readBytes(audioData, contentLength);
  36.   if (bytesRead == contentLength) {
  37.     // 调用您的播放函数
  38.     if (!i2s.playMP3(audioData, bytesRead)) {
  39.       log_e("Failed to play MP3");
  40.       free(stream);
  41.       return -1;
  42.     }
  43.   } else {
  44.     Serial.printf("Failed to read complete audio data, read only %d bytes\n", bytesRead);
  45.   }
  46.   http.end();
  47.   free(audioData); // 释放分配的内存
  48.   return bytesRead; // 返回实际解码数据大小
  49. }
复制代码

三、【功能演示】


本项目的基本操作是这样的。reset按键——>自动连接网络——>指示灯亮——>按 boot 键输入语音(5S)——>语音转文字——>拍照截图——>提交大语言模型识别——>返回生成内容——>文本转语音——>功放播放





您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail