Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ Eight services start: `db`, `icecast`, `engine`, `api`, `kokoro` (TTS synthesize
- **API:** `http://localhost:8080` β€” anonymous hot path (`GET /media/random`, `GET /media/{id}`, `GET /health`) plus the cookie-auth admin surface under `/api/*`
- **Spectator page:** `http://localhost:8081` β€” the station's read-only public face (now playing, history, stats, an optional anonymous song-request line with free-text wishes plus genre/mood pickers). Off by default: flip the live `Station:SpectatorMode` setting to enable it; [DEPLOYMENT.md](DEPLOYMENT.md) covers the four operating modes and the public topology. Metadata-aware players also get **per-track album art** via ICY `StreamUrl` once `Station:PublicBaseUrl` is set.

On first boot the library scans `MEDIA_DIR`, enriches each file (loudness + cue + energy + BPM + tags, plus a high-confidence MusicBrainz release-year lookup when the tags carry none β€” disable-able live via `Library:YearLookup:Enabled`), and the feeder begins pulling ready tracks. Until the first tracks are ready, the engine plays the safe-rotation source β€” a curated library scope (`Station:SafeScope:LibraryIds`) pulled via `GET /internal/safe-track`. On a fresh deploy, a one-shot boot seed creates a `safe` library, renders a branded TTS announcement ("Please Stand By"), and points SafeScope at it β€” so drains air the announcement, not a random track; an operator-set SafeScope is never overwritten. If the scope resolves empty, `mksafe` emits silence as a logged degraded mode. The Orchestrator interleaves TTS patter (station IDs, lead-ins, back-announces β€” and, opt-in, top-of-hour time checks plus weather and this-day-in-history segments) with music once Kokoro is up. When an `Llm:Endpoint` is configured (Settings page β€” live, no restart), lead-ins and back-announces become LLM-authored copy, optionally in an operator-authored DJ persona's voice (Personas page) β€” or hire a ready-made DJ from the community [Community Catalog](https://github.com/GenWave-Org/genwave-catalog) (CC0 persona cards, browsed and adopted one-click from the Admin UI after a full-card review); with no LLM configured the template patter airs unchanged. Station identity (`STATION_NAME`, voice, scope) defaults to `GWAV 108.8` / `af_heart` / library 1 β€” override via env if needed.
On first boot the library scans `MEDIA_DIR`, enriches each file (loudness + cue + energy + BPM + tags, plus a high-confidence MusicBrainz release-year lookup when the tags carry none β€” disable-able live via `Library:YearLookup:Enabled`), and the feeder begins pulling ready tracks. Until the first tracks are ready, the engine plays the safe-rotation source β€” a curated library scope (`Station:SafeScope:LibraryIds`) pulled via `GET /internal/safe-track`. On a fresh deploy, a one-shot boot seed creates a `safe` library, renders a branded TTS announcement ("Please Stand By"), and points SafeScope at it β€” so drains air the announcement, not a random track; an operator-set SafeScope is never overwritten. If the scope resolves empty, `mksafe` emits silence as a logged degraded mode. The Orchestrator interleaves TTS patter (station IDs, lead-ins, back-announces β€” and, opt-in, top-of-hour time checks plus weather and this-day-in-history segments) with music once Kokoro is up. When an `Llm:Endpoint` is configured (Settings page β€” live, no restart), lead-ins and back-announces become LLM-authored copy, optionally in an operator-authored DJ persona's voice (Personas page) β€” or hire a ready-made DJ from the community [Community Catalog](https://github.com/GenWave-Org/genwave-catalog) (CC0 persona cards, browsed and adopted one-click from the Admin UI after a full-card review); with no LLM configured the template patter airs unchanged. A weekly **format clock** (Schedule page β€” a drag-paint 7Γ—48 grid) decides who's on the air when, with audible DJ-to-DJ handoffs at the boundaries; since v3.4.0 the hours have names too: **shows** (a name, a tagline, and a flavor line that colors the DJ's patter) assign to whole runs in one click, sign-ons welcome you to the named show, top-of-hour idents brand it, dated **specials** shadow the weekly grid for one-off broadcasts, and the spectator card tells listeners what's on now and up next. Station identity (`STATION_NAME`, voice, scope) defaults to `GWAV 108.8` / `af_heart` / library 1 β€” override via env if needed.

The station's look is themeable too (v3.0.0–v3.2.0). A theme is one JSON manifest β€” colour tokens for light and dark plus curated fonts β€” composed live into CSS for both the Admin UI and the spectator page; pick one via Settings or the switcher on either surface (a cookie-remembered visitor choice outranks the station default). The Community Catalog generalized from a persona-only shelf into a multi-kind one β€” personas, themes, and Dean-curated font packs, all adopted through the same one-click review flow. Installed font packs list on the **Wardrobe** page (v3.1.0), which is also where a pack is uninstalled β€” refused while a saved theme still references one of its faces; the **theme editor** (`/editor`, v3.2.0) mixes any theme's palette with a vendored-or-installed face and saves the remix as your own station theme.
The station's look is themeable too (v3.0.0–v3.2.0). A theme is one JSON manifest β€” colour tokens for light and dark plus curated fonts β€” composed live into CSS for both the Admin UI and the spectator page; pick one via Settings or the switcher on either surface (a cookie-remembered visitor choice outranks the station default). The Community Catalog generalized from a persona-only shelf into a multi-kind one β€” personas, themes, shows (v3.4.0), and Dean-curated font packs, all adopted through the same one-click review flow. Installed font packs list on the **Wardrobe** page (v3.1.0), which is also where a pack is uninstalled β€” refused while a saved theme still references one of its faces; the **theme editor** (`/editor`, v3.2.0) mixes any theme's palette with a vendored-or-installed face and saves the remix as your own station theme.

### Resilience & operator tools

Expand All @@ -77,7 +77,7 @@ The broadcast never depends on a sick dependency. **LLM failure is a mode, not a
β”‚ └─ genwave.liq # Liquidsoap playout script
β”œβ”€ db/
β”‚ β”œβ”€ 01-library.sh # library schema + library_svc role (canonical fresh install)
β”‚ └─ 02..34-*-migration.sh # idempotent in-place upgrades, one per shipped feature β€”
β”‚ └─ 02..36-*-migration.sh # idempotent in-place upgrades, one per shipped feature β€”
β”‚ # each header says what it adds; ./migrate.sh applies them all
β”œβ”€ icecast/
β”‚ β”œβ”€ Dockerfile # self-owned Icecast2 image
Expand Down
Loading