A radio station for your house, with a DJ who knows your music.
GenWave is my radio station. It plays my music library around the clock on my home network, with crossfades between tracks, every song at the same loudness, a DJ who knows what is playing and tells you about it, and yes, even some parody ads :) It runs on Docker on one box in my house. It is open source, so you can run your own too!
Contents: Features · Getting started · Why GenWave · Docs · Built with · Contributing · License
- 🎚️ Equal-power crossfades and loudness matching, so quiet and loud tracks play at the same volume.
- 🛟 The stream never stops. A safe rotation covers gaps, and the audio engine keeps playing even when the API or database is down.
- 🎙️ A DJ voice rendered on your own box (Kokoro, with Piper as the CPU-only fallback).
- 🧠 Optional local LLM (Ollama) writes what the DJ says between songs. Without one, the DJ uses templates.
- 🗓️ Named shows on a weekly schedule, so mornings and late nights sound different.
- 🎭 Personas: give the DJ a name, a voice and a style.
- 📣 Station sponsors and short parody ads, written and voiced on the box.
- 📻 A now-playing page for the house with song requests.
- 🛠️ An admin console for the library, schedule, voices and settings.
- 🧩 Plugins add new providers without forking the station.
- 🥧 Runs on amd64 and arm64. A 4 GB Raspberry Pi 5 is a known-good box.
You need Docker with Compose v2.24 or newer and a folder of .mp3 or .flac files. HARDWARE.md lists the boxes it runs on (currently).
- Get the code.
git clone https://github.com/GenWave-Org/genwave.git && cd genwave
- Run the setup wizard. It asks four questions, writes a
.envfile with fresh secrets, and starts your station../setup.sh
- Listen. Open
http://localhost:8000/streamin any audio player, and the admin console is available athttp://localhost:3000. Sign in with the admin password the wizard printed (it is alsoADMIN_PASSWORDin.env). - Expect "Please Stand By". You may hear it at first. That is normal: the station plays it, with a short pause between repeats, until the first tracks in your library are analysed, then the music starts.
Prefer a one-liner? download.genwaveradio.com fetches the exact same wizard without needing to clone the repo, etc.
Twenty-plus years ago, in my first job as a software engineer, we pulled a lot of all-nighters, fueled by music that IT graciously let us keep on one of their servers (the Exchange server, if memory serves). We'd bring in CDs, IT would rip them, and when the last non-engineer left for the night, someone would fire up a playlist and start the stream.
It was great, until it wasn't. The problem with playlists is that they're dumb: same music, same order, every time. Being engineers, we solved it! Sort of. I wrote a playlist generator that jumbled the order on every run. Problem solved! Except now we were hearing B-sides and artists nobody recognized, with no good way to find out what was playing. It felt more like real radio, and it left us with a thought that stuck, with me at least: wouldn't it be cool if we had DJs to announce the music? There was no way to build that back then, so we coerced our QA lead into recording a few sound bites, played one every X tracks, and christened the result FLAP Radio (because reasons).
The itch never went away. Over the years I built a home version of FLAP Radio. Still, honestly, a playlist randomizer, and I was never truly happy with it. Then, a couple of years ago, LLMs and TTS started making a serious splash, and the itch came back in earnest: the technology had finally caught up with the idea. This time GenWave was born for real: a station that never stops broadcasting, knows what it's playing, and has a DJ who tells you about it.
Itch scratched. 📻
| Doc | What is in it |
|---|---|
| DEPLOYMENT.md | Running it day to day: modes, services, settings, voices, troubleshooting |
| HARDWARE.md | Boxes it runs on, sizing, which LLM fits your hardware |
| PLUGINS.md | What a plugin is and how to write one |
| CONTRIBUTING.md | Building, testing, and the architecture rules |
| SECURITY.md | Reporting a security problem |
- Liquidsoap — the real-time mixing, crossfade, and encode engine underneath the whole broadcast.
- Icecast — fans the mixed stream out to every listener.
- Kokoro — the primary DJ voice, an open-weight TTS model rendered locally.
- Piper — the CPU-only fallback voice that keeps a DJ talking on modest hardware.
- Ollama — runs the local LLM that writes what the DJ says between songs when you point GenWave at one — the station airs template patter without it.
- ffmpeg — loudness, cue points, energy analysis: the numbers every crossfade decision rests on.
- aubio — the BPM analysis behind every track's tempo.
- PostgreSQL — the catalog of record for every track, measurement, and scheduled show.
GenWave is built with AI as a force multiplier, and every design decision, review and sign-off is mine; the .claude/ toolkit in this repo is how it gets built, and you are welcome to use it. Hats off to Rob Conery for his Claude Code Toolkit, and you can find the workflows I use here.
Bug fixes and small improvements are welcome. Read CONTRIBUTING.md first. Don't worry, it's short.
GenWave is licensed under the GNU Affero General Public License v3.0. The plugin contracts in src/GenWave.Abstractions/ are MIT, so a plugin can link them under any license you want.


