announcer/AGENTS.md
Kent 775ab6d075 install.sh: ufw låst til NetBird (wt0) når det finnes
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-06 19:20:47 +02:00

3.8 KiB
Raw Blame History

sg-announcer – utrop på høyttaleranlegget (Sauda Gathering)

Liten Flask-app: tekst inn i nettleseren → forhåndslytt → «Send ut på anlegget» spiller lyden lokalt på denne maskinen med pw-play. TTS er Piper (piper-tts, onnx, helt lokalt). Alt ligger i to filer: announcer.py (server + kø) og index.html (sida).

Dokumentasjon for Kent: Athena-notatet 30 Ressurser/Teknologi/Sauda Gathering - announcer.md. Oppdater det, ikke denne fila, når noe som er verdt å huske endres.

Kjøring

Tjenesten er en systemd-brukerenhet: ~/.config/systemd/user/sg-announcer.service (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). Finnes NetBird (wt0) skrur det på ufw med deny incoming og åpner 22 og porten kun på wt0. 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).

Hvordan det henger sammen

  • /api/preview syntetiserer og returnerer WAV til nettleseren. Ingen lyd på PC-en.
  • /api/announce legger meldingen i én FIFO-kø; en bakgrunnstråd spiller én om gangen med pw-play. /api/stop dreper gjeldende avspilling, /api/clear tømmer køen.
  • Knappen «Send ut» er låst til nøyaktig den teksten/stemmen/hastigheten som sist ble forhåndslyttet. Det er med vilje: ingen skal sende noe de ikke har hørt.
  • Ferdige WAV-er bufres i cache/ etter innholdshash. Trygt å slette.
  • Jingler: de innebygde (BUILTIN_CHIMES) genereres i Python med _tone/ _mix/_overlay, ingen lydfiler. Egne filer i chimes/ (wav/mp3/ogg/flac) dukker opp i menyen som file:<stem>; ffmpeg kutter til 6 s, normaliserer til -18 LUFS og fader ut. Mappa leses ved hver forespørsel, så nye filer vises uten restart. Toppnivå på de innebygde ligger mellom -4 og -10 dBFS, talen går til 0 dBFS, så jinglen skal aldri være høyere enn stemmen.

Stemmer og motorer

VOICES_LIST i announcer.py er eneste sted en stemme legges til. To motorer:

  • edge (_edge): Microsofts nevrale stemmer via edge-tts-pakken. Gratis, ingen nøkkel, men krever internett og er en uoffisiell bruk av Edge sin «les høyt»-tjeneste – kan slutte å virke uten varsel. Norsk: bare nb-NO-FinnNeural og nb-NO-PernilleNeural. *MultilingualNeural-stemmene kan lese norsk med engelsk aksent. Liste: uv run edge-tts --list-voices. Leverer MP3 24 kHz; dekodes med ffmpeg til PCM i edge_pcm().
  • piper (_piper): lokalt, robotaktig, reserve når nettet er nede. Modellen lastes ned ved oppstart til voices/ (gitignored). Norsk finnes bare som talesyntese-medium og nvcc-medium (ti talere, speaker-indeks). Full liste: https://huggingface.co/rhasspy/piper-voices/resolve/main/voices.json.

Vil Kent ha enda bedre lyd: ElevenLabs (nøkkel, best norsk) eller OpenAI gpt-4o-mini-tts er neste trinn; legg til som ny motor i synthesize().

Feller

  • ufw: appen kjører nativt, så Docker-smutthullet gjelder ikke. Porten må åpnes eksplisitt for LAN-et (sudo ufw allow from 10.20.70.0/23 to any port 8090 proto tcp).
  • pkill -f announcer.py fra et skall som selv har announcer.py i kommandolinja dreper skallet. Bruk systemctl --user.
  • Piper 1.8 bruker SynthesisConfig(length_scale=…); lavere = raskere.
  • Forhåndslytt svarer 502 med feilmelding hvis edge-tts feiler (ingen nett). Køen markerer meldingen som failed. Bytt til en lokal reserve-stemme.