🚀 RPiCam-Apps v1.9.1: Der Durchbruch für stabiles Raspberry Pi Livestreaming Die Suche nach einer verlässlichen Lösung für das Livestreaming von einem Raspberry Pi zu einem zentralen Server war lange von Hürden geprägt. Doch mit der
🚀 RPiCam-Apps v1.9.1: Der Durchbruch für stabiles Raspberry Pi Livestreaming
Die Suche nach einer verlässlichen Lösung für das Livestreaming von einem Raspberry Pi zu einem zentralen Server war lange von Hürden geprägt. Doch mit der rpicam-apps Version v1.9.1 erleben wir endlich den entscheidenden Fortschritt!
Diese Version bringt nach intensiven Fehlerbehebungen die notwendige Stabilität und funktioniert nun fehlerfrei sowohl unter Raspberry Pi OS Bookworm (Debian 12) als auch unter dem neueren Raspi Trixie (Debian 13). Insbesondere die kritischen Speicherzugriffsfehler unter Trixie sind mit diesem Update endlich behoben.
Falls die neue Version noch nicht über den Paketmanager apt
verfügbar ist, besteht kein Grund zur Sorge: Die rpicam-apps
lassen sich relativ simpel per Git klonen und selbst kompilieren.
💡 Die Herausforderung: FullHD-Streaming mit 30 FPS und Audio vom Raspberry Pi Zero 2 W
Unser Ziel ist klar: Wir wollen Livestreams in FullHD (1080p) und 30 FPS mit Audio von einem kompakten Raspberry Pi Zero 2 W auf einen zentralen Server senden.
Um dieses anspruchsvolle Vorhaben auf dem kleinen Rechner zu realisieren, muss eine Vielzahl von Faktoren beachtet und optimiert werden:
- Hardware-Ressourcen: CPU-Leistung, RAM und die Geschwindigkeit der SD-Karte.
- Kritische Dienste: Laufende Prozesse wie Fenstermanager und grafische Oberflächen.
- Konnektivität: Stabile Netzwerkgeschwindigkeit über WLAN.
- Media-Komponenten: Optimale Kamera-Einstellungen sowie die Konfiguration von Mikrofon und Audio-Managern wie ALSA oder PulseAudio.
Die richtige Zusammenstellung all dieser Komponenten zu finden, ist eine komplexe Aufgabe. Es ist nicht leicht, alle Komponenten in Einklang zu bringen und dabei die möglichen Flaschenhälse im Zusammenspiel des Stream-Aufbaus zu identifizieren.
Nach intensiven Tests und detaillierten Analysen haben wir die Schlüssel zu einem stabilen Stream gefunden. Hier präsentieren wir unsere Überlegungen und die daraus resultierenden Ergebnisse in aller Kürze:
➡️ Wichtige Vorbemerkung zur Software: Wir setzen auf die rpicam-apps in Version v1.9.1 oder neuer. Diese Version behebt kritische Speicherzugriffsfehler unter Raspberry Pi OS Bookworm (Debian 12) und Trixie (Debian 13) und ist somit die Basis für ein stabiles System. Falls noch nicht per apt
verfügbar, kann die Kompilierung über Git erfolgen.
1. 🛑 Swap oder Nicht-Swap? Der Speicher-Flaschenhals
Unsere umfangreichen Tests rund um die Speicherverwaltung – inklusive Experimenten mit verschiedenen Swap-Größen, der swappiness
und komprimiertem ZRAM-Swap – führten uns zu einem klaren und kritischen Ergebnis:
- Das Problem: Wird im System geswappt, entzieht dies anderen Prozessen systemweit Rechen- und Schreibleistung. Unabhängig davon, ob der Swap komprimiert ist oder nicht, stellt das Auslagern eine enorme Fehlerquelle dar, die die Stabilität des Livestreams massiv gefährden kann.
- Das Fazit: Swapping muss minimiert oder idealerweise komplett eliminiert werden.
🖥️ Optimale Konfiguration für stabile Streams
Um dies zu erreichen, streben wir zwei Szenarien an:
- System ohne GUI (Best Practice): Wenn Sie ohne eine grafische Oberfläche (Fenstermanager) auskommen, ist dies der größte Vorteil. Sie können in diesem Fall meist komplett auf Swap-Speicher verzichten. Dadurch eliminieren Sie speicher- und rechenintensive Prozesse und stellen die maximale Leistung für den Stream-Aufbau sicher.
- System mit GUI (Der Kompromiss): Sollte dennoch eine grafische Oberfläche benötigt werden (z. B. für eine Anzeige von Messwerten wie Temperatur, Datum und Uhrzeit in einem Pygame-Fenster), ist Folgendes zu beachten:
- Stellen Sie sicher, dass der verbleibende freie RAM ausreichend groß ist. Testen Sie dies am besten während der Laufzeit mit Analyse-Tools wie
btop
oderbpytop
. - Setzen Sie die
swappiness
auf einen Wert zwischen 1 und 10. Ein niedriger Wert sorgt dafür, dass das System nur im äußersten Notfall mit der Auslagerung beginnt und diese nicht permanent die Systemressourcen blockiert.
- Stellen Sie sicher, dass der verbleibende freie RAM ausreichend groß ist. Testen Sie dies am besten während der Laufzeit mit Analyse-Tools wie
Ziel ist immer: Mehr RAM-Nutzung, weniger Festplattenzugriff – der Schlüssel zur Eliminierung von Verzögerungen und Stream-Abbrüchen.
2. ⚡ CPU-Taktung und Governance: Sparen, wo es geht
Die gute Nachricht zuerst: Unsere Tests ergaben, dass der eigentliche FullHD-Stream mit Video und Audio nur 15% bis 25% der Rechenleistung des Raspberry Pi Zero 2 W beansprucht. Das ist deutlich weniger als oft angenommen.
- Energie sparen: Da der Grundbedarf gering ist, können wir die CPU-Taktfrequenz reduzieren. Im Grunde kommen wir mit 600 MHz und einer
powersave
oderondemand
Governor-Einstellung aus. Dies spart Strom und reduziert den Bedarf an aktiver Kühlung. - Wärmeentwicklung und Kühlung: Trotz der geringen CPU-Auslastung ist passive Kühlung dennoch dringend empfohlen. Streaming beansprucht auch die GPU (für das H.264-Encoding) und das Netzwerk, was zu einer generellen Temperaturerhöhung führt. Mit passiven Kühlkörpern pendelt sich die Temperatur meist bei etwa 60 Grad Celsius ein.
- Fehlerbehebung bei Instabilität: Sollten Sie dennoch Stream-Abbrüche oder kritische Alsa Buffer Xruns (Audiofehler) feststellen, kann die Ursache manchmal doch in der Rechenleistung liegen. Hier empfiehlt sich, testweise auf den
performance
Governor umzustellen. Dies kann eventuelle Engpässe beseitigen.
Ein simples Shell-Skript (cpu-settings.sh
) zum einfachen Auslesen und Setzen des Governors finden Sie im Anhang dieses Beitrags.
3. Netzwerk: Der Kritische Flaschenhals
Das WLAN ist die häufigste Ursache für Stream-Abbrüche und Alsa Buffer Xrun Fehler, und gleichzeitig die große Unbekannte mit oft erratischem Verhalten.
Obwohl der Zero 2 W Linkqualitäten von 60-80% und über 30 Mbit Bruttogeschwindigkeit anzeigte (was für einen 4 Mbit Stream theoretisch reichen sollte), war die Verbindung instabil.
- Das entscheidende Finding: Stabile Streams über Stunden und Tage wurden nur mit einer Linkqualität zwischen 90% und 100% und stabilen 72 Mbit in Sende- (TX) und Empfangsrichtung (RX) erreicht.
- Analyse-Tool: Nutzen Sie
wavemon
(apt install wavemon
) auf dem Raspberry Pi, um die exakte Netzwerklage einzusehen und die Stabilität abzuschätzen. - Lösung: Gehen Sie diesen Aufwand ein! Eine Umpositionierung von Pi oder Router oder der Einsatz eines Repeaters ist nötig, um diese Werte zu erreichen. Die Netzwerkleistung ist die entscheidende Größe für Langzeitstabilität.
4. 📸 Kamera- und Mikrofon-Settings: Qualität und Effizienz
Mit den richtigen Einstellungen liefert der kleine Raspberry Pi Zero 2 W FullHD-Streams von beeindruckender Qualität, die oft besser sind als die Ergebnisse kommerzieller Überwachungskameras – vorausgesetzt, Sie achten auf ausreichend Licht und ein gutes Mikrofon.
Video: GPU-Encoding und Bildeinstellungen
Um die knappen Ressourcen optimal zu nutzen, setzen wir auf Hardware-Beschleunigung:
- GPU-Nutzung: Wir nutzen die GPU des Raspberry Pi für die H.264-Erzeugung. Dies entlastet die CPU massiv.
- Sensor-Optimierung: Für den kleinen IMX-Sensor stellen wir Belichtung (
exposure
), White Balance (awb
), Sättigung (saturation
), Kontrast (contrast
) und Schärfe (sharpness
) auf brauchbare Werte ein. - HDR-Option: Bei Bedarf können Sie mit wenig Aufwand HDR-Streams (High Dynamic Range) produzieren. HDR hellt dunkle Bildbereiche auf und dunkelt helle ab. Für authentischere Streams belassen wir es jedoch meist bei der Deaktivierung von HDR.
Audio: ALSA als beste Wahl
Für die Audio-Einstellungen empfehlen wir dringend, auf die ALSA-Struktur zu setzen.
- Prozess-Minimierung: Audio-Manager wie Pipewire und PulseAudio legen zusätzliche laufende Prozesse auf das System und sind im Hintergrund trotzdem auf ALSA angewiesen. Nach dem Motto “Je weniger, desto besser” verzichten wir auf diese zusätzlichen Ebenen.
- Root-Kompatibilität: Wichtig für den Betrieb als Systemdienst: PulseAudio lässt sich nicht als Root-User ausführen. Da der System-Stream oft unter Root-Rechten läuft, ist ALSA hier die praktikabelste Lösung.
Mikrofon-Konfiguration
Lautstärkeeinstellung: Die Mikrofonlautstärke stellen Sie über das Tool alsamixer
ein. Achten Sie darauf, die gewünschte Lautstärke zu erreichen, ohne dabei zu übersteuern. Fast alle günstigen USB-Mikrofone haben sich in unseren Tests bewährt.
Geräte-Auswahl: Mit dem Befehl arecord -l
listen Sie die verfügbaren Audio-Karten und -Devices auf.
Stream-Einbindung: Das korrekte Device setzen Sie dann im Stream-Kommando mit der Option --audio-device hw:0,0
(wobei 0,0
durch Ihre ermittelten Werte ersetzt werden muss).
5. Das Perfekte Stream-Kommando und seine Parameter
Dieses Kommando nutzt rpicam-vid
und sendet einen H.264 Video- und AAC Audio-Stream im FLV-Format an einen Nginx-RTMP Server.
Wichtig: Ersetzen Sie 192.168.x.y
durch die tatsächliche IP Ihres RTMP-Servers.
Bash
#!/bin/bash
nice -n -19 rpicam-vid -t 0 --width 1920 --height 1080 \
--nopreview 1 --low-latency 1 --hdr off --flush 1 \
--buffer-count 6 --exposure long --sharpness 1.1 --contrast 1.2 \
--brightness 0.0 --saturation 1.0 --ev +1.0 --awb auto \
--profile high --level 4.2 --codec libav --libav-audio 1 \
--audio-source alsa --audio-device hw:0,0 --audio-channels 1 \
--audio-codec aac \
--audio-samplerate 48000 --audio-bitrate 128000 --libav-format flv \
-n --framerate 30 -b 4500000 --autofocus-mode manual --lens-position 0.8 \
--denoise auto --autofocus-window 0.25,0.25,0.5,0.5 --inline 1 \
-o "rtmp://192.168.x.y/zero/test"
📋 Detaillierte Erklärung der Optionen
Option | Wert | Erklärung |
nice -n -19 | Priorisierung des Stream-Prozesses. -19 ist die höchste Priorität und sichert die Rechenleistung. | |
-t 0 | Unendliche Aufnahmezeit (0 Millisekunden), d.h., der Stream läuft, bis er gestoppt wird. | |
--width , --height | 1920 , 1080 | Setzt die FullHD-Auflösung (1080p). |
--nopreview 1 | Deaktiviert die lokale Bildvorschau, spart Ressourcen. | |
--low-latency 1 | Wichtig für geringe Verzögerungen im Stream. | |
--hdr off | High Dynamic Range (HDR) ist deaktiviert, um einen authentischeren Look zu gewährleisten. | |
--flush 1 | Erhöht die Reaktionsfähigkeit und reduziert die Pufferung. | |
--buffer-count 6 | Anzahl der Puffer, die für die Video-Frames verwendet werden. Optimiert für den Stream. | |
--exposure long | Belichtungszeit auf ‘lang’ gesetzt, oft gut für Innenräume/wenig Licht. | |
--sharpness 1.1 , --contrast 1.2 | Anpassung der Bildeigenschaften (hier leicht erhöht). | |
--codec libav | Verwendet die Libav-Bibliothek für Encoding und Streaming. | |
--libav-audio 1 | Aktiviert die Audio-Verarbeitung durch Libav. | |
--audio-source alsa | Definiert ALSA als Audio-Quelle, um Pulse/Pipewire zu umgehen. | |
--audio-device hw:0,0 | Das spezifische Audio-Gerät (Karte 0, Gerät 0), ermittelt durch arecord -l . | |
--audio-codec aac | Audio-Codec AAC (Advanced Audio Coding), Standard für Streaming. | |
--audio-samplerate 48000 | Samplerate für die Audioaufnahme (48 kHz). | |
--audio-bitrate 128000 | Audio-Bitrate von 128 kbps. | |
--libav-format flv | Containerformat FLV (Flash Video), Standard für RTMP-Streaming. | |
-n | Deaktiviert das Speichern in einer lokalen Datei. | |
--framerate 30 | Die gewünschte Bildrate pro Sekunde. | |
-b 4500000 | Video-Bitrate von 4.5 Mbit/s (4500000 Bits pro Sekunde). | |
--autofocus-mode manual | Autofokus ist manuell eingestellt. | |
--lens-position 0.8 | Manuelle Einstellung der Fokusposition für eine feste Schärfe. | |
--inline 1 | Fügt SPS/PPS-Header in den Stream ein (wichtig für die Dekodierung). | |
-o "rtmp://..." | Die Ausgabe-URL an den Nginx-RTMP Server. |
6. Automatischer Start: Stream als Systemdienst
Für den automatischen Start des Streams beim Booten erstellen wir einen Systemdienst (Service-Unit).
1. Dienstdatei erstellen:
nano /lib/systemd/system/stream.service
2. Inhalt stream.service
:
[Unit]
Description=ZeroCam stream service
After=network.target
Wants=network-online.target
StartLimitIntervalSec=3
StartLimitBurst=5
[Service]
Type=simple
ExecStartPre=/bin/sleep 1
Nice=-12
Restart=always
RestartSec=5
User=root
WorkingDirectory=/home/axel
ExecStart=/usr/bin/streamfull
# Das streamfull.sh Skript wurde hier ohne .sh nach /usr/bin/ kopiert.
[Install]
WantedBy=multi-user.target
3. Dienst aktivieren und starten:
systemctl enable stream.service
systemctl start stream.service
Der Stream sollte nun automatisch bei jedem Systemstart laufen.
7. Überwachung und Fehlerbehebung
Zur Überwachung der Stabilität dient das System-Journal, insbesondere, wenn der Stream als Dienst läuft.
🔍 Journal-Überwachung
Bash
journalctl -u stream.service -f
🟢 Stabile Stream-Ausgabe
Ein stabiler Stream zeigt erfolgreiche Initialisierungen und eine fortlaufende Audio-/Videokette:
root@zero:/home/axel# journalctl -u stream.service -f
Okt 18 09:00:17 zero.jerabek.fi streamfull[1440]: [h264_v4l2m2m @ 0x55c1978350] <<< v4l2_encode_init: fmt=179/0
Okt 18 09:00:17 zero.jerabek.fi streamfull[1440]: [h264_v4l2m2m @ 0x55c1978350] Using device /dev/video11
Okt 18 09:00:17 zero.jerabek.fi streamfull[1440]: [h264_v4l2m2m @ 0x55c1978350] driver 'bcm2835-codec' on card 'bcm2835-codec-encode' in mplane mode
Okt 18 09:00:17 zero.jerabek.fi streamfull[1440]: [h264_v4l2m2m @ 0x55c1978350] requesting formats: output=YU12 capture=H264
Okt 18 09:00:17 zero.jerabek.fi streamfull[1440]: Input #0, alsa, from 'hw:0,0':
Okt 18 09:00:17 zero.jerabek.fi streamfull[1440]: Duration: N/A, start: 1760770817.363771, bitrate: 768 kb/s
Okt 18 09:00:17 zero.jerabek.fi streamfull[1440]: Stream #0:0: Audio: pcm_s16le, 48000 Hz, 1 channels, s16, 768 kb/s
Okt 18 09:00:17 zero.jerabek.fi streamfull[1440]: Output #0, flv, to 'rtmp://192.168.178.25/zero/test':
Okt 18 09:00:17 zero.jerabek.fi streamfull[1440]: Stream #0:0: Video: h264 (High), drm_prime(tv, bt709), 1920x1080, q=2-31, 4500 kb/s, 30 fps, 30 tbr, 1000k tbn
Okt 18 09:00:17 zero.jerabek.fi streamfull[1440]: Stream #0:1: Audio: aac (LC), 48000 Hz, mono, fltp, 128 kb/s
🔴 Tracking-Fehler (Instabiler Stream)
Pkt tracking failure
deutet auf eine Instabilität im Stream hin, der neu eingestellt und neu gestartet werden muss:
Oct 18 09:10:55 zero3 streamfull[2322]: [h264_v4l2m2m @ 0x55a1a21480] Pkt tracking failure: pts=101818, track[58]=101946
🔊 Audio Buffer Xruns (Typischer Fehler)
Audio Buffer Xruns gehören zu den häufigsten Fehlern in unseren Stream-Protokollen. Sie sind ein deutliches Anzeichen dafür, dass es zu Paketierfehlern zwischen Video und Audio kommt. Im Kern signalisieren sie eine Überlastung des Systems oder des Übertragungswegs.
Die Echte Ursache: Meistens das WLAN
Obwohl Xruns auf überlastete Hardware hindeuten können, war in unserem Fall die Ursache sehr oft “lediglich” die instabile WLAN-Verbindung zwischen dem Raspberry Pi und dem Nginx-RTMP Server (bzw. dem Router/der Fritzbox).
root@zero3:/home/axel# journalctl -u stream.service -f
Oct 18 15:39:50 zero3 streamfull[7439]: SRGGB10_CSI2P,1640x1232/41.8515 - Score: 1000
Oct 18 15:39:50 zero3 streamfull[7439]: SRGGB10_CSI2P,1920x1080/47.5737 - Score: 1541.48
Oct 18 15:39:50 zero3 streamfull[7439]: SRGGB10_CSI2P,3280x2464/21.1941 - Score: 19329.9
Oct 18 15:39:50 zero3 streamfull[7439]: SRGGB8,640x480/103.327 - Score: 5504.81
Oct 18 15:39:50 zero3 streamfull[7439]: SRGGB8,1640x1232/41.8515 - Score: 2000
Oct 18 15:39:50 zero3 streamfull[7439]: SRGGB8,1920x1080/47.5737 - Score: 2541.48
Oct 18 15:39:50 zero3 streamfull[7439]: SRGGB8,3280x2464/21.1941 - Score: 20329.9
Oct 18 15:39:50 zero3 streamfull[7439]: Stream configuration adjusted
Oct 18 15:39:50 zero3 streamfull[7439]: [7:41:07.117053737] [7439] INFO Camera camera.cpp:1215 configuring streams: (0) 1640x1232-YUV420/Rec709 (1) 1640x1232-SRGGB10_CSI2P/RAW
Oct 18 15:39:50 zero3 streamfull[7439]: [7:41:07.117807228] [7442] INFO RPI vc4.cpp:615 Sensor: /base/soc/i2c0mux/i2c@1/imx219@10 - Selected sensor format: 1640x1232-SRGGB10_1X10/RAW - Selected unicam format: 1640x1232-pRAA/RAW
Oct 18 15:39:57 zero3 streamfull[7439]: [h264_v4l2m2m @ 0x55682da480] <<< v4l2_encode_init: fmt=179/0
Oct 18 15:39:57 zero3 streamfull[7439]: [h264_v4l2m2m @ 0x55682da480] Using device /dev/video11
Oct 18 15:39:57 zero3 streamfull[7439]: [h264_v4l2m2m @ 0x55682da480] driver 'bcm2835-codec' on card 'bcm2835-codec-encode' in mplane mode
Oct 18 15:39:57 zero3 streamfull[7439]: [h264_v4l2m2m @ 0x55682da480] requesting formats: output=YU12 capture=H264
Oct 18 15:39:57 zero3 streamfull[7439]: Input #0, alsa, from 'hw:0,0':
Oct 18 15:39:57 zero3 streamfull[7439]: Duration: N/A, start: 1760794797.840298, bitrate: 768 kb/s
Oct 18 15:39:57 zero3 streamfull[7439]: Stream #0:0: Audio: pcm_s16le, 48000 Hz, 1 channels, s16, 768 kb/s
Oct 18 15:39:57 zero3 streamfull[7439]: Output #0, flv, to 'rtmp://192.168.178.25/zero3/test':
Oct 18 15:39:57 zero3 streamfull[7439]: Stream #0:0: Video: h264 (Main), drm_prime(tv, bt709), 1640x1232, q=2-31, 3500 kb/s, 30 fps, 30 tbr, 1000k tbn
Oct 18 15:39:57 zero3 streamfull[7439]: Stream #0:1: Audio: aac (LC), 48000 Hz, mono, fltp, 64 kb/s
Oct 18 15:40:02 zero3 streamfull[7439]: [alsa @ 0x55682e1e30] ALSA buffer xrun.
Oct 18 15:40:04 zero3 streamfull[7439]: [alsa @ 0x55682e1e30] ALSA buffer xrun.
Oct 18 15:40:08 zero3 streamfull[7439]: [alsa @ 0x55682e1e30] ALSA buffer xrun.
Oct 18 15:40:13 zero3 streamfull[7439]: [alsa @ 0x55682e1e30] ALSA buffer xrun.
Oct 18 15:40:18 zero3 streamfull[7439]: [alsa @ 0x55682e1e30] ALSA buffer xrun.
Oct 18 15:40:23 zero3 streamfull[7439]: [alsa @ 0x55682e1e30] ALSA buffer xrun.
Oct 18 15:40:27 zero3 streamfull[7439]: [alsa @ 0x55682e1e30] ALSA buffer xrun.
Oct 18 15:40:29 zero3 streamfull[7439]: [alsa @ 0x55682e1e30] ALSA buffer xrun.
🛠️ Lösung und Strategie
- Bitrate reduzieren: Sollte es Ihnen trotz aller Bemühungen nicht gelingen, eine stabile 100-Prozent-Verbindung zum Router herzustellen, versuchen Sie, die Datenraten von Video und/oder Audio etwas herunterzuschrauben. Dadurch verringert sich die Datenlast pro Sekunde.
- Netzwerkproblem fundamental lösen: Treten die Xruns danach immer noch auf, ist eine reine Reduzierung der Bitrate nicht ausreichend. In diesem Fall muss das WLAN/WiFi-Problem grundsätzlich angegangen werden: Optimale Umpositionierung des Raspberry Pi und/oder des Routers oder der Einsatz eines WLAN-Repeaters sind die einzig dauerhaften Lösungen.
Xruns sind ein kritischer Indikator. Ignorieren Sie sie nicht, denn sie bedeuten, dass Ihr Stream nicht robust genug für den Langzeitbetrieb ist.
8. 🛡️ Automatisierte Überwachung: Den Stream am Laufen halten
Selbst bei optimaler Konfiguration können externe Faktoren (wie kurzzeitige WLAN-Schwankungen) zu ALSA Buffer Xruns führen. Bevor diese Fehler den Stream komplett unbrauchbar machen und er nicht mehr vom Nginx-RTMP-Server abgerufen werden kann, sollte proaktiv gehandelt werden.
Wir richten einen dedizierten Systemd-Überwachungsdienst ein, der das Log des eigentlichen Streams (stream.service
) permanent ausliest und bei Erkennung des Schlüsselworts “ALSA buffer xrun” sofort einen Neustart auslöst.
Schritt 1: Das Überwachungs-Skript erstellen
Erstellen Sie das Shell-Skript, das das journalctl
-Log überwacht und den Neustart durchführt.
nano /home/pi/scripts/monitor_stream_single.sh
Inhalt monitor_stream_single.sh
:
#!/bin/bash
SERVICE_NAME="stream.service"
LOG_FILE="/var/log/buffer_xrun_restart.log"
# Das Skript benötigt Lesezugriff auf das Journal.
# Es liest das Log des Stream-Dienstes (-u) im Follow-Modus (-f).
journalctl -u "$SERVICE_NAME" -f | while read -r line; do
# Prüft, ob die kritische Fehlermeldung auftritt
if echo "$line" | grep -q "ALSA buffer xrun"; then
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Protokolliert den Neustart in einer separaten Log-Datei
echo "[$timestamp] Detected buffer xrun. Restarting $SERVICE_NAME" >> "$LOG_FILE"
# Führt den Neustart des Stream-Dienstes aus
systemctl restart "$SERVICE_NAME"
fi
done
Stellen Sie sicher, dass das Skript ausführbar ist:
chmod +x /home/pi/scripts/monitor_stream_single.sh
Schritt 2: Den Systemd-Monitor-Dienst erstellen
Erstellen Sie die Unit-Datei für den Überwachungsdienst.
nano /etc/systemd/system/stream-monitor.service
Inhalt stream-monitor.service
:
[Unit]
Description=Monitor stream.service for ALSA buffer xrun and restart on error
After=network.target
[Service]
ExecStart=/home/pi/scripts/monitor_stream_single.sh
Restart=always
RestartSec=5
StandardOutput=null
StandardError=journal
User=root
[Install]
WantedBy=multi-user.target
ParameterErklärung: ExecStart
Startet das erstellte Überwachungs-Skript.Restart=always
Stellt sicher, dass der Monitor selbst immer läuft, auch wenn er abstürzt.StandardOutput=null
Verhindert, dass das Skript unnötige Ausgaben ins Journal schreibt.User=root
Wichtig, da das Skript journalctl
lesen und systemctl restart
ausführen muss.
Schritt 3: Dienst aktivieren und starten
Laden Sie die Konfiguration neu, aktivieren und starten Sie den Dienst:
systemctl daemon-reload
systemctl enable stream-monitor.service
systemctl start stream-monitor.service
Ihr Raspberry Pi Zero 2 W überwacht nun proaktiv seine eigene Stream-Stabilität. Tritt ein ALSA buffer xrun
auf, wird der Stream innerhalb weniger Sekunden neu gestartet, was die Verfügbarkeit drastisch erhöht.
🏁 Fazit: Die Lektion des Zero 2 W und der Wunsch an die Entwickler
Die Reise zum stabilen FullHD-Livestream vom Raspberry Pi Zero 2 W war eine Lektion in Geduld und Systemverständnis. Die wichtigste Erkenntnis ist, dass wir es hier mit einem System zu tun haben, das kaum Puffer für Mikrounterbrechungen im Datenfluss toleriert.
Die größten Frustrationen entstehen dadurch, dass die Fehlerquellen nicht offensichtlich sind. Das beste Beispiel ist die WLAN-Geschwindigkeit: Rechnerisch sollten 30 Mbit/s für einen 4 Mbit Stream mehr als ausreichen. In der Praxis zeigte sich jedoch, dass ohne eine stabile 72 Mbit-Verbindung der Stream unweigerlich kippt – ein rechnerischer Trugschluss, der zu stundenlanger Fehlersuche an der falschen Stelle führen kann (z. B. CPU oder Swap).
Anfangs machten alle latenten Fehlerquellen zusammen den Stream instabil. Nur durch die konsequente Optimierung jedes einzelnen Glieds der Kette – von der Eliminierung des Swaps über die korrekte Governor-Einstellung bis hin zur kompromisslosen Netzwerkleistung – konnten wir einen robusten 24/7-Betrieb erreichen. Der kleine Pi Zero 2 W erholt sich bei kurzen Aussetzern im WLAN meist nicht mehr; der Stream ist dann unwiderruflich kaputt.
Abschließend bleibt nur ein Wunsch, der die Streams noch zuverlässiger machen würde:
Wir wünschen uns vom rpicam-apps Team, dass endlich eine vernünftige Methode zur Synchronisation bezüglich des Video- und Audio-Sync bei der Initialisierung des Streams integriert wird!
Bis dahin hoffen wir, dass unsere gesammelten Erfahrungen Ihnen helfen, Ihren perfekten Livestream auf dem Raspberry Pi Zero 2 W schnell und stabil einzurichten.
Anhang: CPU-Governor Shell-Skript (cpu-settings.sh
)
Bash
#!/bin/bash
# Pfad zum CPU-Governor-Verzeichnis
GOVERNOR_PATH="/sys/devices/system/cpu/cpufreq/policy0/scaling_governor"
# Funktion, um den aktuellen Governor anzuzeigen
show_governor() {
if [ -f "$GOVERNOR_PATH" ]; then
current_governor=$(cat "$GOVERNOR_PATH")
echo "Aktueller CPU-Governor: $current_governor"
else
echo "Fehler: Konnte den Pfad zum Governor-Verzeichnis nicht finden."
exit 1
fi
}
# Funktion, um den Governor zu ändern
set_governor() {
local new_governor=$1
echo "Ändere Governor zu '$new_governor'..."
if [ -f "$GOVERNOR_PATH" ]; then
echo "$new_governor" | sudo tee "$GOVERNOR_PATH" > /dev/null
if [ $? -eq 0 ]; then
echo "Erfolgreich geändert."
else
echo "Fehler: Konnte den Governor nicht ändern. Möglicherweise fehlen root-Rechte."
fi
else
echo "Fehler: Konnte den Pfad zum Governor-Verzeichnis nicht finden."
exit 1
fi
}
# Hauptlogik des Skripts
case "$1" in
"status")
show_governor
;;
"ondemand")
set_governor "ondemand"
;;
"performance")
set_governor "performance"
;;
"powersave")
set_governor "powersave"
;;
"schedutil")
set_governor "schedutil"
;;
*)
echo "Verwendung: $0 [status|ondemand|performance|powersave|schedutil]"
echo " status: Zeigt den aktuellen Governor an."
echo " ondemand: Stellt den Governor auf 'ondemand'."
echo "performance: Stellt den Governor auf 'performance'."
echo "powersave: Stellt den Governor auf 'powersave'."
echo "schedutil: Stellt den Governor auf 'schedutil'."
;;
esac
Anhang 2 – Nginx-RTMP Server Beispiel-config: (mit gleichzeitigem HLS Stream)
user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
multi_accept on;
use epoll;
}
http {
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_types text/plain application/json application/javascript text/css application/xml text/javascript;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
server {
listen 9090;
location / {
root /var/www/html;
index index.html;
}
# HLS Streams für mevo
location /hlsmevo/ {
root /var/hls;
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
add_header Cache-Control no-cache;
}
# HLS Streams für pi
location /hlspi/ {
root /var/hls;
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
add_header Cache-Control no-cache;
}
# HLS Streams für zero
location /hlszero/ {
root /var/hls;
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
add_header Cache-Control no-cache;
}
# HLS Streams für zero2
location /hlszero2/ {
root /var/hls;
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
add_header Cache-Control no-cache;
}
# HLS Streams für zero3
location /hlszero3/ {
root /var/hls;
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
add_header Cache-Control no-cache;
}
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}
}
rtmp {
server {
listen 1935;
timeout 30s;
chunk_size 4096;
allow publish all;
allow play all;
play_restart on;
idle_streams off;
drop_idle_publisher 60s;
max_message 8M;
max_connections 512;
respawn on;
application mevo {
live on;
record off;
hls on;
hls_path /var/hls/hlsmevo;
hls_fragment 8;
hls_playlist_length 16;
hls_type live;
sync 100ms;
hls_cleanup on;
}
application pi {
live on;
record off;
hls on;
hls_path /var/hls/hlspi;
hls_fragment 8;
hls_playlist_length 16;
hls_type live;
sync 100ms;
hls_cleanup on;
}
application zero {
live on;
record off;
hls on;
hls_path /var/hls/hlszero;
hls_fragment 8;
hls_playlist_length 16;
hls_type live;
sync 100ms;
hls_cleanup on;
}
application zero2 {
live on;
record off;
hls on;
hls_path /var/hls/hlszero2;
hls_fragment 8;
hls_playlist_length 16;
hls_type live;
sync 100ms;
hls_cleanup on;
}
application zero3 {
live on;
record off;
hls on;
hls_path /var/hls/hlszero3;
hls_fragment 8;
hls_playlist_length 16;
hls_type live;
sync 100ms;
hls_cleanup on;
}
}
}