esp32cam推流至服务器+网站显示

概要

记录一次esp32cam 推流到公网的学习,本来是想找rstp跟rmtp推流能力不足放弃了,最后采用了图传的方式上传。

这里记录一下自己学习的几种方式,以免忘记

1.esp32cam+nodejs+python(tcp)

esp32 cam 的代码:
这里是将esp32拍摄的图片流一张一张的上传到tcp服务器中。

/*
网络调试助手
https://soft.3dmgame.com/down/213757.html
*/
#include <Arduino.h>
#include <WiFi.h>
#include "esp_camera.h"
#include <vector>
 
const char *ssid = "*******";//wifi名称
const char *password = "--------------";//wifi密码
const IPAddress serverIP(192,168,0,2); //欲访问的地址
uint16_t serverPort = 8080;         //服务器端口号
 
#define maxcache 1430
 
WiFiClient client; //声明一个客户端对象,用于与服务器进行连接
 
//CAMERA_MODEL_AI_THINKER类型摄像头的引脚定义
#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
 
static camera_config_t camera_config = {
   
    .pin_pwdn = PWDN_GPIO_NUM,
    .pin_reset = RESET_GPIO_NUM,
    .pin_xclk = XCLK_GPIO_NUM,
    .pin_sscb_sda = SIOD_GPIO_NUM,
    .pin_sscb_scl = SIOC_GPIO_NUM,
    
    .pin_d7 = Y9_GPIO_NUM,
    .pin_d6 = Y8_GPIO_NUM,
    .pin_d5 = Y7_GPIO_NUM,
    .pin_d4 = Y6_GPIO_NUM,
    .pin_d3 = Y5_GPIO_NUM,
    .pin_d2 = Y4_GPIO_NUM,
    .pin_d1 = Y3_GPIO_NUM,
    .pin_d0 = Y2_GPIO_NUM,
    .pin_vsync = VSYNC_GPIO_NUM,
    .pin_href = HREF_GPIO_NUM,
    .pin_pclk = PCLK_GPIO_NUM,
    
    .xclk_freq_hz = 20000000,
    .ledc_timer = LEDC_TIMER_0,
    .ledc_channel = LEDC_CHANNEL_0,
    
    .pixel_format = PIXFORMAT_JPEG,
    .frame_size = FRAMESIZE_VGA,
    .jpeg_quality = 12,
    .fb_count = 1,
};
void wifi_init()
{
   
    WiFi.mode(WIFI_STA);
    WiFi.setSleep(false); //关闭STA模式下wifi休眠,提高响应速度
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
   
        delay(500);
        Serial.print(".");
    }
    Serial.println("WiFi Connected!");
    Serial.print("IP Address:");
    Serial.println(WiFi.localIP());
}
esp_err_t camera_init() {
   
    //initialize the camera
    esp_err_t err = esp_camera_init(&camera_config);
    if (err != ESP_OK) {
   
        Serial.println("Camera Init Failed");
        return err;
    }
    sensor_t * s = esp_camera_sensor_get();
    //initial sensors are flipped vertically and colors are a bit saturated
    if (s->id.PID == OV2640_PID) {
   
    //        s->set_vflip(s, 1);//flip it back
    //        s->set_brightness(s, 1);//up the blightness just a bit
    //        s->set_contrast(s, 1);
    }
    Serial.println("Camera Init OK!");
    return ESP_OK;
}
 
void setup()
{
   
    Serial.begin(115200);
    wifi_init();
    camera_init();
}
 
void loop()
{
   
    Serial.println(
### ESP32-CAM 视频教程及配置方法 #### 开发环境准备 为了使ESP32-CAM能够顺利工作于视频项目中,需先准备好开发环境。对于更高效的编程体验,荐采用VSCode配合PlatformIO作为IDE[^2]。 - 安装Visual Studio Code编辑器以及PlatformIO插件。 - 创建新工程时指定框架为`Espressif 32`,并设置目标设备型号为`ESP32 WROVER MODULE`或其他兼容选项[^3]。 #### 库文件安装 确保已正确安装必要的库来支持图像处理与传输功能: ```cpp #include "WiFi.h" #include "esp_camera.h" ``` 还需通过Library Manager获取额外依赖项如`ArduinoJson`用于解析HTTP请求参数等操作。 #### Wi-Fi连接设定 编写初始化Wi-Fi模块的相关代码片段如下所示: ```cpp const char* ssid = "YOUR_SSID"; const char* password = "YOUR_PASSWORD"; void setup_wifi() { delay(10); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } randomSeed(micros()); Serial.println(""); Serial.println("WiFi connected"); } ``` 此段程序负责建立至无线路由器的安全链接以便后续数据交换过程得以正常开展[^1]。 #### 摄像头硬件初始化 针对特定款式的摄像头模组完成相应的驱动加载动作: ```cpp #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 camera_config_t config; void cameraSetup(){ 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(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; } } ``` 上述脚本定义了相机的各项物理接口映射关系,并依据是否存在外部PSRAM存储芯片调整分辨率大小以优化性能表现。 #### HTTP服务器创建 最后一步则是构建简易Web服务端口监听来自客户端浏览器发出的GET指令从而返回实时拍摄画面帧序列: ```cpp AsyncWebServer server(80); String getContentType(String filename){ if(filename.endsWith(".html")) return "text/html"; else if(filename.endsWith(".css")) return "text/css"; else if(filename.endsWith(".js")) return "application/javascript"; else if(filename.endsWith(".ico")) return "image/x-icon"; return "text/plain"; } void handleRoot(AsyncWebServerRequest *request){ request->send_P(200, "text/html", index_html, processor); } void startStream(){ camera_fb_t * fb = NULL; bool streamed = false; String contentType = "multipart/x-mixed-replace;boundary=" + boundaryStr; AsyncEventSourceClient *client = request->client(); while(client && !streamed){ fb = esp_camera_fb_get(); if(!fb || client==nullptr){ break; } streamed = true; size_t out_len, out_idx=0; uint8_t *out_buf; bool jpeg_converted=false; if(fb->format != PIXFORMAT_JPEG){ bool res = frame2jpg(fb, 80, &out_buf, &out_len); jpeg_converted=true; }else{ out_buf = fb->buf; out_len = fb->len; } streamClient.println("--" + boundaryStr); streamClient.println("Content-Type: image/jpeg"); streamClient.println("Content-Length:" + String(out_len)); streamClient.println(); streamClient.write(out_buf,out_len); streamClient.println(); esp_camera_fb_return(fb); if(jpeg_converted){ free(out_buf); } } } void setup(){ ... pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); setup_wifi(); cameraSetup(); server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){handleRoot(request);}); server.on("/capture", HTTP_GET, [](AsyncWebServerRequest *request){startStream();}); server.begin(); } ``` 这段逻辑实现了当接收到根路径访问请求时发送静态网页界面;而对于`/capture`地址则持续抓取最新一帧影像并通过MJPEG格式编码后分包送出去形成连续播放效果。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值