0efc5bb3462551a6fa8f4c8d26b8d0c7c97f607c
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-surfacerot)
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 flask flask-login werkzeug openai
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) |
GET /add-site?name=<name> |
Neuen Standort anlegen |
POST /admin/<site>/delete-site |
Standort + alle Screens/Medien löschen |
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 },
"casino": { "playlist": [...], "interval": 15 }
}
}
},
"priority": {
"enabled": true,
"playlist": [...]
}
}
Helper-Funktionen (app.py)
load_config()/save_config()– JSON lesen/schreibenget_site_list(cfg)– alle Standorte sortiertget_screen_config(cfg, site, screen)– Screen-Konfiguration mit Defaultsis_url(item)– prüft ob Item eine URL istnormalize_url(item)– normalisiert URL-Item zu{"url", "zoom"}playlist_item_name(item)– Name aus String oder Dict extrahierenplaylist_item_enabled(item)– Enabled-Status prüfenload_priority_files()– Priority-Playlist + Dateien ladenprio_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.
Description
Languages
HTML
63.3%
Python
36.4%
Dockerfile
0.2%
Shell
0.1%