15 KiB
Raspberry Pi NDI Gateway
Work in Progress – erste öffentliche Veröffentlichung
Ein Installationsskript für einen Raspberry Pi 4 (ARM64) mit Raspberry Pi OS / Debian 13 „Trixie“. Das Projekt richtet einen headless NDI-Gateway mit GStreamer ein:
- USB-HDMI-Capture → NDI
- NDI → HDMI über DRM/KMS
- optionales Capture-Audio → NDI
Der aktuelle Stand ist ausdrücklich nicht als vollständig getestete oder produktionsreife Lösung zu verstehen. Siehe Bekannte Einschränkungen.
Funktionsumfang des aktuellen Skripts
| Bereich | Implementierter Stand |
|---|---|
| Betriebssystem | Debian 13 / Raspberry Pi OS Trixie, ARM64 |
| GStreamer | Debian-/Raspberry-Pi-OS-Systempakete |
| NDI-Plugin | gst-plugin-ndi aus gst-plugins-rs, standardmäßig Tag 0.14.5 |
| NDI-Runtime | Vorhandene NDI-6-Runtime wird gesucht; andernfalls wird ein SDK-Archiv benötigt |
| Capture-Video | Automatische oder manuelle V4L2-Geräteauswahl |
| Capture-Formate | MJPEG und YUYV, sofern vom Gerät angeboten |
| Capture-Audio | Optional; automatische oder manuelle ALSA-Geräteauswahl |
| NDI-Empfang | NDI-Quelle per Name oder direkter IP:Port-Adresse |
| HDMI-Video | Direkte Ausgabe über kmssink / DRM-KMS, ohne Desktop |
| HDMI-Audio | Noch nicht implementiert; empfangenes NDI-Audio wird aktuell verworfen |
| Dienste | ndi-capture.service und ndi-display.service |
| Diagnose | /opt/ndi-pi/bin/ndi-pi-diagnose |
Architektur
Capture: USB-Capture → NDI
USB-HDMI-Capture
├── V4L2-Video
│ ├── MJPEG → jpegdec ───────────┐
│ └── YUYV → videoconvert ───────┤
│ ▼
│ kurze Queue
│ │
└── USB-Audio → ALSA → convert/resample
│
▼
ndisinkcombiner
│
ndisink
│
NDI OUT
Wenn kein passendes Capture-Audiogerät gefunden wird oder ENABLE_AUDIO=false gesetzt ist, wird eine Video-only-Pipeline gestartet. Die Audiozuordnung erfolgt anhand des USB-Gerätepfads; wenn keine eindeutige Übereinstimmung gefunden wird, kann derzeit ersatzweise das erste gefundene USB-Audiogerät gewählt werden.
Display: NDI → HDMI
NDI IN
│
ndisrc
│
ndisrcdemux
│
├── Video → queue → videoscale → kmssink → HDMI
│
└── Audio → queue → fakesink (wird verworfen)
Die Videoausgabe verwendet DRM/KMS und benötigt daher keine Desktop-Umgebung wie X11 oder Wayland. Wenn die Live-Pipeline beendet wird, versucht der Dienst einen schwarzen Standby-Bildschirm mit Statusanzeige zu starten und die NDI-Verbindung erneut aufzubauen.
Voraussetzungen
- Raspberry Pi 4 mit 64-Bit-ARM-System
- Raspberry Pi OS / Debian 13 „Trixie“
- Netzwerkverbindung; Ethernet wird empfohlen
- USB-HDMI-Capture-Gerät mit Linux-V4L2-Unterstützung
- HDMI-Display am Pi für die lokale Ausgabe
- NDI-kompatible Gegenstelle im Netzwerk
- Root-/sudo-Rechte für die Installation
Das Skript prüft Architektur und Debian-Codename. Andere Raspberry-Pi-Modelle, Betriebssystemversionen oder 32-Bit-Systeme sind nicht als unterstützt anzusehen.
Installation
- Repository auf dem Raspberry Pi klonen.
- Ein offizielles NDI-SDK-Archiv lokal bereitstellen oder eine Download-URL angeben.
- Installationsskript mit Root-Rechten ausführen.
Beispiel mit lokal heruntergeladenem SDK-Archiv:
sudo NDI_SDK_TARBALL=/pfad/zum/ndi-sdk.tar.gz ./install-trixie-ndi-pi-v18.sh
Alternativ kann die URL über die Umgebungsvariable übergeben werden:
sudo NDI_SDK_URL="https://<NDI-SDK-Download-URL>" ./install-trixie-ndi-pi-v18.sh
<NDI-SDK-Download-URL> ist durch die aktuelle Download-URL des NDI-Herstellers zu ersetzen. Die URL ist absichtlich nicht im Skript fest hinterlegt.
Wenn die NDI-6-Runtime bereits an einem der vom Skript geprüften Orte installiert ist, wird kein SDK-Archiv benötigt:
/usr/local/lib/usr/lib/aarch64-linux-gnu
Das Skript installiert Systemabhängigkeiten, baut das NDI-GStreamer-Plugin und legt Konfiguration, Hilfsskripte und systemd-Units an. Es aktiviert und startet anschließend beide Dienste.
Hinweis: Das Installationsskript sollte vor dem Einsatz geprüft werden. Es verändert Systempakete, installiert Bibliotheken und schreibt Dateien unter
/opt/ndi-pi,/etcund/etc/systemd/system.
Warum GStreamer aus den Distributionspaketen kommt
GStreamer selbst wird nicht aus einem Git-Repository gebaut. Das Skript installiert die GStreamer-Komponenten aus den Debian-/Raspberry-Pi-OS-Paketen. Das zusätzliche NDI-Plugin wird separat aus gst-plugins-rs gebaut.
Standardmäßig verwendet das Skript den Tag 0.14.5:
Debian / Raspberry Pi OS GStreamer
│
└── gst-plugin-ndi (gst-plugins-rs 0.14.5)
│
└── NDI 6 Runtime
Der Plugin-Tag kann über NDI_GST_TAG überschrieben werden:
sudo NDI_GST_TAG=0.14.5 NDI_SDK_TARBALL=/pfad/zum/ndi-sdk.tar.gz ./install-trixie-ndi-pi-v18.sh
Konfiguration
Die zentrale Konfigurationsdatei lautet:
/etc/ndi-pi.conf
Eine neue Installation legt sie mit folgenden wesentlichen Standardwerten an:
PI_NAME=<HOSTNAME>
NDI_CAPTURE_NAME=<HOSTNAME>-Capture
NDI_DISPLAY_SOURCE=PC01-Capture
NDI_DISPLAY_ADDRESS=auto
NDI_USE_DIRECT_ADDRESS=true
CAPTURE_DEVICE=auto
CAPTURE_WIDTH=1920
CAPTURE_HEIGHT=1080
CAPTURE_FPS=30
CAPTURE_FORMAT=MJPEG
CAPTURE_AUTO_FALLBACK=true
CAPTURE_QUEUE_BUFFERS=2
ENABLE_AUDIO=true
CAPTURE_AUDIO_DEVICE=auto
CAPTURE_AUDIO_RATE=48000
CAPTURE_AUDIO_CHANNELS=2
ENABLE_HDMI_AUDIO=false
HDMI_AUDIO_DEVICE=auto
KMS_DRIVER=vc4
KMS_CONNECTOR_ID=auto
NDI_MAX_QUEUE=0
DISPLAY_WIDTH=1920
DISPLAY_HEIGHT=1080
DISPLAY_FPS=60
<HOSTNAME> steht hier nur als Platzhalter für den vom Installer ermittelten Hostnamen. Die tatsächliche Datei enthält konkrete Werte.
Wichtige Einstellungen
| Einstellung | Bedeutung |
|---|---|
NDI_CAPTURE_NAME |
Name der vom Pi gesendeten NDI-Quelle |
NDI_DISPLAY_SOURCE |
Name der NDI-Quelle, die der Pi empfangen soll |
NDI_DISPLAY_ADDRESS |
auto für mDNS-Auflösung oder feste Adresse im Format IP:Port |
NDI_USE_DIRECT_ADDRESS |
Bei true wird die aufgelöste bzw. konfigurierte IP:Port-Adresse für ndisrc verwendet |
CAPTURE_DEVICE |
auto oder ein konkreter V4L2-Gerätepfad |
CAPTURE_WIDTH, CAPTURE_HEIGHT, CAPTURE_FPS |
Bevorzugter Capture-Modus |
CAPTURE_FORMAT |
MJPEG, YUYV oder auto |
CAPTURE_AUTO_FALLBACK |
Erlaubt die Suche nach einem anderen unterstützten Modus |
CAPTURE_QUEUE_BUFFERS |
Anzahl der Videobuffer in der Capture-Queue |
ENABLE_AUDIO |
Aktiviert/deaktiviert Capture-Audio → NDI |
CAPTURE_AUDIO_DEVICE |
auto oder ALSA-Gerät, z. B. plughw:2,0 |
KMS_DRIVER |
DRM/KMS-Treiber, Standard vc4 |
KMS_CONNECTOR_ID |
auto oder eine feste DRM-Connector-ID |
DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_FPS |
Auflösung und Framerate des Standby-Bildes |
NDI_MAX_QUEUE |
NDI-Empfangsqueue; Standardwert 0 |
ENABLE_HDMI_AUDIO und HDMI_AUDIO_DEVICE sind derzeit vorbereitete Konfigurationswerte, werden von der aktuellen Display-Pipeline aber noch nicht umgesetzt. Sie einzuschalten aktiviert daher keine HDMI-Audioausgabe.
Bestehende Konfigurationen werden vom Installer ergänzt, ohne vorhandene Werte generell zu überschreiben. Bei älteren Konfigurationsdateien sollten die benötigten Capture-Werte kontrolliert und gegebenenfalls ergänzt werden.
Capture-Geräteauswahl und Videoformate
Mit:
CAPTURE_DEVICE=auto
untersucht das Skript /dev/video* und berücksichtigt Geräte mit V4L2-Video-Capture-Funktion und einem unterstützten Modus.
Für eine feste Installation kann ein konkreter Pfad eingetragen werden, vorzugsweise ein stabiler Symlink:
CAPTURE_DEVICE=/dev/v4l/by-id/<GERAETEPFAD>
Die Modusauswahl berücksichtigt die tatsächlich vom Gerät gemeldeten Formate. Die gewünschte Kombination aus Auflösung und Framerate wird zuerst versucht. Wenn CAPTURE_AUTO_FALLBACK=true gesetzt ist, folgt eine festgelegte Fallback-Liste.
Wichtig zur Formatpriorität: Bei CAPTURE_FORMAT=auto ist die aktuelle Fallback-Reihenfolge YUYV vor MJPEG. Auch die Gerätebewertung bevorzugt YUYV. Das unterscheidet sich von einer MJPEG-first-Strategie. Bei einer neuen Installation steht CAPTURE_FORMAT=MJPEG als Standard in der Konfiguration; damit wird die Auswahl auf MJPEG beschränkt, sofern ein passender Modus vorhanden ist und ein Fallback nicht durch die Formatvorgabe ausgeschlossen wird.
MJPEG wird mit jpegdec dekodiert. Der aktuelle Code verwendet bewusst nicht v4l2jpegdec. YUYV wird über videoconvert in UYVY konvertiert, bevor es an den NDI-Sink geht.
Audio
Capture-Audio → NDI
Bei ENABLE_AUDIO=true versucht das Skript, ein ALSA-Gerät zu finden, das zum ausgewählten USB-Capture-Gerät gehört. Alternativ kann ein ALSA-Gerät fest vorgegeben werden:
CAPTURE_AUDIO_DEVICE=plughw:2,0
Die automatische Zuordnung ist heuristisch und sollte mit der konkreten Capture-Hardware überprüft werden. Wird kein Gerät gefunden, startet die Capture-Pipeline als Video-only.
NDI-Audio → HDMI
Diese Richtung ist im aktuellen Skript noch nicht implementiert. Der Audio-Pad von ndisrcdemux wird derzeit an fakesink angeschlossen und damit verworfen. Es gibt aktuell keine ALSA-Wiedergabepipeline für den NDI-Ton.
NDI-Discovery und Netzwerk
Der Display-Dienst verwendet standardmäßig:
NDI_DISPLAY_SOURCE=PC01-Capture
NDI_DISPLAY_ADDRESS=auto
NDI_USE_DIRECT_ADDRESS=true
Bei auto versucht das Skript, den NDI-Dienst über Avahi/mDNS (_ndi._tcp) aufzulösen und die ermittelte IP-Adresse samt Port an ndisrc zu übergeben. Eine feste Adresse kann so angegeben werden:
NDI_DISPLAY_ADDRESS=192.168.1.50:5961
Der tatsächliche Port ist abhängig von der NDI-Quelle und muss passend ermittelt werden. Wenn keine direkte Adresse verfügbar ist, verwendet der initiale Start ndi-name als Fallback. Die Wiederverbindungslogik ist derzeit noch eingeschränkt; siehe Bekannte Einschränkungen.
Für Discovery über VLAN- oder Subnetzgrenzen hinweg kann eine gesonderte NDI-Discovery-Server-Konfiguration erforderlich sein. Das wird vom Installationsskript nicht eingerichtet.
systemd-Dienste und Logs
Es werden zwei getrennte Dienste angelegt:
ndi-capture.service
ndi-display.service
Status prüfen:
systemctl status ndi-capture
systemctl status ndi-display
Logs verfolgen:
journalctl -u ndi-capture -f
journalctl -u ndi-display -f
Beide Dienste verwenden Restart=always und aktuell RestartSec=1.
Nach einer Änderung an /etc/ndi-pi.conf:
sudo systemctl restart ndi-capture ndi-display
Diagnose
Das Diagnoseprogramm liegt unter:
sudo /opt/ndi-pi/bin/ndi-pi-diagnose
Es sammelt unter anderem:
- Kernel- und Betriebssysteminformationen
- GStreamer-Version und ausgewählte Plugin-Informationen
- V4L2-Geräte und gemeldete Capture-Formate
- ALSA-Aufnahme- und Wiedergabegeräte
- DRM-Geräte und Connector-Status
- NDI-Konfiguration und NDI/mDNS-Discovery
- systemd-Status und letzte Service-Logs
Für Fehlerberichte ist die vollständige Ausgabe hilfreich. Zugangsdaten oder andere private Netzwerkinformationen sollten vor dem Veröffentlichen entfernt werden.
Bekannte Einschränkungen
Der folgende Abschnitt beschreibt bewusst den Stand des aktuellen Skripts und ist Teil der WIP-Kennzeichnung.
- NDI-Audio wird am HDMI-Ausgang nicht wiedergegeben. Der Empfangs-Audiozweig endet aktuell in
fakesink. - Automatische USB-Audiozuordnung ist nicht garantiert. Wenn die Zuordnung zum Video-Gerät nicht gelingt, kann ein anderes erstes USB-Audiogerät als Fallback ausgewählt werden.
- Wiederverbindung nach NDI-Ausfall ist eingeschränkt. Die Standby-Schleife prüft eine direkte IP:Port-Adresse. Wenn nur der Namens-Fallback aktiv ist oder mDNS die Quelle nicht auflösen kann, wird die Quelle nicht in allen Fällen erneut gefunden.
- Signalbehandlung des Display-Helfers muss weiter getestet werden. Das aktuelle Trap räumt den Standby-Prozess auf; das Verhalten beim Beenden durch systemd sollte auf dem Zielgerät überprüft werden.
- Ältere Konfigurationsdateien benötigen Prüfung. Die Migration ergänzt einige Schlüssel, aber nicht alle möglichen Capture-Parameter. Fehlende Werte wie
CAPTURE_WIDTHoderCAPTURE_FPSkönnen bei älteren Konfigurationen problematisch sein. - NDI-Runtime-Pfad in systemd: Der Installer erkennt die Runtime auch unter
/usr/lib/aarch64-linux-gnu; die erzeugten systemd-Units setzen aktuell jedoch festNDI_RUNTIME_DIR_V6=/usr/local/lib. Bei einer Runtime-Installation im Multiarch-Verzeichnis muss das geprüft werden. - Keine vollständige Hardware-/Laufzeitvalidierung durch Syntaxprüfung: Ein erfolgreicher Bash-Syntaxcheck bestätigt weder GStreamer-Pipeline-Negotiation noch NDI-Discovery, DRM/KMS-Ausgabe oder das Verhalten einer konkreten Capture-Karte.
Weitere bekannte Entwicklungsaufgaben sind eine umfassendere Plugin-Prüfung, robustere Installer-Rollback-Strategien und eine Prüfung des SDK-Archivs anhand eines verifizierten Hashes bzw. einer Signatur.
Sicherheit und Lizenzhinweise
Das NDI SDK bzw. die NDI-Runtime wird vom NDI-Hersteller bereitgestellt und unterliegt dessen Lizenz- und Distributionsbedingungen. Das SDK-Archiv und die Runtime-Bibliotheken sollten nicht ohne Prüfung dieser Bedingungen in ein öffentliches Repository eingecheckt oder weiterverteilt werden.
Das Repository enthält das Installationsskript und die Projektdateien; Nutzer müssen die NDI-Runtime entsprechend den geltenden Herstellerbedingungen selbst beziehen bzw. bereitstellen.
Das Installationsskript entpackt ein bereitgestelltes SDK-Archiv mit Root-Rechten. Verwende nur ein vertrauenswürdiges Archiv aus einer offiziellen Quelle. Eine automatisierte Hash-/Signaturprüfung des Archivs ist im aktuellen Skript noch nicht implementiert.
Projektstatus
Dieses Projekt wird aktiv entwickelt. Hardwarekombinationen, Capture-Modi, NDI-Versionen und HDMI-Ausgabeverhalten können sich unterscheiden. Rückmeldungen mit Diagnoseausgabe, Pi-Modell, OS-Version und genauer Capture-Hardware sind willkommen.
Vor einem produktiven Einsatz sind Tests mit der eigenen Hardware und Netzwerkinfrastruktur erforderlich.