Engineering

The Day My Radio Hack Became a Programmable Broadcasting Platform

08 July 2026By Mike K8 min read

TL;DR: I started building a personal radio stream because I wanted tech, gaming, movie updates, weather, podcasts, and music without politics or noise. It began as a hack with RSS feeds, ElevenLabs voices, Suno-generated music, jingles, and Icecast, but slowly turned into a full geo-distributed Kubernetes-based radio platform with custom broadcasting, scheduling, Android TV playback, restreaming to YouTube/Twitch, AI-generated documentation, and an open beta.

Example of what came out:

You can also listen to other user-created radio stations on Tunio Streams.

How everything started

It was pouring rain. I was standing on the roof, silently watching the city through the rain. The city was drowning in its own noise.

Politics, scandals, intrigue, and investigations - all of it felt like raindrops falling onto my screen. I was looking for something else. Tech news, games, movies, and music that didn't tell me what to do.

So I built a radio for myself.

What started as a personal stream grew into a full-fledged platform. A platform for people who simply want to know and understand what is happening in the world.

That was how Tunio was born. I took my hands off the keyboard and lit a cigarette. A new day had begun.

The first version was basically one big hack:

  • Podcasts generated from a prompt. You give a subject and instructions, and the system creates a podcast, without previous episodes from the context.
Podcasts generated from a prompt
0:00
0:00
  • RSS audio. I connected popular RSS feeds for tech and gaming news. The system collects posts, filters out ads, negativity, and political content, summarizes the texts, and sends each story to ElevenLabs for narration. Then everything gets merged into a single audio block.
RSS audio
0:00
0:00
  • Weather forecasts. You can configure a list of needed locations, and the system fetches daily weather for today and tomorrow for each location, generates a spoken segment via ElevenLabs, and then merges everything into one unified weather block.
Weather forecast
0:00
0:00
  • Jingles and a jingle generator. This became possible by combining TTS APIs for generating short audio clips, plus some ffmpeg-based audio processing effects.
Jingles and a jingle generator
0:00
0:00

As the stream started to come alive, and with the evolution of Suno models improving music quality, I suddenly caught myself thinking: Holy shit, now finally you can listen to it.

The combination of live ElevenLabs voices and the latest Suno models made the whole stream feel much more natural. Because when I first started implementing the idea, Suno was at version 3.5 - and honestly, it was barely listenable unless it was instrumental, and even then not for more than 5 minutes.

I work as a system architect, and I didn’t want to build this on top of an existing broadcasting stack (like AzuraCast or similar platforms). I wanted to build something from scratch, and also improve my DevOps/SRE practices in the process.

After a few months of work, I already had my own geo-distributed Kubernetes infrastructure. Each radio station runs in its own isolated cluster on separate hardware, with its own database replicas, Icecast instance, and full stream orchestration.

Initially, I started with an Icecast + Liquidsoap setup, but over time I became unhappy with Liquidsoap’s CPU requirements. So I ended up writing a lightweight broadcaster in Go, which simply spawns FFmpeg per station and streams everything continuously into Icecast based on what the station’s rotation engine feeds into it.

What went wrong along the way:

Initially, I set up the system to broadcast, transcode, and store everything in MP3. But once I started implementing restreaming to platforms like YouTube and Twitch, it became clear that this format was not suitable - those platforms expect AAC, often wrapped in an M4A container.

That immediately introduced a new problem: real-time transcoding to AAC significantly increased CPU load, even for a single outgoing stream.

The M4A container for AAC is also more practical because it supports embedded metadata (including cover art) and preserves track duration correctly - unlike “raw” AAC streams. On the other hand, if you don’t use audio processing features like crossfades or effects in Liquidsoap, you can actually run everything in passthrough mode without transcoding at all, which makes CPU usage almost negligible.

So the lack of a unified AAC pipeline became one of the early blockers when I was trying to build a lightweight ffmpeg-based broadcaster.

At the early stage of the project, I was running everything on relatively cheap VPS instances. But both Liquidsoap and my custom broadcaster turned out to be quite CPU-hungry in real-time scenarios.

The problem was that most VPS providers I tried were heavily oversold. Hypervisor contention effectively “stole” CPU time, which meant my processes would randomly lose compute resources. This led to occasional audio artifacts and instability.

Hypervisor contention stole CPU time
Hypervisor contention stole CPU time

Once I switched to dedicated servers, this problem disappeared completely.

At the beginning, when I started building my personal internet radio, I really wanted everything to feel “professional”. I even ordered jingles a couple of times from commercial production studios.

But every time, the process turned into a long back-and-forth with the studio - aligning on voice selection, waiting for available voice actors (who were often booked), and in the end, the result didn’t always match my expectations.

Once I started generating jingles myself using ElevenLabs voices, most of these problems simply disappeared. I could get exactly what I needed - fast, cheap, and without any unnecessary coordination overhead. It also gave me the ability to produce jingles in multiple languages from the start. My first ElevenLabs jingles: Jingle #1, Jingle #2, Jingle 3

ElevenLabs Jingle 1
0:00
0:00
ElevenLabs Jingle 2
0:00
0:00
ElevenLabs Jingle 3
0:00
0:00

And then something else happened while I was still building the core system: Sonnet arrived.

Even after that, I kept doing a lot of things manually - including routine work like CRUD operations and defining new data models. Even after I had the infrastructure properly set up in code, I still wrote a lot of boilerplate by hand, which slowed me down more than I expected.

First signs of success

When the content generation was already working and the radio streams were running, I built a UI for managing the radio stations and shared it in private chats with friends.

I immediately received a lot of feedback and support. People started joining who were specifically interested in legally safe, royalty-free AI-generated music that they could confidently play in places like a stationery store or a gym. (Yes, those were my first real testers - and also my first source of product ideas.)

That’s how scheduling for radio streams appeared, as well as a dedicated Android TV player app. It connects to a station via a PIN code, plays the stream, and also caches tracks locally in case of internet outages. If the device detects that the internet is down, it automatically switches to offline mode and continues playing cached audio until the connection is restored.

And of course, AI agents.

Recently they’ve helped me a lot with UI localization into multiple languages, as well as generating user documentation with screenshots in different languages. I only had to give the agent access to a Playwright-enabled account, and it handled the rest - taking screenshots and writing documentation automatically.

I even spun up a Qdrant database over a weekend and fed it all the knowledge about the system, so I could reduce the load on support and avoid answering repetitive technical questions myself.

In conclusion, I want to say that at some point along the way - almost without realizing it - I somehow ended up with a much more serious radio system than I originally planned, and even a restreaming system for YouTube and other platforms.

It turned out to be a fault-tolerant system with a key advantage: the content itself can be generated directly inside the platform.

Right now, we’re running an open beta with free access for anyone who wants to test the system before paid plans are introduced. Also, we’re currently testing a virtual radio studio directly in the browser, so you can run live broadcasts and invite guests to connect and join the stream.

I also created a Discord server so I can share updates quickly, answer your questions, and collect feature requests and bug reports.

 

The Day My Radio Hack Became a Programmable Broadcasting Platform - Tunio Blog | Tunio