-
本方案为esp32cam 服务端 浏览器 三端联合使用。将服务端部署在公网即可远程使用,没有远程需求,可以直接在局域网使用。代码无需修改。
-
本文取缔了esp32cam自身运行http服务的相关逻辑,使得esp32cam只负责不停拍照片发给服务端,从而减少esp32cam的压力,提升了其视频流畅度。
-
本文代码开源地址:https://gitcode.net/qq_26700087/simpleVideoServer
SimpleVideoServer-esp32cam视频示意
您需要准备| 物料 | 说明 |
|---|---|
| esp32cam开发板 | esp32cam,本人是使用其自带摄像头,代码仅仅在其自带摄像头下测试 |
| 一台装有windows或者linux操作系统的计算机 | 用于运行服务端 |
| USB转TTL模块/或底座 | 用于烧录/串口监控 |
| 杜邦线若干 | 用于io0接地/使用底座烧录不需要 |
鄙人无MacOs系统PC,未对MacOS进行测试。但服务端由java编写,自行下载macOS版本的jdk17,运行服务端,理论上不会有问题
也可以将java源代码重新编译,甚至移植到安卓App上。
本文以windows系统为例,使用安信可家esp32cam模块 和安信可家USB转TTL CP2012模块。
烧录esp32cam本文以ardunio 框架开发,你可以选择 ardunio ide 编译和烧录
或者platformio(基于vs code/clion)新建项目选择 以ardunio framework新建。
ardunio ide 准备esp32cam环境 1.追加附加板地址打开菜单 -> 文件 -> 首选项
在附加开发板管理器网址中追加一行
https://dl.espressif.com/dl/package_esp32_index.json2.安装esp32环境
在 工具 -> 开发板 -> 开发板管理器里 搜索 esp32 点击进行安装。
此处可能需要把dns修改为腾讯或者阿里公共dns,才容易成功。
3.新建项目选择esp32cam
platformio 准备esp32cam环境新建项目找到 AI Thinker ESP32-CAM,则选择了开发板。框架选择 ardunio。若没有初始化esp32环境,会自动下载,同样建议修改dns。
新建后生成的ini文件如下(串口相关设置需要手动添加)
[env:esp32cam] platform = espressif32 board = esp32cam framework = arduino upload_speed= 115200 upload_port = COM3 monitor_speed= 115200 monitor_port = COM3代码
存在多个文件和服务端相关代码,在gitcode上已经开源。点此跳转
引导方面本文更加详细。可先参考本文。
esp32cam代码共两个文件。也可以合成一个。
文件 ai_thinker_esp32_cam_meta.h表示esp32cam相关GPIO引脚定义
#ifndef AI_THINKER_32_CAM_META #define AI_THINKER_32_CAM_META #define PWDN_GPIO_NUM 32 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 0 #define SIOD_GPIO_NUM 26 #define SIOC_GPIO_NUM 27 #define Y9_GPIO_NUM 35 #define Y8_GPIO_NUM 34 #define Y7_GPIO_NUM 39 #define Y6_GPIO_NUM 36 #define Y5_GPIO_NUM 21 #define Y4_GPIO_NUM 19 #define Y3_GPIO_NUM 18 #define Y2_GPIO_NUM 5 #define VSYNC_GPIO_NUM 25 #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 #endif文件main.cpp
在ardunio ide里无需考虑该文件名,而只是把该文件内容复制到你的.ino 文件中。
请按照具体情况修改wifi的ssid和密码,一般可以使用你pc运行服务端,可以将PC的ip填写到以下源文件host变量的值中。
#include #include#include "esp_camera.h" #define CAMERA_MODEL_AI_THINKER #include "ai_thinker_esp32_cam_meta.h" char* ssid = "test0"; const char* passwd = "12345687"; const char* host = "192.168.137.1"; // 服务端地址,可以用你的PC运行服务端则是PC的ip。 WiFiClient streamSender; void connectWifi(const char* ssid, const char* passphrase) { WiFi.mode(WIFI_STA); WiFi.begin(ssid, passphrase); Serial.println("connecting to router... "); //等待wifi连接成功 while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); } Serial.print("nWiFi connected, local IP address:"); Serial.println(WiFi.localIP()); } void setup() { Serial.begin(115200); Serial.setDebugOutput(true); while (!Serial) { } camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; config.pin_sscb_sda = SIOD_GPIO_NUM; config.pin_sscb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.pixel_format = PIXFORMAT_JPEG; // if PSRAM IC present, init with UXGA resolution and higher JPEG quality // for larger pre-allocated frame buffer. if (psramFound()) { config.frame_size = FRAMESIZE_UXGA; config.jpeg_quality = 10; config.fb_count = 2; } else { config.frame_size = FRAMESIZE_SVGA; config.jpeg_quality = 12; config.fb_count = 1; } // camera init esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x", err); return; } Serial.println("get sensor "); sensor_t* s = esp_camera_sensor_get(); // drop down frame size for higher initial frame rate s->set_framesize(s, FRAMESIZE_VGA); connectWifi(ssid, passwd); Serial.println("connect stream channel"); if (!streamSender.connect(host, 8004)) { Serial.println("connect stream channel failed"); } streamSender.setNoDelay(true); } void loop() { camera_fb_t* fb = NULL; size_t len = 0; Serial.println("do loop"); uint8_t end[5] = {'j', 'p', 'e', 'g', 'n'}; while (true) { fb = esp_camera_fb_get(); if (!fb) { Serial.println("Camera capture failed"); return; } len = fb->len; streamSender.write(fb->buf, len); streamSender.write(end, 5); streamSender.flush(); esp_camera_fb_return(fb); } }
查看PC的ip的办法
按win + R 输入cmd 按enter打开控制台
输入 ipconfig 回车,找到有ipv4地址的那一行。如果有多个适配器,大概率需要自己确定和无线路由器所在同一网络的ip。
一般wifi连接则是网卡名带 无线适配器,而路由器网线直连则自己抉择。
烧录 使用USB转TTL模块时接线| USB转TTL模块引脚 | esp32cam引脚 |
|---|---|
| 5V | 5V |
| GND | GND |
| TXD | U0R |
| RXD | U0T |
当上载控制台出现连接某某com口,请尽快连接IO0和GND,再按RST。
使用烧录底座将esp32cam安上底座,则无需考虑针脚连接具体如何。
串口监控鄙人不知烧录底座是否可以串口监控,使用USB转TTL模块时,在烧录完成后,断开IO0与GND的连接,再按RST重启esp32cam则可以查看串口打印,但此时没有运行服务端SimpleVideoServer。
下载和运行服务端根据自己需要选择以下任意方式运行服务端
-
下载 windows服务端发行版
解压之后,进入对应目录点击run.bat文件启动服务器。
-
下载linux服务端发行版
需要安装 p7zip或者7zip。否则会提示7z找不到。也可以自行解压后上传。注意jre的bin目录的执行权限
运行
7z x SimpleVideoSever_linux.7z cd linux_release/ sh run.sh
-
发行版内部仅仅是一些java17 版本的class文件和jre以及启动脚本,你可以使用任意其它的jre17运行这些class文件。并非需要发行版。
-
也可以下载源码,自行编译使用其它版本的jre或者使用可以开发java的ide运行。
一般无需修改,但提供改法。后续此处可能会有变化,可以跟随该开源项目SimpleVideoSever具体描述。
light-video.properties
里面含有三个配置
http.port=8003 http.clients.limit=10 stream.port=8004
http.port 为http的端口。
查看视频访问 http://ip:该端口/video。改成80则无需在url中声明端口。
充当服务端的pc访问 http://127.0.0.1:8003/video 是比较方便的一种办法。
http.clients.limit http客户端限制数,可以多个客户端同时查看同一视频,类似直播。增加多客户端增加服务端负担。
stream.port esp32cam像服务端发送照片的端口,在本项目中使用该默认端口,如果需要修改,一并修改esp32cam代码中连接的端口。一般无需修改。
查看视频待服务端正常启动后
重启esp32cam
注意冒号为英文的冒号 :
如果使用本机运行服务端进入该地址即可 http://127.0.0.1:8003/video
也可以使用其它设备查看,比如手机,输入PC的
http://PC的ip:8003/video
使用远程服务器如云服务器同学则无需额外指导。注意本服务端毫不安全,没有任何安全机制,在公网使用不宜长久暴露服务端口。



