{"slug": "personal-internet-radio-agentic-ai-dj", "title": "Personal internet radio: Agentic AI DJ", "summary": "Subwave launches a personal internet radio station powered by an agentic AI DJ that selects tracks, writes and speaks intros, station idents, time checks, and weather updates. The service streams a single shared broadcast via Icecast, allowing listeners to request songs in plain language while hearing the same content simultaneously. It supports custom music libraries, multiple TTS engines, and swappable LLM providers, aiming to recreate the communal radio experience with AI-driven curation.", "body_md": "**A personal internet radio station.** One Icecast stream, one broadcast.\nEvery listener hears the same thing at the same time. An AI DJ picks the\ntracks and talks between them: station idents, time checks, the weather,\na quick intro for whatever's going out next. You can ask for music in plain\nlanguage; the DJ works out what you meant and slots it in.\n\nIt's *radio*, not a playlist. No per-listener shuffle, no skip button, no\n\"up next for you.\" You tune in and hear whatever is on.\n\n## SUBWAVE.Showreel.1080p.mp4\n\n**Project site**—[getsubwave.com](https://www.getsubwave.com/)** Demo player**—[getsubwave.com/listen](https://www.getsubwave.com/listen)** Mobile apps**— native players —[iOS on the App Store](https://apps.apple.com/app/sub-wave/id6778786696),[Android on Google Play](https://play.google.com/store/apps/details?id=com.getsubwave.app)**Setup walkthrough**—[getsubwave.com/setup](https://www.getsubwave.com/setup)** Operator manual**—[getsubwave.com/manual](https://www.getsubwave.com/manual)** Community**—[join the Discord](https://discord.gg/vjVbVKnMBa)\n\n**The listener player.** One shared broadcast, with in-app song requests.\n\n**The admin console.** Where the operator runs the station.\n\n**The Library Observatory.** A data-art map of every track the DJ has tagged, placed by genre and lit by energy. Click a point for its full dossier: BPM, key, mood, embeddings, and nearest neighbours. Open it at `/observatory`\n\n.\n\n**One shared Icecast stream.** Every listener hears the same broadcast at the same time.**AI DJ that picks and talks.** Curates tracks, writes intros, and reads station idents, the time, and the weather.**Plain-language requests.**\"Play something more upbeat\" or \"anything by Radiohead\" works.** Your own music library.**Pulls from Navidrome over the Subsonic API. No external catalogue.** Swappable LLM provider.**Ollama, Anthropic, OpenAI, Google, DeepSeek, OpenRouter, Vercel AI Gateway, or any OpenAI-compatible server. Change it from the admin UI with no redeploy.**Five TTS engines.** Piper and Kokoro in-process for fast local speech, plus an optional`tts-heavy`\n\nsidecar (`docker compose --profile tts-heavy up -d`\n\n) that adds Chatterbox (zero-shot voice cloning) and PocketTTS (6× real-time, EN/FR/DE/IT/ES/PT). Cloud (OpenAI / ElevenLabs) is also available. Pick a different engine per kind of speech.**Multiple DJ personas.** Up to 10 souls in rotation, each with its own voice and writing style.**Dual-codec broadcast.** MP3 128 kbps for Sonos, hardware radios, and cars; Ogg-Opus 96 kbps for modern browsers. The web player picks automatically.**Native apps and PWA.** Native iOS (on the App Store) and Android (on Google Play) players — background audio, lock-screen / CarPlay / Android Auto controls, multi-station — plus an installable PWA on phone and desktop.**Scheduled shows.** A 24×7 grid; each slot has its own persona, mood, and skills.**Pluggable skills.** The DJ's between-track segments — weather, news, traffic, and your own — are skills. The built-ins are scaffolded as editable files under`state/skills/<kind>/`\n\non first boot, so you can rewrite a brief or change the news feed (BBC → your own RSS) right from the admin console — no code, no redeploy. Add your own by dropping a`SKILL.md`\n\n(plus optional data-fetching code) into`state/skills/`\n\n, hitting Rescan, and enabling it. See.`docs/custom-skills.md`\n\n**Mood-aware rotation.** Time of day, weather, and festival days bias what gets played and how the DJ talks.**Hourly archives.** Every hour saved as MP3 for later replay.**Crossfade + voice ducking.** Tracks blend smoothly; the music ducks under DJ speech and lifts back up.**Admin console.** Live status, queue, booth log, personas, shows, skills, stats, and a debug view of recent LLM calls.**Library Observatory.** A full-screen, data-art map of every tagged track at`/observatory`\n\n— placed by genre, lit by energy, with a full dossier per track (BPM, key, mood, embedding fingerprints, and nearest-in-vector-space neighbours). Scales from a few hundred to tens of thousands of tracks.**MCP server.** External agents (Claude Desktop, Cursor, etc.) can request songs and drive the DJ.**Self-hosted.** One`docker compose up -d`\n\non a single Linux host. Optional Cloudflare in front for TLS.\n\nA playlist is a list you control. Radio is a broadcast you join. SUB/WAVE is the second kind:\n\n**One shared stream.** A single Icecast mount everyone connects to. Everyone hears the same audio at the same instant. That's what makes it a station instead of a jukebox.**No skip.** Track-end is the only natural transition. The DJ — human-curated personas plus an LLM — owns the pacing, not the listener. (Operators*can*skip via the admin API; listeners cannot.)**AI as the DJ, not the catalogue.** The music is your own library, served by Navidrome over the Subsonic API. The LLM picks what's next and talks between tracks. It doesn't generate music and it doesn't replace your taste.**Self-hosted and swappable.** Runs on one Linux box behind Cloudflare. The LLM provider is swappable at runtime (Ollama, Anthropic, OpenAI, Google, OpenRouter, Vercel AI Gateway) with no redeploy.\n\n```\ncurl -fsSL https://cli.getsubwave.com | sh    # installs, then offers to init + start\nsubwave setup                              # connect Navidrome + LLM\n```\n\nTwo Enter prompts during the installer (`Run subwave init now?`\n\n, then\n`Bring the stack up now?`\n\n) and the stack is on-air. `subwave setup`\n\nconnects Navidrome and your LLM, or do the same in the browser at\n`http://localhost:7700/onboarding`\n\n.\n\nNo clone, no Node on the host. `subwave status / logs / doctor / update`\n\nwork from anywhere afterwards.\n\nIf you'd rather skip our binary on your host and stick to `docker compose`\n\n:\n\n```\nmkdir subwave && cd subwave\ncurl -O https://raw.githubusercontent.com/perminder-klair/subwave/main/docker-compose.yml\ncurl -O https://raw.githubusercontent.com/perminder-klair/subwave/main/.env.example\nmv .env.example .env\n# Edit .env: set ADMIN_USER, ADMIN_PASS, SITE_URL (three vars, that's it).\ndocker compose up -d\n# Then open https://your-host/onboarding. The web wizard collects Navidrome,\n# LLM, TTS, DJ persona, and offers to render jingles.\n```\n\nFunctionally identical: same images, same state layout, same persistence.\nThe CLI just saves you the curl-and-edit dance and gives you `subwave logs`\n\n,\n`subwave doctor`\n\n, etc. for the rest of the lifecycle.\n\nChatterbox (zero-shot voice cloning) and PocketTTS (fast multilingual) live in\na separate `subwave-tts-heavy`\n\nsidecar that adds ~5–6 GB of PyTorch and is\n**not** started by default. To enable:\n\n```\ndocker compose --profile tts-heavy up -d\n```\n\nThe controller is wired up to discover the sidecar automatically. Stop it\nagain with `docker compose --profile tts-heavy stop tts-heavy`\n\n; the rest of\nthe stack keeps running and Chatterbox/PocketTTS personas silently fall back\nto Piper. The old `docker build --build-arg WITH_CHATTERBOX=1`\n\npath still\nworks if you already have a custom-built controller image — see\n`docker/Dockerfile.controller`\n\n.\n\n```\ngit clone https://github.com/perminder-klair/subwave.git && cd subwave\n./scripts/setup.sh                                  # scaffolds a 3-var root .env + state/\ndocker compose -f docker-compose.dev.yml up -d      # Broadcast (icecast2 + liquidsoap) + Controller\ncd web && npm install && npm run dev                # web UI on :7700, separate and hot-reloading\n# Then http://localhost:7700/onboarding to finish configuration.\n```\n\nDev compose bind-mounts `controller/src/`\n\n, `radio.liq`\n\n, and `sounds/`\n\nfrom the\nrepo. Controller runs under `tsx watch`\n\nso `src/**`\n\nedits hot-reload inside\nthe container; `radio.liq`\n\nedits just need a `docker compose -f docker-compose.dev.yml restart broadcast`\n\n.\n\nThe standalone `subwave`\n\nCLI works inside the cloned repo too. `cd subwave && subwave start dev`\n\ndoes the right thing. The contributor convenience is `npm start`\n\n, which `tsx`\n\n-runs the CLI source directly so unreleased changes are\nexercised. Same commands, same flags, no `npm install -g`\n\nneeded.\n\nThe same CLI doubles as the console for running the station. Run `npm start`\n\nfor a status-aware menu; every menu action is also a one-shot subcommand,\nappended after `npm start --`\n\n:\n\n```\nnpm start                       # interactive operator console (status-aware menu)\nnpm start -- setup              # first-boot wizard: Navidrome, LLM, admin, env files\nnpm start -- status             # compose env, services, now-playing, recent events\nnpm start -- doctor             # full diagnostic sweep\nnpm start -- start dev          # docker compose up -d (dev or prod)\nnpm start -- restart broadcast  # plain restart (radio.liq is bind-mounted in dev)\nnpm start -- restart controller # rebuild + recreate (source is COPY-d at build)\nnpm start -- logs controller    # tail one service\nnpm start -- listen             # open the web player in a browser\nnpm start -- admin              # open the admin console in a browser\nnpm start -- stop               # docker compose down (confirms first)\n```\n\nSingle Linux host, Cloudflare terminating TLS, Caddy routing to four internal\nservices. The [no-CLI quickstart above](#quick-start-no-cli-raw-docker) is\nthe canonical path: `curl`\n\ntwo files, fill in three vars, `docker compose up -d`\n\n, finish setup in the browser. See for host\nprerequisites, Cloudflare setup, updates, and backup.\n\n`DEPLOY.md`\n\n**On Unraid?** One-click install from ** Community Applications**\n(search\n\n**SUB/WAVE** in the Apps tab) — or run the full split-container stack via the Compose Manager Plus plugin. Both in\n\n**.**\n\n`docs/unraid.md`\n\n**Bring your own reverse proxy.** If you already run Traefik, nginx, or your\nown Caddy in your homelab, swap the bundled-Caddy compose for the BYO variant:\n\n```\ndocker compose -f docker-compose.byo.yml up -d\n```\n\nThat exposes the web UI on `:7700`\n\n, the controller API on `:7701`\n\n, and the\nIcecast stream on `:7702`\n\n(all configurable). Point your proxy at those three.\n`docker/Caddyfile`\n\nis a working reference for the route table you need to\nreplicate. Details in [ DEPLOY.md](/perminder-klair/subwave/blob/develop/DEPLOY.md#bring-your-own-reverse-proxy).\n\n**Images on GHCR.** Tagged releases publish to `ghcr.io/perminder-klair/subwave-{caddy,broadcast,controller,web}`\n\n.\nAll compose files pull `:latest`\n\nby default; pin a version with\n`SUBWAVE_VERSION=v1.2.3`\n\nin the root `.env`\n\n.\n\n```\ndocker-compose.yml      Production deploy with bundled Caddy (default)\ndocker-compose.byo.yml  Production deploy for hosts with their own reverse proxy\ndocker-compose.dev.yml  Local dev (broadcast + controller only; web runs separately)\ncontroller/        Node.js controller, the AI DJ brain\n  src/llm/         LLM layer (AI SDK): provider registry, prompts, tools\n  src/broadcast/   queue, session, DJ agent, scheduler, jingles\n  src/music/       Subsonic client, pool picker, library tagging\n  src/audio/       TTS engines: Piper, Kokoro, Chatterbox, PocketTTS, cloud\n  src/routes/      HTTP API split by surface (public, request, onboarding, settings, …)\nliquidsoap/        radio.liq, the Liquidsoap mixing pipeline\nweb/               Next.js 15 web UI (player, landing, admin, setup)\ndocker/            Caddyfile, Dockerfiles, icecast.xml.template, supervisor entrypoint\nscripts/           setup, jingle generation, update, health check\nmcp-subwave/       MCP server that lets an agent request songs / drive the DJ\ncli/               Operator CLI (TS, run via tsx loader, no build step)\nbin/subwave        Operator CLI entry: setup, status, doctor, lifecycle\n```\n\n**Controller code needs a rebuild, not a restart**, because its source is`COPY`\n\nd at image build time.`radio.liq`\n\nis bind-mounted, so a Liquidsoap restart is enough after editing it.**The LLM provider is swappable at runtime** from the admin UI. Every model call goes through the Vercel AI SDK.**There is no** Track-end is the only natural transition; operators have an admin-only skip endpoint.`/skip`\n\nfor listeners.**Navidrome ≥0.62 is recommended.** It ships several security hardening fixes (internet-radio management now admin-gated, transcode-config disclosure restricted to admins, concurrent-transcode DoS limits) and the OpenSubsonic`sonicSimilarity`\n\nextension. SUB/WAVE streams with`format=raw`\n\nso the transcode limits never throttle the radio, and when`sonicSimilarity`\n\nis enabled the picker automatically folds Navidrome's audio-based neighbours in as an extra track-selection source — no config, capability-probed, and a silent no-op when the extension is absent. Any reasonably recent Navidrome still works.- Several areas (queue/playback path,\n`radio.liq`\n\n, the crossfade, voice ducking, the LLM layer) have**non-obvious constraints** that are easy to regress. Read the relevant note inbefore touching them.`CLAUDE.md`\n\nproduction deployment, updates, backup.:`DEPLOY.md`\n\nrunning on Unraid — one-click from Community Applications, or the Compose Manager Plus stack.:`docs/unraid.md`\n\nthe optional heavy sidecar — expressive voices and acoustic analysis, and how to turn it on.:`docs/tts-heavy.md`\n\ndeep architecture reference and the non-obvious constraints behind each subsystem.:`CLAUDE.md`\n\nhow to contribute.:`CONTRIBUTING.md`\n\nreporting security issues.:`SECURITY.md`\n\nthe MCP server.:`mcp-subwave/README.md`\n\nSUB/WAVE is playback and automation software. It does **not** grant you any\nrights to the music you broadcast through it, and it ships with no licensed\ncontent.\n\nOwning a file — a purchased download, a CD you ripped, anything in your\nNavidrome library — covers your own private listening. It does **not** cover\n**public performance**. The moment SUB/WAVE streams to anyone but you, you are\npublicly performing copyrighted works, which in most countries requires\nlicences for *two* separate rights:\n\n- the\n**musical composition**(songwriting) — e.g. PRS for Music (UK), ASCAP / BMI / SESAC (US); - the\n**sound recording**(the master) — e.g. PPL (UK), SoundExchange (US, under the statutory webcasting licence and its DMCA §114 conditions).\n\nYou are the broadcaster and you are solely responsible for clearing those\nrights. If you don't want to obtain licences, run the station privately (see\n[DEPLOY.md → Make the station private](/perminder-klair/subwave/blob/develop/DEPLOY.md#make-the-station-private-cloudflare-access)),\nor broadcast only content you're cleared to use — music you created or own the\nrights to, Creative-Commons-licensed tracks, royalty-free libraries, or\npublic-domain recordings.\n\nThis is general information, not legal advice. If you run a public station, talk to a media/IP lawyer in your jurisdiction.\n\n[MIT](/perminder-klair/subwave/blob/develop/LICENSE).", "url": "https://wpnews.pro/news/personal-internet-radio-agentic-ai-dj", "canonical_source": "https://github.com/perminder-klair/subwave", "published_at": "2026-06-25 14:34:54+00:00", "updated_at": "2026-06-25 14:44:09.466409+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-products", "ai-tools", "large-language-models", "generative-ai"], "entities": ["Subwave", "Icecast", "Navidrome", "Subsonic", "Ollama", "Anthropic", "OpenAI", "ElevenLabs"], "alternates": {"html": "https://wpnews.pro/news/personal-internet-radio-agentic-ai-dj", "markdown": "https://wpnews.pro/news/personal-internet-radio-agentic-ai-dj.md", "text": "https://wpnews.pro/news/personal-internet-radio-agentic-ai-dj.txt", "jsonld": "https://wpnews.pro/news/personal-internet-radio-agentic-ai-dj.jsonld"}}