SUB/WAVE
The Journal · Radio, not a playlist

Dispatch

A field guide to putting your library on air

From a folder of FLACs to a 24/7 broadcast with an AI DJ: the minimal path through Navidrome, Docker, and the SUB/WAVE stack — and the three mistakes everyone makes on night one.

There is a particular pleasure in hearing your own library announced back to you by a DJ at three in the morning. Getting there takes one evening, one machine that stays on, and a music folder you actually care about. This is the short route, with the potholes marked.

What you're actually assembling

Four pieces, each replaceable, none optional:

PieceJobThe default
LibraryServes your music over Subsonic APINavidrome
ControllerPicks tracks, builds the DJ's contextSUB/WAVE
VoiceTurns DJ text into speechAny TTS engine
TransmitterOne shared stream for every listenerIcecast

The important architectural fact: SUB/WAVE never touches your files. It asks Navidrome for them the way any Subsonic client would, which means your library stays wherever it already lives.

Night one

Point it at your music

docker-compose.yml
services:
  navidrome:
    image: deluan/navidrome:latest
    ports:
      - '4533:4533'
    volumes:
      - ./music:/music:ro
      - ./data:/data

The :ro on the music mount is not decoration — nothing in this stack should ever need write access to your library.

Wire up the station

git clone https://github.com/perminder-klair/subwave
cd subwave
cp .env.example .env
# set NAVIDROME_URL, NAVIDROME_USER, NAVIDROME_PASS, LLM + TTS keys
docker compose up -d

Then open the admin, run the library scan, and wait for the tag report. Which brings us to the potholes.

Hear it

# the stream is just an Icecast mount — anything can play it
mpv http://localhost:8000/radio

If you hear music, then a voice, then music — you're a broadcaster now.

The parts people over-think

Hardware. A used mini-PC or a Raspberry Pi 5 is plenty. The heavy lifting is the LLM and TTS, and both can be API calls; the box itself just moves audio.

The reverse proxy. It's one Icecast port and one web port. Whatever you already use — Caddy, nginx, Traefik — the config is ten lines.

Uptime. This is a radio station, not a bank. If it goes down overnight, the morning show simply starts with a slightly embarrassed DJ. There's something honest about that.

Why bother

You could open any streaming app and get more music with less effort. But it wouldn't be yours — not the library, not the voice, not the 3 a.m. programming decisions. Self-hosting a station is the difference between owning records and renting a mood. The stack above is one evening of work; the feeling of your own call sign is surprisingly permanent.


Full documentation lives at getsubwave.com/setup, and the whole stack is open source.