diff --git a/README.md b/README.md new file mode 100644 index 0000000..0288b90 --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# radio-go — AI Radio broadcast pipeline + +Endless AI-generated radio for your trusty MP3 internet stereo. + +Three stages, two machines: + +``` +┌─────────────────────┐ FLAC ┌──────────┐ mp3+playlist ┌───────────────────────────┐ +│ generator (anywhere)│ ────────► │ shipper │ ──────scp────► │ streaming VPS │ +│ LLM + ComfyUI/YuE2 │ library │ (Go bin) │ │ streamer ─► icecast ◄─Caddy│ +└─────────────────────┘ └──────────┘ │ │ now-playing │ + │ ▼ MQTT │ + └───────────────────────────┘ + │ + your stereo: https://…/ai-radio.mp3 +``` + +- **shipper** (generator machine): reads the ai-radio app's `library/index.json`, + builds a rolling newest-biased playlist, transcodes FLAC→MP3 (ID3-tagged so + the stereo display shows the title), ships `*.mp3 + playlist.m3u8 + titles.json` + to the VPS. +- **streamer** (VPS): plays the shipped files into an icecast mount as one + endless live stream, publishing a now-playing JSON to MQTT per track. + Survives the generator being asleep — replays what's on disk. +- **VPS bundle**: icecast (HTTP :8000 for old stereos) + Caddy (automatic HTTPS) + + streamer, all docker compose. + +## Quick start + +```bash +# build & test +go build ./... && go test ./... + +# generator side (needs ffmpeg): +cp .env.example ship.env && $EDITOR ship.env +set -a; . ./ship.env; set +a +go run ./cmd/shipper # loops; --once for a single cycle + +# VPS side: see vps/DEPLOY.md +``` + +## Docs + +| Level | File | Audience | +|---|---|---| +| Overview | this README | everyone | +| Architecture & design decisions | [docs/architecture.md](docs/architecture.md) | contributors | +| Configuration reference | [docs/config.md](docs/config.md) | operators | +| VPS deployment | [vps/DEPLOY.md](vps/DEPLOY.md) | deploying the server | +| Stereo setup | [docs/stereo-setup.md](docs/stereo-setup.md) | the listener | +| Code-level | godoc comments in `internal/` | developers | + +## Repo layout + +``` +cmd/shipper/ generator-side binary (library -> transcode -> scp) +cmd/streamer/ VPS-side binary (playlist -> icecast + MQTT now-playing) +internal/domain/ pure model: Track, playlist policy (no I/O) +internal/app/ use-cases: library load, transcode, ship +internal/infra/ adapters: m3u, icecast source proto, MQTT 3.1.1 client +vps/ docker-compose bundle (icecast + streamer + caddy) +tests/ e2e fakes (fake icecast + MQTT broker) +``` + +## Testing + +```bash +go test ./... # unit tests (domain/infra/app) +python3 tests/fakes.py & # fake icecast:18000 + mqtt:18883 +STREAM_WEBROOT=... ICECAST_ADDR=127.0.0.1:18000 MQTT_ADDR=127.0.0.1:18883 \ + go run ./cmd/streamer # e2e against the fakes +```