In these uncertain times where I suddenly have a lot of time at home, I remembered that I have an assortement of MP3s1 forgotten in a corner of my NAS from a time before Spotify and other streaming services. What better use of a likewise abandoned Raspberry Pi than making it blast these beats from around the turn of the century to soothe one’s nerves? To go back to those halcyon days of circa 2005, way before any global economic crises or pandemics… when we only had more localized events like the dotcom bubble and the first SARS.

Anyway, today we would have services like DLNA/UPnP and AirPlay to stream media at home but to really go back to the beginning of the new millenium I’m going to set up an internet radio station2.

Log of Shoutcast Radio
Shoutcast, not sure what it really does with llamas or their bodyparts.

My setup consists of three parts:

  1. Raspberry Pi that accesses my collection on NAS over SMB
  2. MPD that runs on the Pi and decodes the files to audio
  3. Icecast that puts that audio stream available on HTTP and can be accessed using a browser, VLC or even iTunes.

Setting up Raspberry Pi

In my case, I will use SMB to connect to my MP3s3. Other option would be NFS or whatever else that lets you mount the collection on the Pi. Maybe you have your collection on a USB drive.

I followed the documentation from raspberrypi.org and installed SMB support using

sudo apt update
sudo apt install samba samba-common-bin smbclient cifs-utils

and then mounting the NAS share using

sudo mkdir /mnt/music
sudo mount -t cifs //<mynas.local>/<share> /mnt/music -o user=<username>,pass=<password>

Setting up MPD

MPD is easily installed on the Pi with

sudo apt install mpd

Now, you might wonder why I explicitly mounted the share in the previous section when MPD’s documentation has a section on how to do this via MPD itself:

MPD has various storage plugins of which multiple instances can be “mounted” into the music directory. This way, you can use local music, file servers and USB sticks at the same time.

However, this feature does not exist yet although it is documented4. We will instead use symbolic links to bring the mounts into MPD’s default music library at /var/lib/mpd/music/ by

cd /var/lib/mpd/music/
sudo ln -s /mnt/music music

Now with ls -l you should see something like music -> '/mnt/music'. Next up, configuring MPD. Fire up your favorite text editor, for example sudo nano /etc/mpd.conf.

There are a lot of settings that can be left to their defaults, however for the symbolic links to work, uncomment and enable the settings in “Symbolic link behavior”5.

follow_outside_symlinks "yes"
follow_inside_symlinks  "yes"

Next up, the “Audio Output” section. Comment out the ALSA output, unless you also want MPD to play music of your Raspberry Pi’s audio out connector. Instead, uncomment the “example of a shout output (for streaming to Icecast)”.

The defaults are fine, but you might want to at least set name, mount, and password. mount defines the path at the end of the server’s URL where the stream will be available and password is the source password that MPD uses to authenticate to Icecast. Full documentation for the settings can be found here at MPD’s output plugin documentation.

#
# An example of a shout output (for streaming to Icecast):
#
audio_output {
        type            "shout"
#       encoder         "vorbis"                # optional
        name            "Your Stream Name Here"
        host            "localhost"
        port            "8000"
        mount           "/stream.ogg"
        password        "sourcepasswordforicecast"
#       quality         "5.0"
        bitrate         "128"
        format          "44100:16:1"
#       protocol        "icecast2"              # optional
#       user            "source"                # optional
        description     "Freshest beats from a better era"    # optional
#       url             "http://example.com"    # optional
#       genre           "jazz"                  # optional
#       public          "no"                    # optional
#       timeout         "2"                     # optional
#       mixer_type      "software"              # optional
}

However, this will create an Ogg Vorbis6 stream that notably Apple’s built-in software (Safari, iTunes, …) cannot handle - although VLC on macOS or iOS will handle it just fine. If you need support for an MP3 stream, either

  1. replace the above block with below to only have one stream, in MP3.
  2. or, just add the below to have two streams, one in MP3 and one in Ogg Vorbis

Note that you have to have unique names or MPD complains and refues to run. Also makes sure to have the same password for both blocks.

The only meaningful changes to above are uncommenting encoder and setting it to "lame" and changing mount (for MP3 stream, due to legacy reasons, you can drop the extension).

audio_output {
        type            "shout"
        encoder         "lame"                # lame encodes to MP3
        name            "Your MP3 Stream Name Here"
        host            "localhost"
        port            "8000"
        mount           "/stream"             # or /stream.mp3
        password        "sourcepasswordforicecast"
#       quality         "5.0"
        bitrate         "128"
        format          "44100:16:1"
#       protocol        "icecast2"              # optional
#       user            "source"                # optional
        description     "Freshest beats from a better era"    # optional
#       url             "http://example.com"    # optional
#       genre           "jazz"                  # optional
#       public          "no"                    # optional
#       timeout         "2"                     # optional
#       mixer_type      "software"              # optional
}

Now you have everything set up for MPD. To start, stop and restart you can control the daemon service with systemctl like most other services (ie. sudo systemctl start mpd).

You might want to wait until you have Icecast setup before starting MPD, but you can check that the service launches and you don’t have typos in configuration by manually starting it with mpd.

Controlling MPD

There are many different clients for MPD that you can find from the application’s website. MPD should come with mpc that is a simple command-line client. A bit more useful is the ncmpc client that can be installed with

sudo apt install ncmpc

A simple web-based front-end is ympd that you can then access also from other devices in your local network using their browsers.

You might need to run mpc update (or if you use another client, ask it to update MPD’s database) for MPD to index your media library. You might need to run this whenever you add or change the contents of your media library or you can change settings in mpd.conf for MPD to automatically reindex its database.

Setting up Icecast

Icecast can likewise be installed with a simple

sudo apt install icecast2

The configuration for Icecast lives in /etc/icecast2/icecast.xml and, again, open it up in your favorite editor or sudo nano /etc/icecast2/icecast.xml. You only really need to chcek the Basic Setup section from Icecast’s documentation.

Icecast will warn if you don’t change the <location> and <admin> settings but you can just ignore them. Next up you want to change the passwords in <authentication> section. Make the <source-password> match what the password you set previously in mpd.conf. You can, but don’t have to, set the <hostname> correctly.

Like MPD, you can control Icecast with systemctl. To check that the configuration file is well-formed, you can also start Icecast manually with icecast -c /etc/icecast2/icecast.xml.

Seeing Icecast’s stats

Icecast comes with a web-based status and admin interfaces that can be accessed from fe. http://raspberrypi.local:8000/. You can see your active mounts (that we setup in MPD’s config), how many listeners these streams have and you can also play the streams from your browser from here.

Putting it all together

Now when you have MPD and Icecast configured and starting, you can launch them as services with

sudo systemctl start icecast2
sudo systemctl start mpd

Use your MPD client (fe. ncmpc) to fill your playlist, start playback and you should be able to listen to your stream at fe. http://raspberrypi.local:8000/stream.ogg (or http://raspberrypi.local:8000/stream for MP3 stream).

Congratulations, you have now a time machine to 2005.

Further improvements

This is a very simple internet radio jukebox setup and it can be improved in numerous ways. Here are some ideas.

Fallback stream

One major issue you will notice is that if MPD’s audio stream ends for whatever reason like

  1. MPD runs out of music to play in its queue and you didn’t set it to repeat the playlist
  2. You accidentally stop playback by tapping the wrong key in ncmpc7

your clients will stop streaming.

One solution is that you can set a fallback in Icecast so that the stream doesn’t stop. This fallback can for example be a silent .ogg or .mp3 file that Icecast will use while you restart playback in MPD. Check the <fallback-mount> setting in Mount specific settings.

Relaying

Let’s say that instead of a personal jukebox you want to set up an internet radio (with your own content) that can be potentially be listened by many random people on the internet. Unless you have a lot of upstream bandwidth, this can potentially saturate your home’s internet connection.

You might instead want to have only one stream going out of your home and distribute the stream in the cloud. You can either follow the setup of the Icecast server on your VPS and set MPD to send its audio stream directly to the internet by changing the hostname setting in audio_output block, or you can set your VPS to relay the stream from the Icecast server on your Raspberry Pi.

The latter is incredibly simple if your Raspberry Pi and its Icecast stream are accessible from the public internet and not blocked by your home’s firewall: on the cloud Icecast instance just uncomment the “Relaying” section and set correct values for <master-server>, <master-server-port> and <master-password>. For bandwidth conservation reasons also enable <relays-on-demand> by setting it to 1. With this setting, your cloud instance will only start a stream from your Raspberry Pi if it has any listeners.

Advanced control of playlists

If you want to create more interesting playlists than just randomly going through your collection, you might want to look at Liquidsoap and its Quick start guide instead of MPD.