Skip to Content

Stream Video con XIAO-ESP32-S3-Sense

Stream Video con XIAO-ESP32-S3-Sense

In questo tutorial imparerai come trasmettere video da una Seeed Studio XIAO-ESP32-S3 Sense board tramite la tua rete Wi-Fi locale al browser web. Questo ti permette di costruire un sistema di videosorveglianza wireless che puoi monitorare dal tuo computer.

Se non hai mai usato la XIAO-ESP32-S3 Sense, dai un’occhiata prima al Getting started with XIAO-ESP32-S3-Sense tutorial introduttivo, che ti aiuta a iniziare con la scheda.

Componenti necessari

Ovviamente, ti servirà una scheda XIAO-ESP32-S3 Sense di Seeed Studio per provare gli esempi di codice. Nota che la scheda può scaldarsi molto, ad esempio durante lo streaming video ad alta frequenza di fotogrammi. Ti consiglio di applicare un piccolo Heatsink sul retro della scheda (vedi il componente elencato qui sotto).

Seeed Studio XIAO ESP32 S3 Sense

Cavo USB C

Piccolo dissipatore 9×9 mm

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.

Streaming video

In questo progetto implementeremo un server di streaming video che gira sulla XIAO-ESP32-S3 Sense. La fotocamera della XIAO-ESP32-S3 Sense cattura immagini e le trasmette via Wi-Fi. Il router Wi-Fi trasporta queste immagini al browser web sul tuo PC, che le mostra come un flusso video. L’immagine sotto illustra l’architettura del sistema:

Streaming Video via local Wi-Fi
Streaming video tramite Wi-Fi locale

Nota che il flusso video non è criptato né sicuro, ma sarà visibile solo tramite un URL all’interno della tua rete Wi-Fi locale, ad esempio 192.168.2.40/stream. Solo chi ha accesso alla tua rete Wi-Fi potrà vedere il flusso video.

Codice per un server di streaming video con XIAO-ESP32-S3-Sense

Il Getting Started Wiki by Seeed Studio per XIAO-ESP32-S3-Sense fornisce molte informazioni sulla scheda e include anche un esempio di codice per un server di streaming video. Tuttavia, quel codice è più complesso rispetto a quello qui sotto.

La semplificazione è dovuta in gran parte alla libreria esp32cam, che puoi installare tramite il Library Manager nell’IDE Arduino. Basta cercare “esp32cam” e premere INSTALLA. L’immagine sotto mostra l’installazione completata:

esp32cam library installed via Library Manager
Libreria esp32cam installata tramite Library Manager

Qui sotto trovi il codice completo per il server di streaming video, che usa la libreria esp32cam. Dai un’occhiata veloce e poi ne discuteremo i dettagli:

#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);
const int FRAMERATE = 10;

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");
      delay(1000 / FRAMERATE);
    }
  }
}

void initCamera() {
  using namespace esp32cam;
  Config cfg;
  cfg.setPins(pins::XiaoSense);
  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();
}

Librerie

Lo sketch inizia includendo le librerie necessarie:

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

Queste librerie abilitano la funzionalità di server HTTP (WebServer.h), la connettività Wi-Fi (WiFi.h) e il controllo della fotocamera tramite la libreria esp32cam.

Costanti

Successivamente definiamo le costanti per le impostazioni Wi-Fi e della fotocamera:

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

Le variabili WIFI_SSID e WIFI_PASS memorizzano le credenziali della rete Wi-Fi. Dovrai sostituire SSID e PASSWORD con i dati di accesso reali della tua rete.

La variabile URL è il percorso su cui verrà servito il flusso video. Puoi cambiarlo come preferisci. Ad esempio, “/video” o “/frontdoor”, assicurandoti solo di mantenere la barra (‘/’) all’inizio.

La variabile RESOLUTION imposta la risoluzione desiderata per la fotocamera. Qui sotto trovi una lista dei valori possibili per la risoluzione, anche se a seconda della fotocamera non tutte potrebbero funzionare:

  • 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

La variabile FRAMERATE definisce quanti fotogrammi al secondo verranno inviati al client. Questo ti permette di rallentare il flusso video ed evitare il surriscaldamento della scheda. Se imposti un framerate troppo alto, verrà automaticamente limitato a ciò che l’ESP32 può gestire per quella risoluzione.

Oggetti

La riga seguente crea l’oggetto server HTTP che ascolta sulla porta 80. Questo è il nostro server web che fornisce il flusso video.

WebServer server(80);

handleStream

La funzione handleStream() gestisce il flusso video ogni volta che un client accede al percorso /stream:

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

Questa riga ottiene il client attualmente connesso al server. Poi si prepara la risposta:

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

Questo header dice al browser che riceverà un flusso MJPEG multipart, dove ogni parte è separata da un confine chiamato frame.

Dentro il ciclo, la funzione cattura prima un fotogramma dalla fotocamera:

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

Se il fotogramma viene catturato con successo, si costruisce un header che descrive l’immagine JPEG e lo si invia al client:

    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 funzione initCamera() configura e avvia la fotocamera:

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

Prima viene creato un oggetto Config. La funzione setPins configura i pin della fotocamera basandosi sulla scheda XIAO-ESP32-S3 Sense. Vedi il pin configurations di altre schede supportate.

setResolution imposta la risoluzione da usare, mentre setBufferCount determina quanti buffer di immagine vengono usati internamente, il che può aiutare ad aumentare il framerate.

La funzione setJpeg imposta la qualità di compressione JPEG tra 0 e 100. 80 è un buon compromesso tra qualità e dimensione. 90 offre qualità migliore ma una riduzione minore della dimensione dell’immagine. Per uno streaming più veloce puoi ridurre la risoluzione e la compressione JPEG, ma ovviamente otterrai immagini più piccole e di qualità inferiore.

Infine, Camera.begin(cfg) inizializza la fotocamera con queste impostazioni.

initWifi

La funzione initWifi() connette la scheda XIAO-ESP32-S3 Sense alla rete Wi-Fi specificata:

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) disabilita la scrittura delle credenziali sulla flash, velocizzando la riconnessione. Il dispositivo è impostato in modalità station (WIFI_STA), e tenta di connettersi al Wi-Fi usando le credenziali fornite.

Una volta connesso, l’indirizzo IP e il percorso dello stream vengono stampati sul monitor seriale. Dovrai copiare e incollare questo URL nel browser per vedere il flusso video. L’URL effettivo dipenderà dalla tua scheda, ma puoi cambiare il suffisso “stream”. Per la mia scheda, vedo il seguente URL sul monitor seriale:

Streaming URL printed to Serial Monitor
URL di streaming stampato sul monitor seriale

Quindi, copio “http://192.168.2.40/stream” nella barra degli indirizzi del mio browser Chrome per accedere al video.

initServer

La funzione initServer() collega il percorso di streaming all’handler e avvia il server:

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

Questo mappa ogni richiesta a /stream alla funzione handleStream(), quindi avvia il server.

setup

La funzione setup() avvia la comunicazione seriale, si connette al Wi-Fi, inizializza la fotocamera e configura il server web:

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

loop

Infine, la funzione loop() gestisce continuamente le richieste HTTP in arrivo:

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

Questa riga permette alla XIAO-ESP32-S3 Sense di rispondere alle richieste dei client invocando gli handler registrati come handleStream().

Nel complesso, questo codice crea un server di streaming MJPEG semplice ma efficace, accessibile da qualsiasi browser web nella stessa rete, fornendo un feed video live dalla XIAO-ESP32-S3 Sense.

Per caricare questo codice sulla tua XIAO-ESP32-S3 Sense, seleziona la scheda XIAO_ESP32S3 e premi il pulsante di download.

Select XIAO_ESP32S3 as board
Seleziona XIAO_ESP32S3 come scheda

Se hai bisogno di ulteriore aiuto, dai un’occhiata al Getting started with XIAO-ESP32-S3-Sense tutorial.

Conclusioni

In questo tutorial hai imparato come trasmettere video da una XIAO-ESP32-S3 Sense tramite la tua rete Wi-Fi locale al browser web.

Se vuoi rilevare oggetti nel flusso video, dai un’occhiata al Object Detection with ESP32-CAM and YOLO tutorial. È scritto per ESP32-CAM ma richiede solo una piccola modifica (cfg.setPins(pins::XiaoSense)) per funzionare con la XIAO-ESP32-S3 Sense.

Allo stesso modo, il tutorial Surveillance Camera with ESP32-CAM ti mostra come registrare video attivati dal movimento su file.

Se hai domande, sentiti libero di lasciarle nella sezione commenti.

Buon divertimento con il tinkering ; )