70 lines
3.8 KiB
Markdown
70 lines
3.8 KiB
Markdown
# 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.
|