The track, the artist, the booth.
The player opens on whatever is on air: cover art pulled straight from your library, title, artist, album, and elapsed time. A waveform tracks the audio underneath. It is not your queue. It is the station’s.
A REAL INTERNET RADIO STATION
One stream, an LLM behind the desk, and a music library that already belongs to you. We spent a week tuned in to find out what a personal radio station actually feels like.
PART ONE · THE PLAYER
Open the player and you join a broadcast already in progress. Here is what a listener actually sees.
The player opens on whatever is on air: cover art pulled straight from your library, title, artist, album, and elapsed time. A waveform tracks the audio underneath. It is not your queue. It is the station’s.
Two drawers slide out from the side. The Timeline shows tracks queued and recently played; the Booth is a live log of every word the DJ has spoken: station IDs, time checks, weather, the links between songs.
There is no skip control for listeners. A stray double-tap on someone’s headphones should not change the song for everyone else. Track-end is the only natural transition. Radio behaves like radio.
Native iOS and Android apps are on the stores, and the web player installs as a PWA. The OS media controls wire straight through, so the lock screen, your headphones, and the car display all show the station. Old-school hardware? /listen.m3u and /listen.pls tune in VLC, Sonos, and internet radios.
PART TWO · THE DJ
The voice between the tracks is not air talent. It is a persona (a name, a soul, a voice engine, a talk frequency) driven by a language model.

The DJ reads the time, the weather, the season, festivals on the calendar, what just played, and any listener requests, then asks an LLM what should come next and pulls a real song from the library.
Intros, time checks, weather reads, and station idents are all written live in the DJ’s voice, then spoken aloud and ducked under the music. Nothing is pre-recorded.
A scheduled show can hand the hour to a different persona, signed off live on air, and seat up to three guest co-hosts who trade banter with the host. The 3am host is not the 8am host.
THE DJ’S MIND
Every track the DJ knows, mapped by how it sounds — clustered by genre, lit by energy. This is the library it reaches into when it chooses what comes next. Hover a star to read it; click one to see what it would mix into. (A sample library below; your own catalogue draws its own.)
And both the model doing the thinking and the voice doing the talking are the operator’s to choose — that is what comes next.
PART THREE · THE STACK
The mind that picks the tracks and the voice that reads them out are two separate, swappable seams. Choose a language model, choose a speech engine, clone a voice if you want one. Change either in the console and the next line on air uses it. No redeploy.
Every pick, every intro, every weather read goes through one provider-agnostic seam. The default is a local Ollama box: private, no API key, nothing leaves the house. Prefer a hosted model, an aggregator with one key for every vendor, or your own OpenAI-compatible server (llama.cpp, vLLM, LM Studio)? The call sites never name a provider, so switching is a single dropdown. A daily token budget caps what a hosted model can spend; hit it, and the music keeps playing without the chatter.
Local engines run on-device: Piper is the fast default and the safety net, Kokoro trades speed for a warmer read. Or stream a cloud voice from OpenAI or ElevenLabs. Every persona carries its own voice, and you can hand a different one to each kind of segment, so the station ID need not sound like the late-night host.
Drop a short reference clip in the voices folder, point a persona at it, and that DJ speaks in the cloned voice from the next line on. Chatterbox does it zero-shot from a single WAV (and renders paralinguistic cues like a laugh or a sigh); PocketTTS clones from a .wav too; and a custom Piper voice pair drops straight in. The 3am host can sound like anyone you have a clip of, entirely on your own box.
PART FOUR · REQUESTS
Requests are the one place a listener steers the broadcast. And it works the way calling a radio station always should have.
Open the request drawer and type what you want: a song title, an artist, a vibe. No exact spelling, no library browsing. Add your name if you want the DJ to use it on air.
“Got it — taking it to the booth.” The acknowledgement is immediate while the matching happens in the background, so the drawer never just sits there.
An LLM reads your request, searches the library, and picks the closest real track. Suggestion chips (built from the current artist, the time of day, the weather) give you a head start if you are undecided.
When the match lands, the drawer shows the track and the DJ’s spoken intro. Your request joins the one queue everyone is hearing, and the DJ may say your name as it goes out.

PART FIVE · THE CONSOLE
Everything a listener hears is shaped from one place: a gated admin console. This is where the operator actually runs the station.

Live status: who is on air, the mood, listener count, weather. See the queue, read the booth log, skip a track, fire a station ID, or send your own words to air as raw or styled voice.
Up to twenty-four DJ identities: name, soul, tagline, talk frequency, voice, and which skills each one may use. One persona hosts at a time; a show can hand it the hour and bring guests into the booth. Or install a ready-made host from the community catalog.
Each skill is an autonomous segment: a weather check, a news headline, a dig on the song playing, an oddly-specific fact. Toggle each one on, assign it to a persona, or run any one now. Write your own in the built-in editor, or install one from the community exchange.

A 24×7 grid you brush shows onto. Each show carries a persona, a music mood, and a topic brief: genres, eras, the host’s tone. Or anchor it to a Navidrome playlist and let the DJ pick from that. Autonomous hours fill whatever you leave blank.

Search the Navidrome library by text, mood, and energy, queue any track, and browse recent additions. The mood tagger walks the library album-by-album and classifies every track.
Debug and Stats show health, Liquidsoap logs, LLM call history, and usage at a glance. DJ Doc runs a full station check-up and has your own LLM review the findings. Settings (TTS, LLM, mixer, jingles) and a danger zone that starts, stops, and restarts the broadcast.


PART SIX · UNDER THE HOOD
No subscriptions, no round-trip to a data center, no algorithm tuned to keep you scrolling. The whole source is open, so you can run your own with a different DJ persona, a different library, and a different city on the dateline.
Streaming apps gave everyone their own private channel. A playlist tuned to you, shuffled for you, paused the second you look away. SUB/WAVE goes the other direction entirely. It is one Icecast stream, a single broadcast every listener hears at the same moment, picked, announced, and mixed by software running on a single box in someone's home. No skip button. No “for you.” You tune in, and you hear whatever is on the air right now, the same as everyone else.
WORKS WITH YOUR LIBRARY
SUB/WAVE is the DJ, the mixer, and the broadcast layer. The music comes from your Navidrome, the self-hosted music server with a Subsonic API. Run Navidrome on your homelab, point SUB/WAVE at it, and the DJ picks from your collection. Nobody else’s algorithm. Nobody else’s catalogue.
ALSO WORKS WITHNavidromeSubsonicAirsonicGonicFunkwhaleNextcloud Musicanything Subsonic-API compatible
END OF FEATURE
Nothing to scroll, nothing to pick. Tune in and hear what the DJ is playing, or stand up your own frequency from the source.
Get the app:App Store Google Play