announcer/AGENTS.md
Kent 756a234b13 Valgbare jingler: seks innebygde + egne filer i chimes/
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-06 03:50:48 +02:00

63 lines
3.4 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`.
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.