u/pinku1

SUB/WAVE - self-hosted internet radio with an AI DJ, runs on your Navidrome library

SUB/WAVE - self-hosted internet radio with an AI DJ, runs on your Navidrome library

Been building this for a few weeks and finally have it stable enough to share. It's a personal radio station that runs on one Linux box and broadcasts a single Icecast stream, everyone tuning in hears the same track at the same moment. No per-listener shuffle, no skip button. Properly like radio.

SUB/WAVE player

Admin dash

The DJ is an LLM. It picks the next track from your library, writes the links between songs, reads time/weather, and handles listener song requests in plain language. You can swap the LLM provider at runtime from the admin UI (Ollama, Anthropic, OpenAI, Google, OpenRouter) — same for the voice engine (Piper/Kokoro on-device, or ElevenLabs/OpenAI cloud).

The stack:

  • Icecast — single /stream.mp3 mount
  • Liquidsoap — crossfades, voice ducking, jingles, limiter
  • Node controller — the DJ brain, scheduler, TTS, HTTP API
  • Next.js PWA — player + admin console, installs to home screen with lock-screen controls
  • Navidrome (or anything Subsonic-compatible — Airsonic, Gonic, Funkwhale) for the music

The controller and Liquidsoap talk only through files in a shared state/ directory — no socket, no message queue. Unix-y and easy to debug.

Admin console has: a 24×7 schedule grid you paint shows onto, up to 12 DJ personas with their own voice and talk frequency, toggleable "skills" (weather check, news headline, station ID), and a mood tagger that walks your library and classifies tracks.

Live demo (currently spinning Punjabi music): https://radio.klair.co/listen

Landing: https://radio.klair.co

Repo: https://github.com/perminder-klair/subwave

MIT licensed. There's a npx subwave setup CLI for first boot, and DEPLOY.md covers the production walkthrough (Cloudflare + Caddy + Docker compose).

Happy to answer questions on the architecture or any of the trade-offs, the no-skip thing in particular was the call that shaped most of the design.

reddit.com
u/pinku1 — 1 day ago
▲ 12 r/radio+3 crossposts

Built a 24/7 Punjabi radio stream with an AI DJ — taking song requests live

Spun up a personal radio station that's been playing Punjabi music non-stop — Sidhu, Diljit, Sikander Kahlon, AP Dhillon, classics, the lot. It's one live stream, not a playlist, so everyone tuning in hears the same track at the same time. Properly like radio.

The twist: there's an AI DJ that picks the next track, talks between songs (time, weather, intros), and you can request any song in plain language, just type the artist or song name in the request box and it'll find it in the library and queue it up.

🎧 Listen: https://radio.klair.co/listen

No signup, no app, just open the link. Works on phone too — lock screen controls and everything.

Drop a request when you're on, would love to see what the community throws at it. Also genuinely curious which tracks you think have to be in a Punjabi station's rotation — I'll add anything missing.

reddit.com
u/pinku1 — 2 days ago

I made a tiny TUI for running Pi agents on local GGUF models via llama.cpp

I’ve been testing coding agents against local GGUF models and got tired of manually juggling llama-server flags, model paths, context sizes, ports, server state, and benchmark commands.

So I made locca: a small MIT-licensed CLI/TUI around llama.cpp.

It can:

- start or attach to llama-server

- fuzzy-switch GGUF models

- benchmark models with readable timings

- print OpenAI-compatible API info + LAN URLs

- launch the pi coding agent against a local model

- use sane defaults for iGPU/shared-VRAM machines

Install:

npm install -g @zeiq/locca

Repo:

https://github.com/perminder-klair/locca

Demo/site:

https://locca.klair.co/

I’d love feedback, especially from people running llama.cpp on AMD/iGPU/shared-memory boxes.

The main thing I’m trying to learn: are the defaults sensible outside my own machines?

locca.klair.co
u/pinku1 — 10 days ago