Video-Livestream mit Raspberry Pi und mediaMTX zu Janus WebRTC Server

Grafische Darstellung eines Drehtellers mit Fat Valley Logo

Um das Arbeiten mit Photogrammetrie zu erleichtern, haben wir einen Drehteller (-tisch) konzipiert und gebaut, der von einem Schrittmotor angetrieben wird. Der Tisch steht in einer Ecke unseres Büros.

Ihr könnt den Tisch drehen und die Geschwindigkeit anpassen. Falls wir in der Nähe sind, setzten wir uns auch gerne mal drauf. 😵‍💫

Die Steuerung des Tisches erfolgt über Websockets. In diesem Beitrag wollen wir aber auf die Realisierung des Livestreams eingehen.

Im ersten Schritt erklären wir, wie man einen Raspberry Pi mit Kamera-Modul zum Streamen bringt. Im nächsten Schritt leiten wir den Videostream an einen WebRTC-Server (Janus Gateway) weiter, damit das Video von vielen Clients gleichzeitig gesehen werden kann.

Raspberry Pi Videostream

Wir verwenden für diese Anleitung einen Raspi 4 mit angeschlossenem Kameramodul und Raspberry Pi OS Debian version: 12 (Bookworm). Bei unserem Beispiel ist Raspi OS Lite Bookworm 64-bit im Einsatz.

Da GStreamer(rpicamsrc / raspivid) die neue libcamera nicht mehr unterstützt, kommt der sehr effiziente MediaMTX Server zum Einsatz.

Zuerst machen wir ein Update und installieren die benötigten Pakete:

sudo apt update && apt full-upgrade
sudo apt install libfreetype6 libcamera0

MediaMTX steht als 32- und 64-Bit Version zur Verfügung. Welches OS wir benutzen, kann mit:

uname -m

herausgefunden werden. armv7l = 32Bit, aarch64 = 64Bit.

Nun laden wir die entsprechende Version (Linux armv7 / arm64v8) von der Release-Seite des Projekts herunter und entpacken das Archiv nach /opt/mediamtx.

Bevor MediaMTX gestartet werden kann, müssen wir die Binary-Datei ausführbar machen:

sudo chmod +x /opt/mediamtx/mediamtx

In /opt/mediamtx/mediamtx.yml (ganz unten) ergänzen wir:

paths:
# example:
# my_camera:
# source: rtsp://my_camera
# Settings under path "all_others" are applied to all paths that
# do not match another entry.
all_others:

mit:

paths:
  cam:
    source: rpiCamera

all_others:

Achtung: in YAML-Dateien muss auf die Einrückung am Zeilenanfang geachtet werden!

In mediamtx.yml kann die Auflösung, Bitrate, Helligkeit, etc. der Raspi-Cam eingestellt werden. "cam:" definiert den jeweiligen Pfad, an dem unser Stream aufrufbar ist.

Jetzt ist es an der Zeit MediaMTX zu starten:

cd /opt/mediamtx
./mediamtx

Um den Videostream zu testen, öffnen wir auf einem anderen Rechner unseres Netzwerks den VLC-Mediaplayer. Medien -> Netzwerkstream öffnen. Als Netzwerkadresse geben wir: rtsp://{Raspi IP-Adresse}:8554/cam ein -> Wiedergabe. Das Live-Video unserer Raspi-Cam sollte nun zu sehen sein. 🤩

MediaMTX verfügt über eine eigene WebRTC-Implementierung. Das Öffnen von http://{Raspi IP-Adresse}:8889/cam in einem Browser sollte das Video ebenfalls wiedergeben. Auch HLS-Streams werden unter: http://{Raspi IP-Adresse}:8888/cam ausgeliefert. Nicht benötigte Protokolle, können in mediamtx.yml abgeschaltet werden.

Um MediaMTX nach einem Neustart des Raspis automatisch auszuführen, richten wir einen systemd-Service ein. Zuerst beenden wir MediaMTX mit Strg + C, dann legen wir die Datei /etc/systemd/system/mediamtx.service mit folgendem Inhalt an:

[Unit]
Wants=network.target

[Service]
ExecStart=/opt/mediamtx/mediamtx /opt/mediamtx/mediamtx.yml

[Install]
WantedBy=multi-user.target

Nun den Service aktivieren und starten:

sudo systemctl daemon-reload
sudo systemctl enable mediamtx
sudo systemctl start mediamtx

Nach Änderungen in der Konfiguration können wir MediaMTX jederzeit neu starten:

sudo systemctl restart mediamtx

Um den Videostream aus dem Internet zu erreichen, könnte nun DynDNS und ein Port-Forwarding im Router eingerichtet werden. Damit unser Stream von vielen Clients gleichzeitig gesehen werden kann, wollen wir im nächsten Abschnitt den Stream an Janus WebRTC Server weiterleiten.

Janus WebRTC Server

Janus WebRTC Server (oder Janus Gateway), ist ein Medien-Server von Meetecho. Mit seiner API ermöglicht er die Umsetzung umfangreicher WebRTC-Projekte wie Videokonferenzen, Streaming und Aufzeichnungen.

Wir wollen hier die absolute Minimalkonfiguration (nur Streaming-Plugin und Websocket-API) für die Verteilung unseres Raspi-Videostreams vorstellen. Voraussetzung ist ein Webserver mit SSL-Zertifikat (https), der über eine öffentliche IP-Adresse erreichbar ist. Für unser Beispiel verwenden wir Debian 12 mit dem Apache Webserver.

Zuerst installieren wir die benötigten Abhängigkeiten:

apt install libwebsockets-dev libjansson-dev libssl-dev libglib2.0-dev libsrtp2-dev libconfig-dev libnice-dev pkg-config git cmake libtool automake

Dann holen wir die Quellen und erzeugen das Konfigurationsscript.

git clone https://github.com/meetecho/janus-gateway.git
cd janus-gateway
sh autogen.sh

Minimalkonfiguration, nur Janus mit Streaming-Plugin und Websocket-API - ./configure --help listet alle Optionen - Doku:

./configure --prefix=/opt/janus --disable-all-plugins --disable-all-transports --disable-all-handlers --disable-all-loggers --enable-plugin-streaming --enable-websockets

Kompilieren:

make
make install

In /opt/janus/etc/janus befinden sich jetzt die Beispiel-Konfigurationsdateien. Wir entfernen jeweils '.sample' aus den Dateinamen. Hier die wichtigsten Einstellungen, manche Zeilen sind auszukommentieren (# entfernen):

janus.jcfg - generelle Konfiguration:

general: {
  log_to_file = "/opt/janus/janus.log"
  interface = "127.0.0.1"
}
nat: {
  ignore_mdns = true
}

janus.transport.websockets.jcfg - Websocket-API (Server) - soll lokal an Port 8188 lauschen:

general: {
  ws = true
  ws_port = 8188
  ws_ip = "127.0.0.1"
}

janus.plugin.streaming.jcfg - Streaming-Plugin Konfiguration - Wir können nach einem Backup den gesamten Inhalt der Datei mit Folgendem ersetzen:

h264Stream: {
  type = "rtp"
  id = 1
  description = "Unser Raspi-Stream"
  audio = false
  data = false
  video = true
  videobufferkf = true
  videoport = 8005
  videopt = 96
  videortpmap = "H264/90000"
  videofmtp = "profile-level-id=42c01f;packetization-mode=1"
}

Diese Konfiguration ist unter Verwendung verschiedener Namen, id's und Ports um zusätzliche Streams erweiterbar. Auch gleichzeitige 'Multistreams' lassen sich realisieren.

Um die -bald- auf Port 8188 lauschende, interne Websocket-API erreichbar zu machen, aktivieren wir diese Apache Proxy-Module:

a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel

Beispiel der Apache-Konfiguration:

<VirtualHost *:443>

  ServerName domain.org
  DocumentRoot /var/www/domain

  ProxyPass /janus-ws ws://127.0.0.1:8188 retry=0
  ProxyPassReverse /janus-ws ws://127.0.0.1:8188

  SSLCertificateFile /pfad/fullchain.pem
  SSLCertificateKeyFile /pfad/privkey.pem

</VirtualHost>

Websocket-Anfragen werden so von extern über https an die Janus-Websocket-Api durchgereicht und beantwortet.

Nach all der Konfiguration wird es Zeit, Apache neu zu starten:

systemctl restart apache2

Zurück zu unserem Raspi

Nun wollen wir den VideoStream von unserem Raspi an Janus senden.

Dazu installieren wir ffmpeg - DAS schweizer Taschenmesser rund um Video.

sudo apt install ffmpeg

In /opt/mediamtx/mediamtx.yml ergänzen wir die Zeilen 'runOnReady' und 'runOnReadyRestart'. '{Janus IP}' wird mit der IP-Adresse des Janus-Servers ersetzt. Das Port 8005 wurde in janus.plugin.streaming.jcfg unter 'videoport' festgelegt (siehe oben).

paths:
  cam:
    source: rpiCamera
    runOnReady: ffmpeg -i rtsp://localhost:8554/cam -c copy -f rtp rtp://{Janus IP}:8005
    runOnReadyRestart: yes

all_others:

ffmpeg nimmt den h264-Stream entgegen und leitet ihn an Janus weiter. Da keine Transkodierung stattfindet, bleibt die CPU-Last auf unserem PI erfreulich gering.

Da wir nur das rtsp-Protokoll nutzen, kann hls, webrtc, rtmp abgeschaltet werden.

Nach den Änderungen starten wir mediaMTX neu:

sudo systemctl restart mediamtx

Zurück zu Janus

Wir starten Janus:

cd /opt/janus/bin
./janus

In der Shell sollten wir nun '[h264Stream] New video stream!' lesen. Das ist unser Raspi-Stream! 🤗 Etwaige Warnungen können wir ignorieren.

Jetzt richten wir Janus als Service ein. Strg + C -> /etc/systemd/system/janus.service:

[Unit]
Description=Janus WebRTC Server
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/opt/janus/bin/janus -o
Restart=on-abnormal
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable janus
sudo systemctl start janus

Einbindung des Streams in eine Webseite:

Für die Einbindung sind zwei Javascript-Dateien erforderlich:

Hier eine minimale Den kompletten Quelltext für die Janus Streaming Demo findet ihr hier.

Wir hoffen, die Anleitung war nützlich! Bei Anregungen und Fragen schreibt uns: office@fatvalley.at


Happy streaming!