Extra 5% OFF Use Code: OL05
Free Shipping over ₹999

Streaming Video from ESP32-CAM to a Browser

In this guide, we’ll walk through a simple but effective setup to stream live video from an ESP32-CAM module to a web browser. Using the ESP32’s built-in WiFi capabilities, this setup can either connect to an existing network or create its own WiFi hotspot, allowing you to access the video stream by typing in the IP address on any browser within range.


Prerequisites

Before diving into the code, ensure you have the following:

  • ESP32-CAM module (e.g., AI-THINKER model)
  • USB to Serial Adapter (for uploading code) or ESP32 Programming Adapter
  • Jumper wires
  • Arduino IDE with ESP32 Board Manager installed

Code

#include "esp_camera.h"
#include <WiFi.h>
#include <WebServer.h>

#define CAMERA_MODEL_AI_THINKER // Adjust to your camera model
#include "camera_pins.h"

const char* ssid = "ESP32-CAM-AP";
const char* password = "12345678";

WebServer server(80);

void handle_jpg_stream() {
  camera_fb_t * fb = NULL;
  esp_err_t res = ESP_OK;
  size_t _jpg_buf_len = 0;
  uint8_t * _jpg_buf = NULL;
  char part_buf[64];
  
  String response = 
    "HTTP/1.1 200 OK\r\n" 
    "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
  
  server.client().write(response.c_str(), response.length());

  while(true) {
    fb = esp_camera_fb_get();
    if (!fb) {
      Serial.println("Camera capture failed");
      break;
    }
    if(fb->format != PIXFORMAT_JPEG){
      bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
      esp_camera_fb_return(fb);
      if(!jpeg_converted){
        Serial.println("JPEG compression failed");
        break;
      }
    } else {
      _jpg_buf_len = fb->len;
      _jpg_buf = fb->buf;
    }

    size_t hlen = snprintf(part_buf, 64, "--frame\r\nContent-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n", _jpg_buf_len);
    server.client().write(part_buf, hlen);
    server.client().write((const char *)_jpg_buf, _jpg_buf_len);
    server.client().write("\r\n", 2);

    if(fb->format != PIXFORMAT_JPEG){
      free(_jpg_buf);
    }
    esp_camera_fb_return(fb);

    if(!server.client().connected()){
      break;
    }
  }
}

void startCameraServer1() {
  server.on("/", HTTP_GET, [](){
    server.send(200, "text/plain", "ESP32-CAM Video Streaming");
  });

  server.on("/stream", HTTP_GET, handle_jpg_stream);

  server.begin();
}

void setup() {
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  Serial.println();

  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(psramFound()){
    // config.frame_size = FRAMESIZE_UXGA;
    config.frame_size = FRAMESIZE_VGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    // config.frame_size = FRAMESIZE_SVGA;
    config.frame_size = FRAMESIZE_VGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }

  // WiFi.begin(ssid, password);

  // while (WiFi.status() != WL_CONNECTED) {
  //   delay(500);
  //   Serial.print(".");
  // }
  // Serial.println("");
  // Serial.println("WiFi connected");

  // startCameraServer1();

  // Serial.print("Camera Ready! Use 'http://");
  // Serial.print(WiFi.localIP());
  // Serial.println("/stream' to connect");

  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(IP);

  startCameraServer1();

  Serial.print("Camera Ready! Use 'http://");
  Serial.print(IP);
  Serial.println("/stream' to connect");

}

void loop() {
  server.handleClient();
}

Code Explaination

Here’s an in-depth breakdown of how the code works to configure the ESP32-CAM and create an access point for streaming.

Step 1: Import Libraries and Set Camera Model

#include "esp_camera.h"
#include <WiFi.h>
#include <WebServer.h>

#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"


The libraries esp_camera.h, WiFi.h, and WebServer.h allow for camera control, WiFi connectivity, and a simple web server setup. Define the correct model for your ESP32-CAM to ensure it initializes with the right pin mappings.

Step 2: Configure WiFi Credentials

const char* ssid = "ESP32-CAM-AP";
const char* password = "12345678";

The code sets up a simple Access Point (AP) mode by using a basic SSID and password. This configuration lets the ESP32-CAM create its own WiFi network, ideal if you want to access the stream without relying on an existing network.

Step 3: Define the Video Streaming Handler

void handle_jpg_stream() {
  camera_fb_t * fb = NULL;
  esp_err_t res = ESP_OK;
  size_t _jpg_buf_len = 0;
  uint8_t * _jpg_buf = NULL;
  char part_buf[64];
  
  String response = 
    "HTTP/1.1 200 OK\r\n" 
    "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
  
  server.client().write(response.c_str(), response.length());

This function, handle_jpg_stream(), captures frames from the ESP32-CAM and streams them in JPEG format. The HTTP response uses multipart/x-mixed-replace, which allows continuous streaming by updating the image data for each frame.

The function:

  • Captures a frame from the camera buffer.
  • Converts it to JPEG format (if not already).
  • Writes the frame to the client with the appropriate Content-Type.

Step 4: Setting Up the Camera Server

void startCameraServer1() {
  server.on("/", HTTP_GET, [](){
    server.send(200, "text/plain", "ESP32-CAM Video Streaming");
  });

  server.on("/stream", HTTP_GET, handle_jpg_stream);

  server.begin();
}

This function sets up the HTTP endpoints:

  • / displays a welcome message.
  • /stream triggers handle_jpg_stream() to begin video streaming.

Step 5: Initialize Camera Settings

camera_config_t config;
// Assign GPIO pins for your specific camera model
// (omitted here for brevity)

The camera settings configure:

  • The frame size (resolution).
  • JPEG quality based on PSRAM availability.
  • The number of frame buffers for smoother performance.

Step 6: Connect WiFi and Start the Camera Server

WiFi.softAP(ssid, password);

IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);

startCameraServer1();

Serial.print("Camera Ready! Use 'http://");
Serial.print(IP);
Serial.println("/stream' to connect");

In AP mode, the ESP32-CAM generates a unique IP address, which is printed in the Serial Monitor. This IP can then be used in any browser on a device connected to the ESP32-CAM network to access the video stream.

Testing the Setup

  1. Upload the code to your ESP32-CAM.
  2. Open the Serial Monitor to see the assigned IP address (something like 192.168.4.1).
  3. Connect your computer or phone to the ESP32-CAM AP network with the specified SSID and password.
  4. Open a browser and enter http://[IP address]/stream (replace [IP address] with the IP shown in the Serial Monitor).

    Leave a Reply

    Your email address will not be published.

    Need Help?