diff --git a/AGENTS.md b/AGENTS.md index 0be4874..e123393 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,6 +15,11 @@ Tjenesten er en systemd-brukerenhet: `~/.config/systemd/user/sg-announcer.servic (enabled, port 8090). `systemctl --user restart sg-announcer` etter endringer i koden. Manuelt: `uv run announcer.py --port 8090`. +Ny maskin (Debian/Ubuntu/Mint): `git clone https://git.1x1.no/kent/sg-announcer.git` +og `./install.sh` gjør alt (apt, uv, Python 3.13, stemmer, enhet, ufw). Kan +kjøres på nytt. Avspilling bruker `pw-play` når PipeWire kjører, ellers +`paplay` (`player_cmd()`), så Mint 21 med PulseAudio virker også. + Miljøvariabler (settes i enheten): `ANNOUNCER_PORT`, `ANNOUNCER_PIN` (tom = ingen PIN), `ANNOUNCER_SINK` (pw-play `--target`; tom = standard utgang). diff --git a/announcer.py b/announcer.py index 077bee9..46fe322 100644 --- a/announcer.py +++ b/announcer.py @@ -15,6 +15,7 @@ import logging import math import os import queue +import shutil import struct import subprocess import threading @@ -321,6 +322,22 @@ class Item: } +def player_cmd(path: Path) -> list[str]: + """pw-play når PipeWire kjører, ellers paplay (PulseAudio, f.eks. Linux Mint 21).""" + runtime = Path(os.environ.get("XDG_RUNTIME_DIR", f"/run/user/{os.getuid()}")) + if shutil.which("pw-play") and (runtime / "pipewire-0").exists(): + cmd = ["pw-play"] + if SINK: + cmd += ["--target", SINK] + elif shutil.which("paplay"): + cmd = ["paplay"] + if SINK: + cmd += ["--device", SINK] + else: + raise RuntimeError("fant verken pw-play (pipewire-bin) eller paplay (pulseaudio-utils)") + return cmd + [str(path)] + + class Player: def __init__(self) -> None: self.q: queue.Queue[Item] = queue.Queue() @@ -374,10 +391,7 @@ class Player: self.current = item try: path = synthesize(item.text, item.voice, item.speed, item.chime) - cmd = ["pw-play"] - if SINK: - cmd += ["--target", SINK] - cmd.append(str(path)) + cmd = player_cmd(path) with self.lock: self.proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE) _, err = self.proc.communicate() diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..93fe94e --- /dev/null +++ b/install.sh @@ -0,0 +1,105 @@ +#!/usr/bin/env bash +# Installerer SG Announcer på en Debian/Ubuntu-maskin (testet mot Linux Mint). +# +# git clone https://git.1x1.no/kent/sg-announcer.git +# cd sg-announcer && ./install.sh +# +# Kjør som vanlig bruker (ikke sudo); skriptet spør om passord der det trengs. +# Valgfritt: ANNOUNCER_PIN=1234 ./install.sh -> sida krever PIN +# ANNOUNCER_PORT=8090 ./install.sh -> annen port +# Kan kjøres på nytt; da oppdateres avhengigheter og tjenesten startes om. +set -euo pipefail + +if [[ $EUID -eq 0 ]]; then + echo "Kjør som vanlig bruker, ikke root/sudo." >&2 + exit 1 +fi + +REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PORT="${ANNOUNCER_PORT:-8090}" +PIN="${ANNOUNCER_PIN:-}" +UNIT_DIR="$HOME/.config/systemd/user" +UNIT="$UNIT_DIR/sg-announcer.service" + +step() { printf '\n\033[1m==> %s\033[0m\n' "$*"; } + +step "Systempakker (apt)" +sudo apt-get update -qq +sudo apt-get install -y -qq git curl ca-certificates ffmpeg pulseaudio-utils +# pw-play finnes i pipewire-bin på Mint 22 / Ubuntu 24.04. På eldre (PulseAudio) +# faller appen tilbake til paplay, så dette er ikke kritisk. +sudo apt-get install -y -qq pipewire-bin 2>/dev/null || true + +step "uv (Python-pakkehåndterer)" +if command -v uv >/dev/null 2>&1; then + UV="$(command -v uv)" +elif [[ -x "$HOME/.local/bin/uv" ]]; then + UV="$HOME/.local/bin/uv" +else + curl -LsSf https://astral.sh/uv/install.sh | sh + UV="$HOME/.local/bin/uv" +fi +echo "uv: $UV ($("$UV" --version))" + +step "Python 3.13 og avhengigheter" +cd "$REPO_DIR" +"$UV" sync +mkdir -p cache chimes voices + +step "Laster ned Piper-stemmene (lokal reserve, ca. 600 MB, kun første gang)" +"$UV" run python -c "import logging, announcer; logging.basicConfig(level=logging.INFO, format='%(message)s'); announcer.ensure_voices()" + +step "systemd-brukertjeneste" +mkdir -p "$UNIT_DIR" +{ + cat < "$UNIT" +systemctl --user daemon-reload +systemctl --user enable --now sg-announcer +systemctl --user restart sg-announcer + +step "Brannmur" +if sudo ufw status 2>/dev/null | grep -q "Status: active"; then + sudo ufw allow "$PORT/tcp" comment "sg-announcer" +else + echo "ufw er ikke aktiv, ingen regel nødvendig." +fi + +sleep 2 +IP="$(hostname -I 2>/dev/null | awk '{print $1}')" +step "Ferdig" +systemctl --user --no-pager status sg-announcer | head -5 || true +cat <}:$PORT fra hva som helst på nettet. + +Tips for en laptop på arrangementet: + - Lyden spilles i din innloggede økt, så maskinen må være logget inn. + Slå på automatisk innlogging (Innstillinger -> Påloggingsvindu). + - Hindre at den sover med lokket igjen: + sudo sed -i 's/^#\?HandleLidSwitch=.*/HandleLidSwitch=ignore/' /etc/systemd/logind.conf + sudo systemctl restart systemd-logind + - Logg: journalctl --user -u sg-announcer -f +MSG