Loading…

Creating a Radio Station with Docker

·

Creating a Radio Station with Docker

I love music. I have been curating and collecting tunes since the nineties, when I had to go to the library to download MIDI files, which I would bring home on 3.5in floppy disks.

My dad had an old Toyota Corolla filled with carefully hand-curated mix-tapes, but I was the one who figured out how to burn mixes on to CDs.

Opening Pandora's Box

I couldn't quite afford a proper iPod, but every picture of me from 2005 through 2008 contains a bright white iPod Shuffle — a now-embarrassing fashion choice, but that Shuffle was my constant companion and its mp3 mix was of critical importance.

Pandora changed how I listened to music again, exposing me to algorithmic analysis of my tunes and helping me to find new songs to jam to.

Rdio was better — I could listen to any tunes that I wanted and share them with my friends.

With Spotify I could sync them to my devices really easily.

With Google Music I could also add my own tracks, which let me load loads of OCRemixes and Soundcloud songs back into my playlists.

These services, though, took a lot of power away from me. I wasn't really curating my music anymore.

The Weighting Game

Okay, let's talk about the Cake problem. Or the Tragically Hip problem. Or the Madonna problem. Or the Harry Belafonte problem.

I want to have a Cake song in my playlist.

But I don't want that Cake song to be, uh, the _same_ Cake song every single time. They have a lot of good songs.

On the other hand, there are some songs — Lone Digger, or Violet Stars Happy Hunting / Many Moons that I can listen to again and again and again.

I want to listen to the song "Lone Digger" about as often as I want to listen to one song, selected randomly, from the entire Cake discography.

The problem with modern playlists is that a band's likelihood of coming up in the playlist is, uh, inherently tied to how many songs from that band you put in the playlist. Some bands have so many hits that when you drop them in to a playlist, the playlist becomes _theirs_.

Two Goals

Creating a Radio Station with Docker

  1. I want to control not just the songs in my playlist, but their relative weights when being selected by the randomization algorithm.

  2. I want to be able to control and stream my own music collection, from anywhere.

Those of you who are familiar with Icecast probably know where this story is headed. An open-source solution to this problem has existed for ages. I just had to build a streaming server.

The Laziest System Operator of Them All

Why Docker, though?

Okay, so, this is a different part of the story, but I run my own dedicated server, because I like burning money, and also because I run a lot of personal projects and I started to get frustrated trying to track down all of them.

There's one rule on the dedicated server to keep the process model neat and tidy: the only things it keeps running are Docker, and Nginx. If I want to run a service, it has to be containerized. It makes managing this beast _very easy_.

Bash, Secret King of the Automation Languages

So, the entire app is just a shell file that creates config files and boots up docker containers. That's it.

We start by killing the container, if it's running right now

sudo docker kill $ICECAST_CONTAINER_NAME
sudo docker rm $ICECAST_CONTAINER_NAME

Then we write an icecast.xml file:

cat >./icecast.xml <<END
<icecast>
    ...
</icecast>
END

Then, we boot up an icecast container &mdash; thanks, moul.

sudo docker run \
    -p 127.0.0.1:$ICECAST_PORT:$ICECAST_PORT \
    --name $ICECAST_CONTAINER_NAME \
    -v `pwd`/icecast.xml:/etc/icecast2/icecast.xml \
    -d moul/icecast

Icecast just exists to stream an audio (or video) source &mdash; it isn't, in and of itself, an audio source.

So, we need to do the same things we've just done with Icecast to a separate application, called LiquidSoap.

LiquidSoap contains a _powerful scripting language_. It is a scripting language for playlists &mdash; I have trouble imagining something more exciting than this specific technology.

So We Kill and Boot LiquidSoap in the Shell File, Too


sudo docker kill $LIQUIDSOAP_CONTAINER_NAME
sudo docker rm $LIQUIDSOAP_CONTAINER_NAME

cat >./liquidsoap.liq <<END
#!/usr/bin/liquidsoap
...
END

sudo docker run \
    -p 127.0.0.1:$LIQUIDSOAP_PORT:$LIQUIDSOAP_PORT \
    --name $LIQUIDSOAP_CONTAINER_NAME \
    -v `pwd`/liquidsoap.liq:/tmp/config.liq \
    -v $HOST_MUSIC_DIRECTORY:$MOUNT_MUSIC_DIRECTORY \
    -d moul/liquidsoap \
sudo -H -u www-data bash -c 'liquidsoap --debug --verbose /tmp/config.liq'

Anyways, the Whole Thing is Simple Enough To Be A Github Gist

And here it is:

It _should_ be simple enough that you can read it and modify it to your own tastes, if you want to run your own internet radio station.

When That's Done

So, with that running on a server, we're running icecast on a port - 8000 - and we can connect to our server at serverdomain.com:8000/groove.ogg and listen to our tunes!

Creating a Radio Station with Docker

It works through a browser, although VLC does a more efficient job. I can also connect from my phone using an app called TuneIn Radio.

I can listen to my radio station from any computer, anywhere. I have cheap enough data on my phone that I can even keep the tunes going while I drive without needing to fall back to music that's loaded on the phone.

Security and Legality Concerns

I used nginx to hide my stream behind HTTPS and Cloudflare, and do some elementary password protection on the stream &mdash;

It's probably not legal to stream my music collection to _anybody who's not me_ on the internet, but my extremely cursory security pass should be enough to at least allow me to argue that the stream is intended for private use only.

For that same reason, I can't really share the final result with you. The radio station is for me!

A Web Interface

While I _usually_ just listen to the radio station on VLC media player, I thought I'd have some fun and build a web interface for the radio station.

With a visualizer, because I found a cool tutorial &mdash; shout-out to Soledad Penadés for writing the code in the first place.

Recording Loads of Fake Radio Promos and Ads

Creating a Radio Station with Docker

This was easily the least necessary part of the whole project, but I recorded a whole bunch of fake radio ads for my fake radio station.

It's not a real radio station if it doesn't have someone shouting at you between songs every now and again.

More Ideas

I've thought of doing the same thing with _video_, which would be the same kind of project but an order of magnitude more complex, I think.

I know it's possible to record stretches of radio play &mdash; I'd like to save about 10 hours of radio play on to my device for the odd plane trip or out-of-service area, and I'd like that 10 hours to update every now and again so that I don't get accidentally stuck with christmas music in July.

I'd like to build something that I could share with other people, although I guess it would have to be entirely creative commons music? I've found maybe five CC albums my entire life that I've liked, so it seems unlikely.

The original site didn't record this post's date; this one is approximate.

Tagged api-key, blog, cube drone