#!/usr/bin/env bash # Audiofy – Installation der Rolle "Player": Spotify-Connect-Gerät (raspotify) und Controller. # # install/install-player.sh Neuinstallation (fragt alles Nötige ab) # install/install-player.sh --update nur Code, Python-Umgebung und Dienst aktualisieren # # Läuft auf Raspberry Pi, Mini-PC oder VM mit Debian 12+ (arm64, armhf oder amd64). # Ausgabe wahlweise über einen Bluetooth-Lautsprecher (BlueALSA) oder einen ALSA-Ausgang # (Klinke, HDMI, USB-DAC). Der Player baut nur ausgehende Verbindungen auf. set -euo pipefail source "$(dirname "$0")/lib.sh" UPDATE=0 BLUETOOTH=0 for arg in "$@"; do case "$arg" in --update) UPDATE=1 ;; -h|--help) sed -n '2,10p' "$0"; exit 0 ;; *) abbruch "Unbekannte Option: $arg" ;; esac done KONFIG="$AUDIOFY_DIR/config" ENV_DATEI="$KONFIG/.env" RASPOTIFY_CONF=/etc/raspotify/conf export AUDIOFY_DIR AUDIOFY_USER schritt "Audiofy-Player: $([ $UPDATE = 1 ] && echo Update || echo Neuinstallation)" pruefe_system ARCH="$(dpkg --print-architecture)" case "$ARCH" in arm64|armhf|amd64) ;; *) abbruch "raspotify gibt es nicht für $ARCH (nur arm64, armhf, amd64)." ;; esac if [ $UPDATE = 1 ] && ! $SUDO test -f "$ENV_DATEI"; then abbruch "Keine bestehende Installation in $AUDIOFY_DIR gefunden – ohne --update ausführen." fi # ------------------------------------------------------------------ Abfragen if [ $UPDATE = 0 ]; then schritt "Angaben" frage GERAETENAME "Name des Spotify-Connect-Geräts" "Audiofy" echo " Audio-Ausgabe: 1) Bluetooth-Lautsprecher 2) Kabel/HDMI/USB (ALSA)" frage AUSGABE "Auswahl" "1" if [ "$AUSGABE" = 2 ]; then BLUETOOTH=0 if command -v aplay >/dev/null; then info "Verfügbare ALSA-Ausgänge:" aplay -L 2>/dev/null | grep -E '^(default|sysdefault|plughw|hdmi)' | sed 's/^/ /' | head -20 || true fi frage ALSA_GERAET "ALSA-Gerät" "default" else BLUETOOTH=1 ALSA_GERAET="bluealsa:DEV=00:00:00:00:00:00,PROFILE=a2dp" # = zuletzt verbundener Lautsprecher fi frage SERVER_URL "Adresse des Audiofy-Servers (leer = ohne Wünsche, nur Playlist)" "" SERVER_URL="${SERVER_URL%/}" PLAYER_TOKEN="" [ -n "$SERVER_URL" ] && frage_geheim PLAYER_TOKEN "PLAYER_API_TOKEN vom Server (verdeckt)" info "Spotify-App (developer.spotify.com): Redirect-URI http://127.0.0.1:8888/callback eintragen." frage SPOTIFY_CLIENT_ID "Spotify Client ID" frage_geheim SPOTIFY_CLIENT_SECRET "Spotify Client Secret (verdeckt)" frage PLAYLIST "Grund-Playlist (Link oder ID; mit Server wird sie dort eingestellt)" PLAYLIST_ID="$(sed -E 's#.*playlist[/:]([A-Za-z0-9]{22}).*#\1#' <<<"$PLAYLIST")" [[ "$PLAYLIST_ID" =~ ^[A-Za-z0-9]{22}$ ]] || { warnung "Keine gültige Playlist – bitte später eintragen."; PLAYLIST_ID=""; } fi # ------------------------------------------------------------------ Pakete schritt "Pakete" $SUDO apt-get update -qq PAKETE=(python3-venv curl ca-certificates alsa-utils) if [ $UPDATE = 0 ] && [ "$BLUETOOTH" = 1 ]; then PAKETE+=(bluez bluez-alsa-utils libasound2-plugin-bluez) fi pakete "${PAKETE[@]}" if ! dpkg -s raspotify >/dev/null 2>&1; then schritt "raspotify (Spotify Connect)" $SUDO curl -sSfL https://dtcooper.github.io/raspotify/key.asc -o /usr/share/keyrings/raspotify_key.asc $SUDO chmod 644 /usr/share/keyrings/raspotify_key.asc echo "deb [signed-by=/usr/share/keyrings/raspotify_key.asc] https://dtcooper.github.io/raspotify raspotify main" \ | $SUDO tee /etc/apt/sources.list.d/raspotify.list >/dev/null $SUDO apt-get update -qq pakete raspotify fi # ------------------------------------------------------------------ raspotify einstellen (nur Neuinstallation) if [ $UPDATE = 0 ]; then schritt "raspotify einstellen" $SUDO test -f "$RASPOTIFY_CONF.orig" || $SUDO cp "$RASPOTIFY_CONF" "$RASPOTIFY_CONF.orig" setze_raspotify() { # KEY WERT – vorhandene (auch auskommentierte) Zeile ersetzen, sonst anhängen if $SUDO grep -qE "^#?\s*$1=" "$RASPOTIFY_CONF"; then $SUDO sed -i -E "0,/^#?\s*$1=.*/s||$1=\"$2\"|" "$RASPOTIFY_CONF" else echo "$1=\"$2\"" | $SUDO tee -a "$RASPOTIFY_CONF" >/dev/null fi } setze_raspotify LIBRESPOT_NAME "$GERAETENAME" setze_raspotify LIBRESPOT_DEVICE_TYPE "speaker" setze_raspotify LIBRESPOT_BACKEND "alsa" setze_raspotify LIBRESPOT_DEVICE "$ALSA_GERAET" setze_raspotify LIBRESPOT_BITRATE "320" # Anmeldedaten speichern (sonst nach jedem Neustart unsichtbar) und normal protokollieren $SUDO sed -i -E 's/^(LIBRESPOT_DISABLE_CREDENTIAL_CACHE=|LIBRESPOT_QUIET=)/#\1/' "$RASPOTIFY_CONF" info "Name „$GERAETENAME“, Ausgabe $ALSA_GERAET" fi $SUDO install -d /etc/systemd/system/raspotify.service.d vorlage raspotify-10-audiofy.conf /etc/systemd/system/raspotify.service.d/10-audiofy.conf $SUDO systemctl daemon-reload $SUDO systemctl enable raspotify >/dev/null 2>&1 [ $UPDATE = 0 ] && $SUDO systemctl restart raspotify # ------------------------------------------------------------------ Bluetooth (nur Neuinstallation) BT_MAC="" if [ $UPDATE = 0 ] && [ "$BLUETOOTH" = 1 ]; then schritt "Bluetooth-Lautsprecher" # Auf frischen Systemen ist Bluetooth oft per rfkill gesperrt (z. B. ohne gesetztes WLAN-Land) command -v rfkill >/dev/null && { $SUDO rfkill unblock bluetooth || true; } $SUDO systemctl enable --now bluetooth >/dev/null 2>&1 || warnung "Bluetooth-Dienst ließ sich nicht starten." # Der Player soll nicht selbst als Bluetooth-Empfänger für fremde Handys dienen $SUDO systemctl disable --now bluealsa-aplay >/dev/null 2>&1 || true info "Lautsprecher jetzt in den Kopplungsmodus versetzen (meist Bluetooth-Taste halten, bis die LED blinkt)." if ja_nein "Jetzt suchen und koppeln?" j; then BT_MAC="$(cd "$REPO/player" && python3 - <<'PY' import sys, lautsprecher as l print(" Suche 15 s …", file=sys.stderr) geraete = l.suchen() if not geraete: print(" Kein Audiogerät gefunden.", file=sys.stderr); sys.exit(0) for i, g in enumerate(geraete, 1): print(f" {i}) {g['name'] or 'Unbekannt'} ({g['mac']})", file=sys.stderr) print(" Nummer: ", end="", file=sys.stderr, flush=True) wahl = open("/dev/tty").readline().strip() if not wahl.isdigit() or not 1 <= int(wahl) <= len(geraete): sys.exit(0) mac = geraete[int(wahl) - 1]["mac"] ok, meldung = l.koppeln(mac) print(f" {meldung}", file=sys.stderr) if ok: print(mac) PY )" || true [ -n "$BT_MAC" ] || warnung "Kein Lautsprecher gekoppelt – später im Admin-Bereich unter Einstellungen → Lautsprecher." fi fi # ------------------------------------------------------------------ Benutzer, Ordner, Code schritt "Dienst-Benutzer, Ordner und Code" dienst_benutzer $SUDO install -d -o root -g "$AUDIOFY_USER" -m 750 "$AUDIOFY_DIR" $SUDO install -d -o "$AUDIOFY_USER" -g "$AUDIOFY_USER" -m 700 "$KONFIG" code_kopieren "$REPO/player" "$AUDIOFY_DIR/app" venv_einrichten "$AUDIOFY_DIR/app/requirements.txt" info "Code in $AUDIOFY_DIR/app, Konfiguration in $KONFIG" # ------------------------------------------------------------------ Konfiguration schritt "Konfiguration ($ENV_DATEI)" if [ $UPDATE = 0 ]; then $SUDO test -f "$ENV_DATEI" || $SUDO install -o "$AUDIOFY_USER" -g "$AUDIOFY_USER" -m 600 /dev/null "$ENV_DATEI" env_setzen "$ENV_DATEI" SPOTIFY_CLIENT_ID "$SPOTIFY_CLIENT_ID" env_setzen "$ENV_DATEI" SPOTIFY_CLIENT_SECRET "$SPOTIFY_CLIENT_SECRET" env_setzen "$ENV_DATEI" SPOTIFY_REDIRECT_URI "http://127.0.0.1:8888/callback" env_setzen "$ENV_DATEI" DEVICE_NAME "$GERAETENAME" env_setzen "$ENV_DATEI" WISH_EVERY_N "3" [ -n "$PLAYLIST_ID" ] && env_setzen "$ENV_DATEI" SPOTIFY_PLAYLIST_ID "$PLAYLIST_ID" [ -n "$BT_MAC" ] && env_setzen "$ENV_DATEI" BT_SPEAKER_MAC "$BT_MAC" if [ -n "$SERVER_URL" ]; then env_setzen "$ENV_DATEI" SERVER_URL "$SERVER_URL" env_setzen "$ENV_DATEI" PLAYER_API_TOKEN "$PLAYER_TOKEN" fi unset SPOTIFY_CLIENT_SECRET PLAYER_TOKEN schritt "Spotify-Login für die Wiedergabe-Steuerung" info "Öffne gleich die angezeigte Adresse im Browser, melde dich an und füge danach die" info "Adresse aus der Adresszeile (http://127.0.0.1:8888/callback?...) hier ein." "${ALS_DIENST[@]}" "$AUDIOFY_DIR/.venv/bin/python" "$AUDIOFY_DIR/app/auth.py" --profil player --env "$ENV_DATEI" \ || warnung "Login fehlgeschlagen – später nachholen (siehe README)." else # alte Schlüsselnamen übernehmen env_umbenennen "$ENV_DATEI" VPS_URL SERVER_URL env_umbenennen "$ENV_DATEI" PI_API_TOKEN PLAYER_API_TOKEN fi # ------------------------------------------------------------------ Dienst schritt "Dienst audiofy-controller" vorlage audiofy-controller.service /etc/systemd/system/audiofy-controller.service $SUDO systemctl daemon-reload $SUDO systemctl enable audiofy-controller >/dev/null 2>&1 $SUDO systemctl restart audiofy-controller sleep 5 systemctl is-active --quiet audiofy-controller || abbruch "audiofy-controller läuft nicht – siehe: journalctl -u audiofy-controller" info "audiofy-controller läuft" # ------------------------------------------------------------------ Zusammenfassung schritt "Fertig" info "Logs: journalctl -u audiofy-controller -f · journalctl -u raspotify -f" if [ $UPDATE = 0 ]; then info "" info "Wichtig: Wähle das Gerät „$GERAETENAME“ EINMAL in der Spotify-App aus (im selben Netz)." info "Danach sind die Anmeldedaten gespeichert, und der Player startet nach jedem Neustart selbst." fi