- HTML 50.2%
- Go 46.2%
- Shell 1.8%
- PowerShell 0.8%
- Makefile 0.5%
- Other 0.5%
playerui zeigt via nowMs()=Date.now()+Offset in allen Sekunden-Widgets und der Sync die identische Server-Zeit statt der eigenen Geraeteuhr. Der Offset kommt aus X-Server-Now: - sync.go: liest X-Server-Now beim Manifest-Poll (RTT/2-korrigiert), merkt den Offset atomar; ServerNowMs() liefert die frische Schaetzung - server.go: stempelt X-Server-Now frisch auf /manifest.json (aus dem gemerkten Offset), damit die zwischengespeicherte Zeit nicht veraltet - playerui/index.html: nowMs()/syncClockOffset(); alle Zeitlesestellen + clockAlign + syncClock-elapsed + Video-Sync auf nowMs(); poll liest Header |
||
|---|---|---|
| .forgejo/workflows | ||
| cmd/agent | ||
| deploy | ||
| internal | ||
| playerui | ||
| .dockerignore | ||
| .gitignore | ||
| CHANGELOG.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| go.mod | ||
| Makefile | ||
| README.md | ||
signagetools-player
On-Device-Player für signagetools. Läuft auf dem Anzeigegerät (Raspberry Pi / Mini-PC) und zeigt das vom Server zugewiesene Layout an — auch offline.
Design- und Architektur-Dokumente liegen zentral im Haupt-Repo
signagetools(siehedocs/). Dieses Repo enthält nur den Player.
Rolle
- Meldet sich per Token am Server an (Pairing → Token).
- Pull-Modell: zieht regelmäßig sein Manifest (JSON: zugewiesenes Layout + Medienliste mit Hashes) vom Server.
- Lädt nur geänderte Medien (Hash-Abgleich) in einen lokalen Cache.
- Startet Chromium im Kiosk-Modus gegen eine lokal ausgelieferte Player-UI.
- Läuft bei Netzausfall offline weiter (letzter gültiger Stand).
- Meldet Status zurück (zuletzt gesehen, aktueller Inhalt, Fehler).
Player-Optionen im Überblick
Es gibt mehrere Wege, einen Bildschirm zu bespielen — vom „Browser aufmachen" bis zur robusten Dauerinstallation. Alle nutzen dasselbe Modell: das Gerät koppelt sich (Kopplungscode → im Builder unter ▶ Player → Verwaltung freigeben) und wird dann mit ▶ Spielen oder über den Zeitplan bespielt.
| Option | Installation | Vollbild/Kiosk | Offline-Cache | Am besten für |
|---|---|---|---|---|
Web-Player im Browser (/play) |
keine | Tap / „Zum Home-Bildschirm" (PWA) | nur Browser-Cache (schwächer) | iPads/Tablets/Smart-TVs, schnelle & temporäre Screens |
| Nativer lokaler Player (Laptop/Mini-PC) | Binary + Autostart (deploy/) |
eigener Kiosk-Browser, Auto-Neustart | voller Platten-Cache | dauerhafte, robuste Screens ohne Docker (Win/Linux/macOS) |
| Nativer Player auf Raspberry Pi | Binary (make build-pi) + -kiosk |
eigener Kiosk-Browser | voller Platten-Cache | klassische Kiosk-Appliance |
| Docker (headless, „Variante A") | docker compose up |
Browser/TV zeigt :4000 an |
Volume-Cache | Server/Mini-PC mit Docker, zentrale Updates |
Kurz entscheiden:
- Schnell / temporär / Tablet → Web-Player (
https://<server>/play), nichts zu installieren. - Dauerhaft & robust auf einem Laptop/Mini-PC → nativer lokaler Player (siehe
deploy/) — offline-fest, kein Docker. - Du betreibst ohnehin Docker → Container-Variante (headless).
Zwei Betriebsarten (für native/Docker-Player und den Web-Player):
- Kopplung (empfohlen): ohne festes Ziel starten → Kopplungscode → im Builder
freigeben. Vollwertiges Flottengerät (Zeitplan, Wartung, Sofort-Nachrichten,
Screenshots, Videowand). Token bleibt im
DATA_DIRbzw.localStorage. - Festes Ziel (ohne Kopplung):
LAYOUT_ID=(festes Layout) oderSCREEN_ID=(zeitgesteuerter Screen-Key) — praktisch für schnelle Kioske.
Details: robuster lokaler Player → deploy/README.md;
Web-Player & Server-Betrieb → docs/DEPLOYMENT.md im Server-Repo (§12 Web-Player,
§5/§6 Player koppeln & zuweisen).
Ersteinrichtung im Browser (Windows, ohne Flags)
Für einen Windows-Mini-PC ist kein Kommandozeilen-Flag nötig:
- Aktuelle
sigplayer-windows-amd64.exeaus den Releases dieses Repos herunterladen (Asset am jeweiligenv*-Tag; die CI baut alle Plattformen: Linux amd64/arm64, Windows, macOS amd64/arm64). - Doppelklick → der Player öffnet automatisch den Browser auf
http://localhost:4000mit einer Einrichtungsseite. Öffnet er nicht von selbst (ältere.exe), die Adresse manuell aufrufen. - Server-Adresse eintragen und speichern → der Player zeigt einen Kopplungscode, den man im Builder unter Geräte freigibt.
- Die Eingaben werden in
player.jsonim Datenverzeichnis gespeichert; beim nächsten Start verbindet sich der Player direkt, ohne Eingabe.
Für den echten Dauerbetrieb -kiosk verwenden (Vollbild, eigener Browserstart)
— am einfachsten per deploy/windows/install.ps1 als Autostart.
Vollständiger Ablauf inkl. Freigabe und Layout-Zuweisung:
docs/onboarding.md im
Server-Repo.
Warum ein eigenes Repo
- Eigenes Deployable auf fremder Hardware, eigener Release-Zyklus.
- Wird an Geräte verteilt; soll klein und unabhängig bleiben.
- Braucht das Admin-Frontend/den Builder nicht — der lebt im Server-Repo.
Geplante Struktur
signagetools-player/
cmd/agent/ # Einstiegspunkt des Agenten (Go)
internal/
sync/ # Manifest ziehen, Hash-Abgleich, Download, atomarer Umschalt
cache/ # lokaler Medien-/Layout-Cache auf Platte
kiosk/ # Chromium-Kiosk starten/überwachen (Watchdog)
api/ # Status-Meldung an Server, Enrollment
playerui/ # lokal ausgelieferte Player-Seite (rendert das Layout)
configs/ # Beispiel-Konfiguration (Server-URL, Token-Pfad)
Tech
- Go — ein statisches Binary, ideal für ARM (Pi) und x86 (Mini-PC).
- Player-UI: schlankes HTML/JS, das ein gecachtes Manifest rendert.
Ausführen
make build
# Empfohlen: Enrollment-Modus (ohne -screen/-layout).
# Der Agent registriert sich, zeigt einen Kopplungscode auf dem Bildschirm und
# wartet auf Freigabe im Builder unter „Geräte".
./bin/agent -server http://<server>:8080 -addr :4000
# Legacy/ohne Auth: festes Layout oder Screen-Key (kein Token nötig).
./bin/agent -server http://<server>:8080 -screen foyer -addr :4000
./bin/agent -server http://<server>:8080 -layout <LAYOUT_ID> -addr :4000
# Kiosk auf dem Pi zusätzlich: -kiosk (startet Chromium auf http://localhost:4000)
Konfiguration auch per Env: SERVER_URL, SCREEN_ID, LAYOUT_ID, PORT,
DATA_DIR, POLL_INTERVAL, KIOSK, CHROMIUM_BIN. Cross-Compile für Pi:
make build-pi.
Robuster lokaler Player (Laptop/Mini-PC — Windows · Linux · macOS, ohne Docker)
Turnkey-Autostart-Skripte, damit ein Gerät nach dem Einschalten von selbst im Vollbild-Kiosk hochkommt (Auto-Neustart bei Absturz, Browser wird automatisch erkannt — Chrome/Chromium/Edge/Brave). Ein Repo, alle Systeme:
make dist # native Binaries: dist/sigplayer-<os>-<arch>[.exe]
Einrichten (Server-URL angeben):
# Linux
SERVER_URL=https://signage.example.tld sh deploy/linux/install.sh ./sigplayer-linux-amd64
# macOS
SERVER_URL=https://signage.example.tld sh deploy/macos/install.sh ./sigplayer-macos-arm64
# Windows (PowerShell)
.\deploy\windows\install.ps1 -ServerUrl https://signage.example.tld -Binary .\sigplayer-windows-amd64.exe
Details und die einmaligen OS-Einstellungen (Auto-Login, Ruhezustand aus) siehe
deploy/README.md.
Die Geräte-Identität und das Token liegen in DATA_DIR/device.json. Solange ein
Token vorhanden ist, läuft der Agent im Gerätemodus und zieht
/api/devices/manifest mit Authorization: Bearer <token>.
Der Agent liefert die UI immer aus dem lokalen Cache aus — fällt der Server aus, läuft der Bildschirm mit dem letzten Stand weiter.
Web-Player (Variante A, Docker, headless)
Statt Chromium auf dem Gerät kann der Agent headless in einem Container
laufen und die Player-UI unter :4000 ausliefern. Anzeige übernimmt ein
beliebiger Browser oder Smart-TV, der die Seite öffnet — der erste Klick/Tap
schaltet Vollbild und Ton frei (Autoplay-Videos starten vorher stumm, wie vom
Browser verlangt). KIOSK bleibt aus (kein Chromium im Container), DATA_DIR
ist ein Volume und hält Cache + Enrollment-Token über Neustarts.
# Bauen und starten (Server-URL angeben):
SERVER_URL=https://signage.example.tld docker compose up -d --build
# Danach im Browser/TV öffnen: http://<docker-host>:4000
Standardmäßig startet der Container im Enrollment-Modus: die Seite zeigt
einen Kopplungscode, den man im Builder unter „Geräte" freigibt. Alternativ
SCREEN_ID (zeitlich aufgelöster Zeitplan) oder LAYOUT_ID in der Compose-Datei
setzen. Ein fertiges Multi-Arch-Image (amd64/arm64) wird bei jedem v*-Tag in
die Forgejo-Registry gepusht (.forgejo/workflows/image.yml, Secret
REGISTRY_TOKEN nötig).
Diese Variante wurde gewählt, weil ein reiner Browser-Player den RSS-Ticker (CORS) bräche und den Offline-Platten-Cache verlöre — der Agent im Container behält beides.
Status
Slice 1+2 laufen und sind end-to-end getestet (inkl. Offline-Weiterbetrieb):
Manifest ziehen → Medien per Delta (Asset-ID) cachen → lokale UI rendert das
Layout und loopt die Playlists. Geräte-Enrollment ist umgesetzt: Pairing per
Kopplungscode, Freigabe im Builder, danach Token-authentifizierte Pulls; -screen
und -layout bleiben als Modi ohne Authentifizierung erhalten.