announcer/AGENTS.md
Kent ad1715838e 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>
2026-10-06 18:55:10 +02:00

68 lines
3.7 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.

# 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). 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.