Files
playwish/README.md
T
99admandClaude Opus 5.5 df5567e6a3 Wiederholungsregel für die Grund-Playlist
Ein Playlist-Titel kommt erst wieder, wenn seit seinem letzten Einsatz
mindestens X % der Playlist gelaufen sind (Admin → Einstellungen → Ablauf,
Standard 50 %). Der Player merkt sich die gespielten Titel über Neustarts.
Wünsche sind ausgenommen (dort gilt weiter die Sperrzeit in Minuten).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:27:15 +01:00

167 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Audiofy – Musikwünsche für Partys
Gäste scannen einen QR-Code und wünschen sich Songs. Ein **Player** spielt über Spotify
zufällige Titel aus einer Grund-Playlist – jeder N-te Titel ist ein Wunsch. Gibt es keine
Wünsche, läuft einfach die Playlist weiter. Der Gastgeber steuert alles über einen
Admin-Bereich, auch vom Handy.
- **Gäste:** Spotify-Suche, Wünschen (optional mit Namen), „Läuft gerade“, Warteschlange – ohne Spotify-Konto
- **Schutz:** Zugang nur per Einladungslink/QR-Code, Limit pro Gast, keine Duplikate, Sperrzeit für Wiederholungen, Sperrliste, optional Moderation und Cloudflare Turnstile
- **Admin:** Play/Pause/Weiter/Lautstärke, „Als Nächstes spielen“, Not-Aus, Wünsche freigeben/umsortieren/löschen, Gäste sperren, Playlist wechseln, Bluetooth-Lautsprecher suchen und wechseln, Verlauf
- **Abwechslung:** Ein Playlist-Titel kommt erst wieder, wenn seit seinem letzten Einsatz mindestens X % der Playlist gelaufen sind (einstellbar, auch über Neustarts); Wünsche haben eine eigene Sperrzeit in Minuten
- **Robust:** Ohne Server spielt der Player die Playlist weiter; Bedienung über die normale Spotify-App bleibt möglich; Pause des Gastgebers wird auch über Neustarts respektiert
## Aufbau
```
Gast-Handy ──HTTPS──▶ Server: Caddy → audiofy-web (FastAPI + SQLite)
▲ Player-API (Bearer-Token)
│ nur ausgehend vom Player
Player: raspotify (Spotify Connect) + audiofy-controller
└─▶ Bluetooth-Lautsprecher (BlueALSA) oder Kabel/HDMI/USB (ALSA)
```
| Rolle | Läuft auf | Braucht |
|---|---|---|
| **Server** | VPS, Heimserver, VM … | Debian 12+, öffentliche (Sub-)Domain, Ports 80/443 |
| **Player** | Raspberry Pi, Mini-PC, VM mit Audio … | Debian 12+ (arm64/armhf/amd64), Lautsprecher, Internet |
Beide Rollen können auch auf demselben Gerät laufen. Der Player braucht **keine**
Portfreigabe am Router.
## Voraussetzungen
1. **Spotify Premium** für das Konto, das abspielt.
2. **Spotify-App** auf <https://developer.spotify.com/dashboard>:
- App anlegen (Web API), Redirect-URI **`http://127.0.0.1:8888/callback`** eintragen
- unter „User Management“ das eigene Spotify-Konto eintragen
- Client ID und Client Secret bereithalten
3. Eine **eigene Playlist** als Grund-Playlist (im Development Mode lassen sich nur eigene Playlists lesen).
4. Für den Server eine **Domain**, deren A/AAAA-Record auf den Server zeigt.
## Installation
Repository auf das jeweilige Gerät holen (`git clone …`) und als Benutzer mit sudo-Rechten
(oder als root) ausführen.
**1. Server**
```
install/install-server.sh
```
Fragt Domain, E-Mail für Let's Encrypt, Spotify-Zugang und Playlist ab, richtet Dienst-Benutzer,
Python-Umgebung, systemd-Dienst und Caddy (HTTPS) ein und optional Firewall (ufw), fail2ban und
automatische Sicherheitsupdates. Danach folgen der Spotify-Login (nur für die Suche) und das
Admin-Passwort.
Am Ende zeigt das Skript, wie du den **`PLAYER_API_TOKEN`** für den Player abrufst.
**2. Player**
```
install/install-player.sh
```
Fragt Gerätename, Audio-Ausgabe (Bluetooth oder ALSA), Server-Adresse, `PLAYER_API_TOKEN`,
Spotify-Zugang und Playlist ab, installiert raspotify, koppelt auf Wunsch gleich den
Bluetooth-Lautsprecher und richtet den Controller als Dienst ein. Danach folgt der
Spotify-Login für die Wiedergabe-Steuerung.
**3. Einmalig in der Spotify-App** das neue Gerät (Standard: „Audiofy“) auswählen – im selben
Netz wie der Player. Damit speichert raspotify seine Anmeldung und ist nach jedem Neustart
von selbst wieder da.
**4. Admin-Bereich** unter `https://<domain>/admin` öffnen, unter **Gäste** den Gastzugang
einschalten und den QR-Code zeigen oder ausdrucken.
## Betrieb
| Aufgabe | Befehl |
|---|---|
| Status | `systemctl status audiofy-web` (Server) · `systemctl status audiofy-controller raspotify` (Player) |
| Logs live | `journalctl -u audiofy-web -f` · `journalctl -u audiofy-controller -f` |
| Neustart | `sudo systemctl restart audiofy-web` bzw. `audiofy-controller` |
| Update | `git pull && install/install-server.sh --update` bzw. `install/install-player.sh --update` |
`--update` ersetzt nur Code, Python-Umgebung und Dienstdatei; Konfiguration, Datenbank,
Caddy, Firewall und raspotify bleiben unverändert.
**Dateien**
| Pfad | Inhalt |
|---|---|
| `/opt/audiofy/app` | Code (gehört root, der Dienst darf nur lesen) |
| `/opt/audiofy/.env` (Server) | Geheimnisse: Spotify, Admin-Passwort-Hash, Turnstile, `PLAYER_API_TOKEN` |
| `/opt/audiofy/data/audiofy.db` (Server) | Wünsche, Verlauf, Einstellungen |
| `/opt/audiofy/config/.env` (Player) | Geheimnisse: Spotify, `SERVER_URL`, `PLAYER_API_TOKEN`, Lautsprecher |
Die `.env`-Dateien gehören dem Dienst-Benutzer `audiofy` (Rechte 600). **Sichere sie an einem
sicheren Ort** (z. B. Passwort-Manager) – sie stehen bewusst nicht im Repository.
**Verwaltung** (interaktiv, im eigenen Terminal):
```
# Server: Admin-Passwort bzw. Turnstile-Schlüssel ändern
sudo -u audiofy /opt/audiofy/.venv/bin/python /opt/audiofy/app/verwaltung.py passwort --env /opt/audiofy/.env
sudo -u audiofy /opt/audiofy/.venv/bin/python /opt/audiofy/app/verwaltung.py turnstile --env /opt/audiofy/.env
# Spotify-Login erneuern – Server bzw. Player
sudo -u audiofy /opt/audiofy/.venv/bin/python /opt/audiofy/app/auth.py --profil server --env /opt/audiofy/.env
sudo -u audiofy /opt/audiofy/.venv/bin/python /opt/audiofy/app/auth.py --profil player --env /opt/audiofy/config/.env
```
Danach den jeweiligen Dienst neu starten.
**Datenbank sichern** (Server):
```
sudo -u audiofy sqlite3 /opt/audiofy/data/audiofy.db ".backup /opt/audiofy/data/sicherung.db"
```
## Server härten (empfohlen, von Hand)
Das Install-Skript ändert die SSH-Konfiguration bewusst **nicht** – damit sperrt man sich
leicht aus. Vorlage: `install/vorlagen/sshd-10-audiofy.conf` (anderer Port, nur Schlüssel,
kein root, nur ein Admin-Benutzer). Vorgehen:
1. Eigenen Admin-Benutzer mit sudo anlegen, SSH-Schlüssel hinterlegen, Login testen.
2. Neuen Port in ufw **und** einer eventuellen Cloud-Firewall öffnen.
3. Vorlage ausgefüllt nach `/etc/ssh/sshd_config.d/10-audiofy.conf` legen, `sudo sshd -t`, `sudo systemctl restart ssh`.
4. **In einer zweiten Sitzung** testen – die alte bleibt offen, bis es klappt.
5. Erst dann den alten Port in ufw/Cloud-Firewall schließen und fail2ban auf den neuen Port umstellen.
## Fehlerbehebung
| Problem | Ursache / Lösung |
|---|---|
| Keine Musik, Log: „Lautsprecher nicht verbunden“ | Lautsprecher einschalten – der Player verbindet ihn neu und startet die Musik von selbst. |
| Lautsprecher verbindet sich nicht mehr („Permission denied“) | Kopplung verloren. Im Admin unter Einstellungen → Lautsprecher neu suchen und verbinden (Lautsprecher im Kopplungsmodus). |
| „Gerät nicht gefunden“ | `systemctl status raspotify`. Nach einer Neuinstallation einmal in der Spotify-App das Gerät auswählen. |
| Admin: „Player offline“ | `systemctl status audiofy-controller`, Internet des Players prüfen. Die Musik läuft trotzdem mit der Playlist weiter. |
| Admin: „Grund-Playlist nicht lesbar“ | Nur eigene Playlists funktionieren (Spotify Development Mode). |
| Befehle „No active device“ | Spotify hatte kein aktives Gerät; „Play“ startet dann die Playlist auf dem Player. |
| Nach Neustart bleibt es still | Gewollt, wenn vorher pausiert oder Not-Aus aktiv war – im Admin „Play“ bzw. „Freigeben“. |
| Musik stockt während der Lautsprecher-Suche | Normal: WLAN und Bluetooth teilen sich oft einen Funkchip. |
| Gäste: „Kein Zugang“ | Gastzugang im Admin eingeschaltet? Nach „Neuen Link erzeugen“ gilt nur der neue QR-Code. |
| Zu viele Admin-Login-Versuche | 15 Minuten warten (max. 5 Versuche pro IP). |
## Spotify-Hinweise
Audiofy nutzt die Spotify Web API im **Development Mode** (nicht kommerziell). Dort gilt:
Premium für den App-Besitzer, Nutzer-Allowlist, höchstens 10 Suchtreffer, nur eigene
Playlists lesbar. Gäste melden sich nie bei Spotify an; Server und Player nutzen je einen
eigenen Refresh-Token desselben Kontos.
## Entwicklung
```
cd server && python3 -m venv .venv && .venv/bin/pip install -r requirements.txt pytest
.venv/bin/python -m pytest -q # Server
cd ../player && python3 -m venv .venv && .venv/bin/pip install -r requirements.txt pytest
.venv/bin/python -m pytest -q tests # Player (Wiederholungsregel)
```
## Lizenz
Noch nicht festgelegt.