install.sh for ny maskin + paplay-reserve når PipeWire mangler
Skriptet installerer apt-pakker, uv, Python 3.13, Piper-stemmene og systemd-brukerenheten, og åpner porten i ufw hvis den er aktiv. Avspilling velger pw-play når PipeWire kjører, ellers paplay (Linux Mint 21). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
756a234b13
commit
ad1715838e
3 changed files with 128 additions and 4 deletions
|
|
@ -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
|
(enabled, port 8090). `systemctl --user restart sg-announcer` etter endringer
|
||||||
i koden. Manuelt: `uv run announcer.py --port 8090`.
|
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 =
|
Miljøvariabler (settes i enheten): `ANNOUNCER_PORT`, `ANNOUNCER_PIN` (tom =
|
||||||
ingen PIN), `ANNOUNCER_SINK` (pw-play `--target`; tom = standard utgang).
|
ingen PIN), `ANNOUNCER_SINK` (pw-play `--target`; tom = standard utgang).
|
||||||
|
|
||||||
|
|
|
||||||
22
announcer.py
22
announcer.py
|
|
@ -15,6 +15,7 @@ import logging
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
import queue
|
import queue
|
||||||
|
import shutil
|
||||||
import struct
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
import threading
|
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:
|
class Player:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.q: queue.Queue[Item] = queue.Queue()
|
self.q: queue.Queue[Item] = queue.Queue()
|
||||||
|
|
@ -374,10 +391,7 @@ class Player:
|
||||||
self.current = item
|
self.current = item
|
||||||
try:
|
try:
|
||||||
path = synthesize(item.text, item.voice, item.speed, item.chime)
|
path = synthesize(item.text, item.voice, item.speed, item.chime)
|
||||||
cmd = ["pw-play"]
|
cmd = player_cmd(path)
|
||||||
if SINK:
|
|
||||||
cmd += ["--target", SINK]
|
|
||||||
cmd.append(str(path))
|
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self.proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
|
self.proc = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
|
||||||
_, err = self.proc.communicate()
|
_, err = self.proc.communicate()
|
||||||
|
|
|
||||||
105
install.sh
Executable file
105
install.sh
Executable file
|
|
@ -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
|
||||||
|
[Unit]
|
||||||
|
Description=SG Announcer – TTS-utrop på høyttaleranlegget
|
||||||
|
After=pipewire.service pulseaudio.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
WorkingDirectory=$REPO_DIR
|
||||||
|
ExecStart=$UV run announcer.py
|
||||||
|
Environment=ANNOUNCER_PORT=$PORT
|
||||||
|
UNIT
|
||||||
|
if [[ -n "$PIN" ]]; then
|
||||||
|
echo "Environment=ANNOUNCER_PIN=$PIN"
|
||||||
|
else
|
||||||
|
echo "# Environment=ANNOUNCER_PIN=1234"
|
||||||
|
fi
|
||||||
|
cat <<'UNIT'
|
||||||
|
# Environment=ANNOUNCER_SINK=alsa_output.xxx
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=3
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
UNIT
|
||||||
|
} > "$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 <<MSG
|
||||||
|
|
||||||
|
Åpne http://${IP:-<denne-maskinens-ip>}:$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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue