Files
signage/README.md
2026-06-07 12:35:10 +02:00

7.8 KiB
Executable File
Raw Blame History

CANCOM Simple Signage

Browserbasiertes Digital-Signage-System für interne Info-Screens.


Features

  • Browserbasierter Player (Kiosk-Modus, Chromium, Firefox)
  • Bilder, Videos (MP4/H.264), HTML-Seiten, URL-Playlist-Einträge
  • Multi-Standort: Standorte (sites) gruppieren Screens
  • Priority-Playlist: globale Inhalte wirken auf alle Player
  • Willkommensseite: bis zu 3 Kundenlogos via OpenAI + Brandfetch
  • Pro Screen eigene Playlist mit Drag-&-Drop-Reihenfolge
  • Auto-Reload bei Playlist-Änderungen
  • Newsticker pro Screen
  • Custom-URL-Button: pro Screen konfigurierbarer Aktions-Button oben links im Player (öffnet URL in iframe-Overlay mit Zurück-Button oder per Direkt-Weiterleitung)
  • Tab-basierte Admin-UI pro Screen: Playlist, Einstellungen, Medien (Tabler Tabs)
  • Priority-Seite ebenfalls mit Tabs: Playlist und Medien
  • Dark Mode (localStorage-persistiert)
  • CI-konformes Admin-UI (CANCOM-Design: brand-surface, nav-surface rot)

Architektur

Browser (Player)
      │
      ▼
Flask App (Server)
├── Admin UI        /admin/<site>
├── Player UI       /player/<site>/<screen>
├── Priority-Seite  /admin/<site>/priority
├── config.json
├── media/
│   ├── <site>/
│   │   ├── <screen>/
│   │   │   ├── bild.jpg
│   │   │   ├── video.mp4
│   │   │   └── welcome.html
│   └── priority/
└── generate_welcome_page.py
  • Server: Python 3 + Flask
  • Player: Jeder moderne Browser (Chrome Kiosk, Edge, Firefox)
  • State: config.json + Dateisystem
  • Frontend: Tabler Core + Tabler Icons + SortableJS (CDN)

Projektstruktur

signage/
├── app.py                          # Flask-App (alle Routen)
├── generate_welcome_page.py        # Logo-Suche + Willkommensseite-Generierung
├── config.json                     # Persistente Konfiguration
├── media/
│   ├── <site>/
│   │   ├── lobby/
│   │   ├── casino/
│   │   └── videosysteme/
│   └── priority/
├── templates/
│   ├── admin.html                  # Admin-Dashboard (Übersicht)
│   ├── priority.html               # Priority-Playlist (eigene Seite)
│   ├── customer.html               # Willkommensseite-Formular
│   ├── player.html                 # Player-Ansicht
│   ├── login.html
│   ├── _header.html                # Gemeinsamer Header
│   ├── _footer.html                # Gemeinsamer Footer
│   └── _styles.html                # Zentrale CSS (Variablen, Dark Mode)
├── static/
│   ├── cancom.svg
│   └── wallpaper.png
└── AGENTS.md

Installation

Voraussetzungen

  • Python ≥ 3.9
  • pip
  • ffmpeg (optional, für Videokonvertierung)

Setup

pip install -r requirements.txt

Starten

python app.py

Server läuft auf http://localhost:5005.

Docker

docker compose up -d

Routen

Route Beschreibung
GET / 404 kein Root-Endpunkt
GET /login Admin-Login
GET /logout Ausloggen
GET /admin Redirect zum ersten konfigurierten Standort
GET /admin/<site> Admin-Dashboard für einen Standort
GET /admin/<site>/priority Priority-Playlist (separate Seite)
POST /admin/<site>/update/<screen> Screen-Einstellungen speichern
POST /admin/<site>/upload/<screen> Medien hochladen
POST /admin/<site>/add-url/<screen> URL zur Playlist hinzufügen
POST /admin/<site>/delete/<screen>/<filename> Datei löschen
POST /admin/<site>/playlist/<screen> Playlist-Reihenfolge speichern (JSON)
POST /admin/<site>/delete-screen/<screen> Screen + Medien löschen
GET /admin/<site>/add-screen?name=<name> Neuen Screen anlegen
GET /add-site?name=<name> Neuen Standort anlegen
POST /admin/<site>/delete-site Standort + alle Screens/Medien löschen
GET /player/<site>/<screen> Player-Ansicht
GET /playlist/<site>/<screen>/hash Playlist-Checksumme (für Auto-Reload)
GET /willkommen?site=<site> Willkommensseite-Formular (GET + POST)
POST /api/customer API-Endpunkt für Willkommensseite (JSON)
GET /media/<site>/<screen>/<file> Medien-Datei ausliefern
GET /media/priority/<file> Priority-Medien (global)

Admin-Portal

http://localhost:5005/admin/<standort>
  • Screens konfigurieren (Tab-basiert: Playlist, Einstellungen, Medien)
  • Medien hochladen / löschen
  • Playlist per Drag & Drop sortieren
  • Priority-Playlist verwalten (ebenfalls mit Tabs)
  • Willkommensseite generieren (bis zu 3 Kundenlogos)
  • Custom-URL-Aktionsbutton pro Screen konfigurieren (iframe-Overlay oder Weiterleitung)
  • Standorte anlegen & löschen

Player-URL

http://localhost:5005/player/<standort>/<screen>

Beispiel:

http://localhost:5005/player/stuttgart/lobby

Willkommensseite

http://localhost:5005/willkommen?site=stuttgart

Maximal 3 Kunden eingeben → Logos werden via OpenAI + Brandfetch gesucht → welcome.html wird in der Lobby-Playlist vorne eingefügt.


Konfiguration (config.json)

{
  "server_url": "http://signage.ccmake.de",
  "admin": { "username": "...", "password": "..." },
  "sites": {
    "stuttgart": {
      "screens": {
        "lobby": {
          "playlist": [...],
          "interval": 10,
          "show_images": true,
          "show_videos": true,
          "newsticker_text": "...",
          "newsticker_enabled": false,
          "custom_url_enabled": false,
          "custom_url": "https://...",
          "custom_url_label": "Infos",
          "custom_url_target": "overlay"
        },
        "casino": { "playlist": [...], "interval": 15 }
      }
    }
  },
  "priority": {
    "enabled": true,
    "playlist": [...]
  }
}

Screen-Konfiguration (pro Screen in config.json)

Feld Typ Beschreibung
playlist Array Playlist-Einträge (Strings oder Dicts mit url/zoom)
interval int Anzeige-Intervall in Sekunden
show_images bool Bilder anzeigen
show_videos bool Videos anzeigen
newsticker_text string Text für Newsticker (max. 200 Zeichen)
newsticker_enabled bool Newsticker anzeigen
custom_url_enabled bool Custom-URL-Button im Player anzeigen
custom_url string URL des Aktions-Buttons
custom_url_label string Button-Beschriftung
custom_url_target string "overlay" (iframe) oder "redirect"

Helper-Funktionen (app.py)

  • load_config() / save_config() JSON lesen/schreiben
  • get_site_list(cfg) alle Standorte sortiert
  • get_screen_config(cfg, site, screen) Screen-Konfiguration mit Defaults
  • is_url(item) prüft ob Item eine URL ist
  • normalize_url(item) normalisiert URL-Item zu {"url", "zoom"}
  • playlist_item_name(item) Name aus String oder Dict extrahieren
  • playlist_item_enabled(item) Enabled-Status prüfen
  • load_priority_files() Priority-Playlist + Dateien laden
  • prio_redirect(site) Redirect-Pfad zur Priority-Seite

Dark Mode

Wird über localStorage("signage-theme") persistiert. Umschalt-Button im Header. CSS-Variablen --ccm-* in _styles.html.


Sicherheit

  • Admin-Bereich per Flask-Login geschützt
  • Player-Seiten Read-Only
  • Externe Nutzung via Reverse Proxy + TLS empfohlen

Git & Medien

Das Repository ist für Code gedacht, nicht für Medien.

media/ und Medien-Dateiendungen sind in .gitignore ausgeschlossen.


Video-Empfehlungen

  • Format: MP4 (H.264)
  • Auflösung: max. 1920×1080
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -movflags +faststart output.mp4

Maintainer

CANCOM Simple Signage Interne Lösung, nicht für externe Weitergabe bestimmt.