LabCodeHub öffentliche Ansicht
Anmelden
Küpper / ehc-tvwall öffentlich
Branch: main
ehc-tvwall / README.md
Verlauf Rohdaten
R Rüdiger Küpper feat: add silent boot script to enhance boot experience
461e563c vor 11 Tagen
README.md 378 Zeilen · 14.4 KB · Markdown

TV-Wall

Digitale Anzeigetafel für den Raspberry Pi: Bilder und Videos aus einem Ordner
laufen im Vollbild in Endlosschleife. Neue Inhalte kommen per Webinterface auf
das Gerät — der Pi spannt dafür ein eigenes WLAN auf, in das man sich mit Handy
oder Notebook einwählt.

  • Wiedergabe — Bilder je 5 Sekunden (einstellbar), Videos komplett, danach

von vorne. Der Ordner wird alle 10 Sekunden neu eingelesen, neue Dateien
landen automatisch hinten in der Playliste.

  • Webinterface — Hochladen per Fingertipp, Reihenfolge per Ziehen ändern,

Löschen, Pause/Weiter, Anzeigedauer umstellen.

  • Access Point — eigenes WLAN mit frei wählbarem Namen, damit sich mehrere

Geräte („TVWall-01“, „TVWall-02“, …) sauber unterscheiden lassen.

  • Autostart — ein systemd-Dienst, der beim Einschalten von selbst hochfährt.

Ein einziges Go-Programm ohne Fremdbibliotheken, dazu mpv als Abspieler.


Schnellstart

1. Auf dem Entwicklungsrechner bauen

make dist

Das erzeugt dist/tvwall-<version>.tar.gz mit fertigen Programmdateien für
64- und 32-Bit-Raspberry-Pi-Systeme.

2. Auf den Pi kopieren

scp dist/tvwall-*.tar.gz pi@raspberrypi.local:~
ssh pi@raspberrypi.local
tar xzf tvwall-*.tar.gz && cd tvwall-*

3. Namen vergeben und installieren

nano config/tvwall.conf      # AP_SSID und HOSTNAME für diesen Pi setzen
sudo ./install.sh

Der Installer richtet alles ein: Pakete, Benutzer, Medienordner, systemd-Dienst
und den Access Point. Danach ist das Gerät sofort einsatzbereit und startet bei
jedem Einschalten von allein.

Alternativ direkt auf dem Pi bauen: Go ≥ 1.21 installieren

(sudo apt install golang-go) und sudo ./install.sh im Quellverzeichnis

aufrufen — der Installer übersetzt dann selbst.

4. Benutzen

  1. Am Handy mit dem WLAN TVWall-01 verbinden (Passwort aus tvwall.conf).
  2. http://192.168.4.1 bzw. http://tvwall im Browser öffnen.
  3. Bilder und Videos hochladen, Reihenfolge ziehen — fertig.

Konfiguration

Alle Einstellungen stehen in /etc/tvwall/tvwall.conf. Nach Änderungen:

sudo systemctl restart tvwall
SchlüsselBedeutung
AP_SSIDName des WLANs — pro Pi eindeutig vergeben
AP_PASSWORDWLAN-Passwort, mindestens 8 Zeichen
AP_COUNTRYLändercode (DE); ohne ihn bleibt das WLAN aus
AP_IPAdresse des Pi im eigenen Netz (Standard 192.168.4.1)
AP_CHANNELWLAN-Kanal 1–11
CAPTIVE_PORTALyes = Handys öffnen die Seite von selbst
HOSTNAMEGerätename, auch als http://<name>.local erreichbar
WEB_PORTPort des Webinterface (Standard 80)
WEB_PASSWORDgesetzt = Webinterface fragt nach einem Passwort
MAX_UPLOAD_MBObergrenze je Upload-Vorgang
IMAGE_DURATIONAnzeigedauer für Bilder in Sekunden
MUTEyes = Videos ohne Ton
SCAN_INTERVALTakt, in dem der Ordner neu eingelesen wird
DISPLAY_MODEauto (empfohlen), drm oder desktop
RUN_USERBenutzer des Dienstes
MPV_GPU_APIopengl (Standard) oder vulkan/auto — siehe Fehlersuche
MPV_HWDECno (Standard, Software) oder auto-safe (Hardware, nur Pi 4)
STALL_TIMEOUTSekunden ohne Fortschritt, bevor ein Video übersprungen wird
MPV_EXTRA_ARGSzusätzliche mpv-Optionen, z. B. --video-rotate=90
STATE_DIRDatenverzeichnis, Medien liegen in <STATE_DIR>/media

Mehrere Geräte

Für jeden Pi nur zwei Zeilen anpassen:

AP_SSID="TVWall-02"
HOSTNAME="tvwall-02"

Danach sudo ./install.sh — oder auf einem bereits eingerichteten Gerät nach
dem Ändern der Datei:

sudo /opt/tvwall/scripts/setup-ap.sh

Alle Geräte dürfen dieselbe IP 192.168.4.1 verwenden: Man ist immer nur mit
einem WLAN gleichzeitig verbunden.

Bildausgabe: auto, drm oder desktop

Ein Bildschirm hat immer nur einen Herrn. Läuft ein Desktop, gehört ihm die
Grafikausgabe — mpv kommt dann nur über die Sitzung dieses Desktops daran und
nur als der Benutzer, dem die Sitzung gehört. Läuft kein Desktop, malt mpv
direkt über DRM/KMS. Genau darum geht es bei dieser Einstellung.

  • auto (empfohlen) — der Dienst sucht beim Start nach einer erreichbaren

Wayland- oder X11-Sitzung und nimmt sonst DRM. Der Installer erkennt zusätzlich
am Boot-Ziel, ob der Pi in den Desktop startet, und trägt bei Bedarf den
Desktop-Benutzer als RUN_USER ein.

  • drm — erzwingt die direkte Ausgabe. Richtig für Raspberry Pi OS Lite.

Der Installer schaltet dafür den Login-Prompt auf tty1 ab.

  • desktop — erzwingt die Ausgabe über die laufende Desktop-Sitzung. Dann

muss RUN_USER der Desktop-Benutzer sein (meist pi) und der Pi sich
automatisch anmelden: sudo raspi-configSystem Options → *Boot / Auto
Login* → Desktop Autologin.

Der Wayland-Socket heißt je nach Oberfläche wayland-0 oder wayland-1 — er
wird gesucht, nicht geraten. Welchen Weg der Dienst tatsächlich gewählt hat,
steht im Protokoll und unten im Webinterface.


Bedienung

Webinterface

BereichFunktion
HochladenDateien ziehen oder antippen; mehrere gleichzeitig möglich
WiedergabeZurück / Pause / Weiter, „Neu laden“ springt sofort in die aktuelle Playliste
EinstellungenAnzeigedauer für Bilder, Ton stummschalten
PlaylisteReihenfolge per Ziehen am Griff oder mit ↑ ↓, Löschen per 🗑
HakenOhne Haken bleibt die Datei liegen, wird auf der Wand aber übersprungen

Reihenfolge, Haken und Einstellungen bleiben über einen Neustart hinweg
erhalten (order.json, disabled.json, settings.json im Datenverzeichnis).

Ausgeblendete Einträge stehen weiter im Webinterface, sind grau hinterlegt und
mit „ausgeblendet" gekennzeichnet — sie landen nur nicht in der playlist.m3u,
die mpv abspielt. Die Änderung greift am nächsten Dateiübergang, ein laufendes
Video wird also nicht unterbrochen.

Ohne Webinterface

Dateien lassen sich auch direkt ablegen — per USB-Stick, scp oder
Netzwerkfreigabe:

scp urlaub.mp4 pi@tvwall-01.local:/var/lib/tvwall/media/

Sie tauchen beim nächsten Durchlauf (Standard: 10 Sekunden) automatisch in der
Playliste auf.

Unterstützte Formate

  • Bilder: jpg, jpeg, png, gif, bmp, webp, tif, tiff
  • iPhone-Fotos: heic und heif werden beim Hochladen automatisch in JPEG

umgewandelt (dafür wird ffmpeg gebraucht)

  • Videos: mp4, m4v, mov, mkv, avi, webm, mpg, mpeg, wmv, flv, ts, 3gp, ogv

Alles andere wird beim Hochladen abgelehnt und im Ordner ignoriert.


Betrieb

sudo /opt/tvwall/scripts/diagnose.sh   # Selbsttest bei Problemen
systemctl status tvwall          # Zustand
journalctl -u tvwall -f          # Protokoll mitlesen
sudo systemctl restart tvwall    # neu starten
sudo systemctl disable tvwall    # Autostart abschalten

Aktualisieren: neues Paket auspacken und sudo ./install.sh erneut ausführen.
Eine vorhandene /etc/tvwall/tvwall.conf bleibt dabei unangetastet; die neue
Fassung landet als tvwall.conf.neu daneben.

Entfernen:

sudo /opt/tvwall/scripts/uninstall.sh          # Medien bleiben erhalten
sudo /opt/tvwall/scripts/uninstall.sh --purge  # alles löschen

Wenn etwas klemmt

Der Bildschirm bleibt schwarz.
Zuerst den Selbsttest laufen lassen — er prüft Dienst, Benutzer, Gruppen,
Bildschirm, Medien, Webinterface und Access Point und nennt die nötigen Schritte:

sudo /opt/tvwall/scripts/diagnose.sh

Die beiden häufigsten Ursachen:

  1. Ein Desktop läuft, der Dienst aber unter dem falschen Benutzer. Die

Desktop-Sitzung von pi liegt in /run/user/1000 und ist für den Benutzer
tvwall schlicht nicht zugänglich. Abhilfe: in /etc/tvwall/tvwall.conf
RUN_USER="pi" und DISPLAY_MODE="desktop" setzen, dann
sudo /opt/tvwall/install.sh --no-ap.

  1. DISPLAY_MODE="drm" auf einem Desktop-System. Der Compositor hält den

Bildschirm bereits, mpv kommt nicht daran. Abhilfe: DISPLAY_MODE="auto"
oder in raspi-config auf Console Autologin umstellen.

Zum Prüfen, ob mpv überhaupt ein Bild bekommt (Dienst vorher mit
sudo systemctl stop tvwall anhalten):

# mit Desktop
sudo -u pi XDG_RUNTIME_DIR=/run/user/1000 mpv --fullscreen /var/lib/tvwall/media/<datei>
# ohne Desktop
sudo -u tvwall mpv --vo=gpu --gpu-context=drm --fullscreen /var/lib/tvwall/media/<datei>

Das WLAN taucht nicht auf.

nmcli connection show --active     # läuft tvwall-ap?
rfkill list                        # Funk gesperrt?
sudo /opt/tvwall/scripts/setup-ap.sh

Häufigste Ursache: Der Pi ist noch mit einem anderen WLAN verbunden. Eine
Schnittstelle kann nicht gleichzeitig Client und Access Point sein —
andere WLAN-Verbindungen mit nmcli connection modify <name> connection.autoconnect no
abschalten. Zweithäufigste Ursache: fehlender Ländercode (AP_COUNTRY).

Webinterface nicht erreichbar.
Zuerst http://192.168.4.1 probieren — Namen wie tvwall.local funktionieren
nicht auf allen Handys. Läuft der Dienst? systemctl status tvwall.

Das Bild bleibt nach einigen Wechseln stehen, obwohl das Webinterface
weiterzählt.

Das ist der Grund für die Voreinstellung MPV_GPU_API="opengl". Über Vulkan
baut libplacebo bei jedem Bildwechsel die Swapchain neu auf und läuft nach rund
neun Wechseln in VK_ERROR_OUT_OF_HOST_MEMORY. mpv läuft dann weiter und meldet
auch weiter Dateiwechsel — nur gemalt wird nichts mehr. Im Journal steht:

[vo/gpu/libplacebo] vk->CreateSwapchainKHR(...): VK_ERROR_OUT_OF_HOST_MEMORY
[vo/gpu/libplacebo] Failed (re)creating swapchain!

Nachgemessen auf einem Pi 5 (Wayland/labwc, mpv 0.40), 20 Bildwechsel:

RendererSwapchain-Fehler
--vo=gpu (Vulkan)24
--vo=gpu --gpu-api=opengl0
--vo=gpu-next (Vulkan)84

Dasselbe galt für Videos: Mit Vulkan brach die Wiedergabe nach ein bis zwei
Sekunden ab, mit OpenGL lief derselbe Clip vollständig durch. diagnose.sh
prüft das mit.

Ein Video bleibt nach ein paar Sekunden stehen.
Zuerst MPV_GPU_API="opengl" prüfen (siehe oben), dann MPV_HWDEC="no". Der
Raspberry Pi 5 hat keinen Hardware-Dekoder für H.264 mehr; mit auto-safe
läuft ein Video dort ein bis zwei Sekunden und friert dann ein — genau so lange,
wie der bereits gefüllte Puffer reicht. Zum Gegenprüfen hilft der direkte
Vergleich, weil mpv von sich aus --hwdec=no verwendet:

sudo systemctl stop tvwall
mpv --hwdec=no        --fullscreen /var/lib/tvwall/media/<datei>   # läuft
mpv --hwdec=auto-safe --fullscreen /var/lib/tvwall/media/<datei>   # friert ein
sudo systemctl start tvwall

Bleibt es dabei, misst dieses Skript jede Variante einzeln durch und nennt die
verantwortliche Option — statt zu raten:

sudo /opt/tvwall/scripts/bisect-mpv.sh /var/lib/tvwall/media/<datei>

Was in der Datei steckt, zeigt diagnose.sh oder direkt:

ffprobe -hide_banner /var/lib/tvwall/media/<datei>

Ist das Material breiter als 1920 Pixel (Handyvideos sind oft 4K), hilft nur
Herunterrechnen — am besten auf dem Rechner, nicht auf dem Pi:

ffmpeg -i gross.mov -vf scale=1920:-2 -c:v libx264 -preset slow -crf 23 \
       -c:a aac -movflags +faststart klein.mp4

Die Wiedergabe bleibt dabei nicht hängen: Läuft ein Video STALL_TIMEOUT
Sekunden (Standard 30) nicht weiter, wird es übersprungen und die Schleife
läuft weiter. Im Webinterface steht dann, welche Datei betroffen war.

Kein Ton.
Ausgabegerät prüfen (mpv --audio-device=help) und passend in
MPV_EXTRA_ARGS="--audio-device=..." eintragen. Bei HDMI-Ton hilft oft
--audio-device=alsa/sysdefault:CARD=vc4hdmi0.


Aufbau

cmd/tvwall/main.go        Start, Signalbehandlung, periodischer Ordner-Durchlauf
internal/config/          tvwall.conf lesen, Laufzeit-Einstellungen speichern
internal/playlist/        Ordner einlesen, Reihenfolge merken, playlist.m3u schreiben
internal/mpv/             JSON-IPC-Verbindung zu mpv
internal/player/          mpv starten, überwachen, Dateien einzeln weiterschalten
internal/web/             HTTP-Schnittstelle und Oberfläche (eingebettet)
systemd/                  Vorlagen für den Dienst (drm / desktop)
internal/player/display.go  Wayland-/X11-/DRM-Erkennung
scripts/setup-ap.sh       Access Point per nmcli
scripts/diagnose.sh       Selbsttest bei Problemen
scripts/console-mode.sh   Desktop abschalten, direkt in die Anzeige booten
scripts/set-splash.sh     eigenes Logo als Startbildschirm setzen
scripts/silent-boot.sh    Textkonsole beim Starten unterdruecken
scripts/bisect-mpv.sh     misst, welche mpv-Option einen Haenger ausloest
install.sh                Installation auf dem Pi

Ein paar Entscheidungen, die vielleicht nicht offensichtlich sind:

  • mpv spielt Bilder und Videos aus einer gemeinsamen Playliste. Kein

Umschalten zwischen zwei Programmen, keine Lücke am Übergang.

  • Die Playliste wird zwischen zwei Dateien getauscht, nicht mittendrin: Ein

Upload unterbricht kein laufendes Video. Wer nicht warten will, drückt
„Neu laden“.

  • Die Oberfläche kommt ohne externe Bibliotheken aus und ist ins Programm

eingebettet. Am Access Point gibt es kein Internet — alles, was von einem CDN
nachgeladen werden müsste, wäre dort tot.

  • mpv rendert über OpenGL, nicht über Vulkan. Auf dem Raspberry Pi 5 baut

die Vulkan-Anbindung von libplacebo bei jedem Bildwechsel die Swapchain neu
auf und läuft dabei nach rund neun Wechseln aus dem Speicher — der Bildschirm
friert ein, während intern alles weiterläuft. Siehe Fehlersuche.

  • Uploads landen erst in einer temporären Datei und werden nach vollem

Empfang umbenannt. So gerät keine halbe Datei in die Wiedergabe.

Web-Schnittstelle

WegMethodeZweck
/api/stateGETPlayliste, Zustand, Einstellungen
/api/uploadPOSTDateien hochladen (multipart)
/api/orderPOST{"order":["a.jpg","b.mp4"]}
/api/deletePOST{"name":"a.jpg"}
/api/enabledPOST{"name":"a.jpg","enabled":false} — aus der Wiedergabe nehmen
/api/settingsPOST{"image_duration":5,"mute":false}
/api/controlPOST{"action":"next|prev|pause|reload|restart|rescan"}
/thumb/<name>GETVorschaubild (per ffmpeg erzeugt, zwischengespeichert)
/media/<name>GETOriginaldatei

Lokal ausprobieren

Ohne Pi, nur die Oberfläche (kein mpv nötig):

make run     # http://localhost:8080