Skip to Content

Transmitir vídeo con ESP32-WROVER CAM

Transmitir vídeo con ESP32-WROVER CAM

En este tutorial te mostraré cómo transmitir vídeo desde una placa Freenove ESP32-WROVER CAM a través de tu red Wi-Fi local hacia tu navegador web. Esto significa que puedes construir fácilmente tu propio sistema de cámara de vigilancia inalámbrica que podrás monitorear desde tu ordenador.

Si no has usado esta placa antes, te sugiero que leas el Programming the ESP32-WROVER CAM tutorial primero, que te ayudará a empezar con la placa.

Partes necesarias

Necesitarás una placa Freenove ESP32-WROVER CAM para seguir este tutorial. Normalmente la placa viene con extras como una tarjeta SD, un lector de tarjetas SD y un cable USB-C, pero en caso de que falten, también los he enlazado a continuación.

ESP32-WROVER CAM

Cable USB C

Lector de tarjetas SD

Tarjeta MicroSD 16GB

Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.

Transmisión de vídeo

En este proyecto vamos a implementar un servidor de transmisión de vídeo que se ejecuta en el ESP32-WROVER. La cámara del ESP32-WROVER captura imágenes y las envía por Wi-Fi. El router Wi-Fi transporta estas imágenes al navegador web de tu PC, que las muestra como una transmisión de vídeo. La imagen a continuación ilustra la arquitectura del sistema:

Streaming Video via local Wi-Fi
Transmisión de vídeo vía Wi-Fi local

Ten en cuenta que la transmisión de vídeo no está cifrada ni es segura, pero solo será visible en una URL dentro de tu red Wi-Fi local, por ejemplo 192.168.2.40/stream. Solo alguien con acceso a tu red Wi-Fi podrá ver la transmisión de vídeo.

Código simple para un servidor de transmisión de vídeo

El núcleo para el ESP32-WROVER CAM incluye código de ejemplo para un CameraWebServer que transmite vídeos; consulta el Programming the ESP32-WROVER CAM tutorial para más detalles. Pero ese código es complejo y la interfaz del servidor web tiene muchas opciones.

Eso está bien para experimentar, pero si solo quieres la transmisión de vídeo simple (por ejemplo, para Home Assistant) y un código sencillo que puedas integrar con otras funciones, como una transmisión de vídeo activada por movimiento, entonces el siguiente código es más fácil de usar.

La simplificación se debe en gran parte a la esp32cam biblioteca, que puedes instalar a través del Library Manager en el Arduino IDE. Solo busca «esp32cam» y presiona INSTALL. La imagen a continuación muestra la instalación completada:

esp32cam library installed via Library Manager
Biblioteca esp32cam instalada vía Library Manager

A continuación encontrarás el código completo para el servidor de transmisión de vídeo, que usa la esp32cam biblioteca. Échale un vistazo rápido primero y luego analizaremos sus detalles:

#include "WebServer.h"
#include "WiFi.h"
#include "esp32cam.h"

const char* WIFI_SSID = "SSID";
const char* WIFI_PASS = "PASSWORD";
const char* URL = "/stream";
const auto RESOLUTION = esp32cam::Resolution::find(800, 600);

WebServer server(80);

void handleStream() {
  static char head[128];
  WiFiClient client = server.client();

  server.sendContent("HTTP/1.1 200 OK\r\n"
                     "Content-Type: multipart/x-mixed-replace; "
                     "boundary=frame\r\n\r\n");

  while (client.connected()) {
    auto frame = esp32cam::capture();
    if (frame) {
      sprintf(head,
              "--frame\r\n"
              "Content-Type: image/jpeg\r\n"
              "Content-Length: %ul\r\n\r\n",
              frame->size());
      client.write(head, strlen(head));
      frame->writeTo(client);
      client.write("\r\n");
    }
  }
}

void initCamera() {
  using namespace esp32cam;
  Config cfg;
  cfg.setPins(pins::FreeNove);
  cfg.setResolution(RESOLUTION);
  cfg.setBufferCount(2);
  cfg.setJpeg(80);
  Camera.begin(cfg);
}

void initWifi() {
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
  }
  Serial.printf("Stream at: http://%s%s\n",
                WiFi.localIP().toString().c_str(), URL);
}

void initServer() {
  server.on(URL, handleStream);
  server.begin();
}

void setup() {
  Serial.begin(115200);
  initWifi();
  initCamera();
  initServer();
}

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

Bibliotecas

El sketch comienza incluyendo las bibliotecas necesarias:

#include "WebServer.h"
#include "WiFi.h"
#include "esp32cam.h"

Estas bibliotecas habilitan la funcionalidad del servidor HTTP (WebServer.h), la conectividad Wi-Fi (WiFi.h) y el control de la cámara usando la biblioteca esp32cam.

Constantes

A continuación, definimos constantes para la configuración de Wi-Fi y la cámara:

const char* WIFI_SSID = "SSID";
const char* WIFI_PASS = "PASSWORD";
const char* URL = "/stream";
const auto RESOLUTION = esp32cam::Resolution::find(800, 600);

Las variables WIFI_SSID y WIFI_PASS almacenan las credenciales de la red Wi-Fi. Deberás reemplazar SSID y PASSWORD con los datos reales de acceso a tu red Wi-Fi.

La URL es la ruta en la que se servirá la transmisión de vídeo. Puedes cambiarla por lo que quieras. Por ejemplo, «/video» o «/frontdoor», solo asegúrate de mantener la barra (‘/’) al principio.

La RESOLUTION establece la resolución deseada para la cámara. A continuación tienes una lista de los valores posibles para la resolución de la cámara, aunque dependiendo de la cámara no todos pueden funcionar:

  • 96×96
  • 160×120
  • 128×128
  • 176×144
  • 240×176
  • 240×240
  • 320×240
  • 320×320
  • 400×296
  • 480×320
  • 640×480
  • 800×600
  • 1024×768
  • 1280×720
  • 1280×1024
  • 1600×1200

Objetos

La siguiente línea crea el objeto servidor HTTP que escucha en el puerto 80. Ese es nuestro servidor web que proporciona la transmisión de vídeo.

WebServer server(80);

handleStream

La función handleStream() maneja la transmisión de vídeo cada vez que un cliente accede a la ruta /stream:

void handleStream() {
  static char head[128];
  WiFiClient client = server.client();

Esta línea obtiene el cliente actual conectado al servidor. Luego se prepara la respuesta:

server.sendContent("HTTP/1.1 200 OK\r\n"
                   "Content-Type: multipart/x-mixed-replace; "
                   "boundary=frame\r\n\r\n");

Esta cabecera indica al navegador que recibirá una transmisión MJPEG multipartida, donde cada parte está separada por un límite llamado frame.

Dentro del bucle, la función primero captura un fotograma de la cámara:

  while (client.connected()) {
    auto frame = esp32cam::capture();

Si se captura un fotograma con éxito, se construye una cabecera que describe la imagen JPEG y se envía al cliente:

    if (frame) {
      sprintf(head,
              "--frame\r\n"
              "Content-Type: image/jpeg\r\n"
              "Content-Length: %ul\r\n\r\n",
              frame>size());
      client.write(head, strlen(head));
      frame->writeTo(client);
      client.write("\r\n");
    }

initCamera

La función initCamera() configura y arranca la cámara ESP32-WROVER:

void initCamera() {
  using namespace esp32cam;
  Config cfg;
  cfg.setPins(pins::FreeNove);
  cfg.setResolution(RESOLUTION);
  cfg.setBufferCount(2);
  cfg.setJpeg(80);
  Camera.begin(cfg);
}

Primero, se crea un objeto Config. La función setPins configura los pines de la cámara según la placa FreeNove. La ESP32-WROVER CAM es de FreeNove y eso es lo que debes configurar aquí. Puedes encontrar el pin configurations of other supported boards here.

setResolution define la resolución a usar, mientras que setBufferCount determina cuántos buffers de imagen se usan internamente, lo que puede ayudar a obtener velocidades de fotogramas más rápidas.

La función setJpeg establece la calidad de compresión JPEG entre 0 y 100. 80 es un buen equilibrio entre calidad y tamaño. 90 ofrece mejor calidad pero una reducción menor en el tamaño de la imagen. Para vídeo más rápido puedes reducir la resolución y la compresión JPEG, pero obviamente obtendrás imágenes más pequeñas con menor calidad.

Finalmente, Camera.begin(cfg) inicializa la cámara con estas configuraciones.

initWifi

La función initWifi() conecta la placa ESP32-WROVER a la red Wi-Fi especificada:

void initWifi() {
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
  }
  Serial.printf("Stream at: http://%s%s\n",
                WiFi.localIP().toString().c_str(), URL);
}

WiFi.persistent(false) desactiva la escritura de las credenciales en la memoria flash, lo que acelera la reconexión. El dispositivo se configura en modo estación (WIFI_STA), y trata de conectarse al Wi-Fi usando las credenciales dadas.

Una vez conectado, la dirección IP y la ruta de la transmisión se imprimen en el monitor serial. Necesitarás copiar y pegar esta URL impresa en la barra de direcciones de tu navegador para ver la transmisión de vídeo. La URL real dependerá de tu placa ESP32-WROVER pero puedes cambiar el sufijo «stream». En mi placa, veo la siguiente URL en el Monitor Serial:

Streaming URL printed to Serial Monitor
URL de transmisión impresa en el Monitor Serial

Por lo tanto, copio «http://192.168.2.40/stream» en la barra de direcciones de mi navegador Chrome para acceder al vídeo.

initServer

La función initServer() vincula la ruta de transmisión al manejador y arranca el servidor:

void initServer() {
  server.on(URL, handleStream);
  server.begin();
}

Esto asigna cualquier petición a /stream a la función handleStream(), y luego inicia el servidor.

setup

La función setup() inicia la comunicación serial, conecta al Wi-Fi, inicializa la cámara y configura el servidor web:

void setup() {
  Serial.begin(115200);
  initWifi();
  initCamera();
  initServer();
}

loop

Finalmente, la función loop() maneja continuamente las solicitudes HTTP entrantes:

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

Esta línea permite que el ESP32-WROVER responda a las solicitudes de los clientes invocando cualquier manejador registrado como handleStream().

En conjunto, este código crea un servidor de transmisión MJPEG simple pero efectivo que puede ser accedido desde cualquier navegador web dentro de la misma red, proporcionando una transmisión en vivo desde la cámara ESP32-WROVER CAM.

Para descargar ese código a tu ESP32-WROVER CAM, selecciona la placa ESP32 Wrover Module y presiona el botón de descarga.

Select ESP32 Wrover Module as board
Selecciona ESP32 Wrover Module como placa

Si necesitas ayuda con esto, echa un vistazo a nuestro Programming the ESP32-WROVER CAM tutorial.

Conclusiones

En este tutorial aprendiste cómo transmitir vídeo desde un ESP32-WROVER CAM a través de tu red Wi-Fi local hacia tu navegador web.

El ESP32-WROVER CAM funciona muy bien pero es una placa bastante grande. Si necesitas una placa con un tamaño más reducido, te sugiero la XIAO-ESP32-S3-Sense, que es diminuta – un cubo de unos 20 mm.

También para detección de objetos echa un vistazo al Object Detection with ESP32-CAM and YOLO tutorial. Está escrito para el ESP32-CAM pero solo requiere un cambio mínimo (cfg.setPins(pins::FreeNove)) para funcionar con el ESP32-WROVER CAM.

Si tienes alguna pregunta, no dudes en dejarlas en la sección de comentarios.

¡Feliz bricolaje ; )