In diesem Tutorial lernst du, wie du Video von einem Seeed Studio XIAO-ESP32-S3 Sense Board über dein lokales Wi-Fi-Netzwerk an deinen Webbrowser streamst. So kannst du dein eigenes kabelloses Überwachungskamerasystem bauen, das du von deinem Computer aus überwachen kannst.
Wenn du den XIAO-ESP32-S3 Sense noch nicht benutzt hast, schau dir zuerst das Getting started with XIAO-ESP32-S3-Sense Tutorial an, das dir den Einstieg mit dem Board erleichtert.
Benötigte Teile
Natürlich brauchst du ein XIAO-ESP32-S3 Sense Board von Seeed Studio, um die Codebeispiele auszuprobieren. Beachte, dass das Board sehr heiß werden kann, zum Beispiel beim Streamen von Video mit hoher Bildrate. Ich empfehle, einen kleinen Heatsink an der Rückseite des Boards anzubringen (siehe unten aufgeführtes Teil).

Seeed Studio XIAO ESP32 S3 Sense

USB-C-Kabel

Kleiner Kühlkörper 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.
Video-Streaming
In diesem Projekt implementieren wir einen Video-Streaming-Server, der auf dem XIAO-ESP32-S3 Sense läuft. Die Kamera des XIAO-ESP32-S3 Sense nimmt Bilder auf und stellt sie über Wi-Fi bereit. Der Wi-Fi-Router überträgt diese Bilder an den Webbrowser auf deinem PC, der die Bilder als Videostream anzeigt. Das folgende Bild zeigt die Architektur des Systems:

Beachte, dass der Videostream nicht verschlüsselt oder gesichert ist, sondern nur unter einer URL innerhalb deines lokalen Wi-Fi-Netzwerks sichtbar ist, z.B. 192.168.2.40/stream. Nur jemand mit Zugang zu deinem Wi-Fi-Netzwerk kann den Videostream sehen.
Code für einen Video-Streaming-Server mit XIAO-ESP32-S3-Sense
Die Getting Started Wiki by Seeed Studio für XIAO-ESP32-S3-Sense bietet umfangreiche Informationen zum Board und enthält auch Beispielcode für einen Video-Streaming-Server. Dieser Code ist jedoch komplexer als der untenstehende.
Die Vereinfachung ist hauptsächlich der esp32cam Bibliothek zu verdanken, die du über den Library Manager in der Arduino IDE installieren kannst. Suche einfach nach „esp32cam“ und drücke INSTALL. Das Bild unten zeigt die abgeschlossene Installation:

Unten findest du den kompletten Code für den Video-Streaming-Server, der die esp32cam Bibliothek verwendet. Schau ihn dir kurz an, danach besprechen wir die Details:
#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();
}
Bibliotheken
Das Sketch beginnt mit dem Einbinden der notwendigen Bibliotheken:
#include "WebServer.h" #include "WiFi.h" #include "esp32cam.h"
Diese Bibliotheken ermöglichen HTTP-Server-Funktionalität (WebServer.h), Wi-Fi-Konnektivität (WiFi.h) und Kamerasteuerung mit der esp32cam Bibliothek.
Konstanten
Als nächstes definieren wir Konstanten für Wi-Fi- und Kameraeinstellungen:
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;
Die WIFI_SSID und WIFI_PASS Variablen speichern die Zugangsdaten für das Wi-Fi-Netzwerk. Du musst SSID und PASSWORD durch die tatsächlichen Zugangsdaten deines Wi-Fi-Netzwerks ersetzen.
Der URL ist der Pfad, unter dem der Videostream bereitgestellt wird. Du kannst ihn nach Belieben ändern, z.B. „/video“ oder „/frontdoor“, achte nur darauf, den Schrägstrich (‚/‘) am Anfang beizubehalten.
Die RESOLUTION legt die gewünschte Auflösung der Kamera fest. Unten findest du eine Liste möglicher Kameraauflösungen, wobei je nach Kamera nicht alle funktionieren:
- 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
Die FRAMERATE Variable definiert, wie viele Bilder pro Sekunde an den Client gesendet werden. So kannst du den Videostream verlangsamen und eine Überhitzung des Boards vermeiden. Wenn du die Bildrate zu hoch setzt, wird sie automatisch auf das Limit des ESP32 für die jeweilige Kameraauflösung begrenzt.
Objekte
Die folgende Zeile erstellt das HTTP-Server-Objekt, das auf Port 80 lauscht. Das ist unser Webserver, der den Videostream bereitstellt.
WebServer server(80);
handleStream
Die Funktion handleStream() verarbeitet den Videostream, sobald ein Client den /stream Pfad aufruft:
void handleStream() {
static char head[128];
WiFiClient client = server.client();
Diese Zeile holt den aktuell mit dem Server verbundenen Client. Die Antwort wird dann vorbereitet:
server.sendContent("HTTP/1.1 200 OK\r\n"
"Content-Type: multipart/x-mixed-replace; "
"boundary=frame\r\n\r\n");
Dieser Header teilt dem Browser mit, dass er einen multipart MJPEG-Stream erhält, bei dem jeder Teil durch eine Grenze namens frame getrennt ist.
Innerhalb der Schleife nimmt die Funktion zuerst einen Frame von der Kamera auf:
while (client.connected()) {
auto frame = esp32cam::capture();
Wenn ein Frame erfolgreich aufgenommen wurde, wird ein Header erstellt, der das JPEG-Bild beschreibt, und an den Client gesendet:
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
Die initCamera() Funktion konfiguriert und startet die Kamera:
void initCamera() {
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::XiaoSense);
cfg.setResolution(RESOLUTION);
cfg.setBufferCount(2);
cfg.setJpeg(80);
Camera.begin(cfg);
}
Zuerst wird ein Config Objekt erstellt. Die setPins Funktion konfiguriert die Kamerapins basierend auf dem XIAO-ESP32-S3 Sense Board. Siehe die pin configurations anderer unterstützter Boards.
setResolution definiert die zu verwendende Auflösung, während setBufferCount bestimmt, wie viele Bildpuffer intern verwendet werden, was schnellere Bildraten ermöglichen kann.
Die setJpeg Funktion setzt die JPEG-Kompressionsqualität zwischen 0 und 100. 80 ist ein guter Kompromiss zwischen Qualität und Größe. 90 liefert bessere Qualität, aber eine geringere Reduktion der Bildgröße. Für schnelleren Video-Stream kannst du die Auflösung und JPEG-Kompression reduzieren, bekommst dann aber kleinere Bilder mit geringerer Qualität.
Schließlich initialisiert Camera.begin(cfg) die Kamera mit diesen Einstellungen.
initWifi
Die initWifi() Funktion verbindet das XIAO-ESP32-S3 Sense Board mit dem angegebenen Wi-Fi-Netzwerk:
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) deaktiviert das Schreiben der Zugangsdaten in den Flash-Speicher, was die Wiederverbindung beschleunigt. Das Gerät wird in den Station-Modus (WIFI_STA) versetzt und versucht, sich mit den angegebenen Zugangsdaten mit dem Wi-Fi zu verbinden.
Nach der Verbindung werden die IP-Adresse und der Stream-Pfad im seriellen Monitor ausgegeben. Du musst diese URL in die Adressleiste deines Browsers kopieren, um den Videostream zu sehen. Die tatsächliche URL hängt von deinem Board ab, aber du kannst den Suffix „stream“ ändern. Bei meinem Board sehe ich folgende URL im seriellen Monitor:

Deshalb kopiere ich „http://192.168.2.40/stream“ in die Adressleiste meines Chrome-Browsers, um das Video zu sehen.
initServer
Die initServer() Funktion verknüpft den Streaming-Pfad mit dem Handler und startet den Server:
void initServer() {
server.on(URL, handleStream);
server.begin();
}
Dies ordnet alle Anfragen an /stream der handleStream() Funktion zu und startet dann den Server.
setup
Die setup() Funktion startet die serielle Kommunikation, verbindet mit Wi-Fi, initialisiert die Kamera und richtet den Webserver ein:
void setup() {
Serial.begin(115200);
initWifi();
initCamera();
initServer();
}
loop
Schließlich verarbeitet die loop() Funktion kontinuierlich eingehende HTTP-Anfragen:
void loop() {
server.handleClient();
}
Diese Zeile erlaubt dem XIAO-ESP32-S3 Sense, auf Client-Anfragen zu reagieren, indem registrierte Handler wie handleStream() aufgerufen werden.
Insgesamt erstellt dieser Code einen einfachen, aber effektiven MJPEG-Streaming-Server, der von jedem Webbrowser im gleichen Netzwerk zugänglich ist und einen Live-Kamerafeed vom XIAO-ESP32-S3 Sense liefert.
Um den Code auf dein XIAO-ESP32-S3 Sense zu laden, wähle das XIAO_ESP32S3 Board aus und drücke den Download-Button.

XIAO_ESP32S3 als Board ausWenn du weitere Hilfe brauchst, schau dir das Getting started with XIAO-ESP32-S3-Sense Tutorial an.
Fazit
In diesem Tutorial hast du gelernt, wie du Video von einem XIAO-ESP32-S3 Sense über dein lokales Wi-Fi-Netzwerk an deinen Webbrowser streamst.
Wenn du Objekte im Videostream erkennen möchtest, schau dir das Object Detection with ESP32-CAM and YOLO Tutorial an. Es ist für den ESP32-CAM geschrieben, benötigt aber nur eine kleine Änderung (cfg.setPins(pins::XiaoSense)), um mit dem XIAO-ESP32-S3 Sense zu funktionieren.
Ähnlich zeigt dir das Surveillance Camera with ESP32-CAM Tutorial, wie du bewegungsaktivierte Videostreams in eine Datei aufzeichnest.
Wenn du Fragen hast, hinterlasse sie gerne im Kommentarbereich.
Viel Spaß beim Tüfteln ; )

