rokita.me

Creating a Radio Station

December 12, 2024 (last week)

This post will guide you step-by-step through the process of creating an internet radio station using the Icecast streaming server, with LiquidSoap as the audio router and Mopidy as the music server.

Diagram of the radio setup

Prerequisites

  • A Linux VM with root access (i’m using Ubuntu 24.04 LTS).
  • A local music library, or a streaming account.
  • Make sure you run sudo apt-get update before installing any packages.
  • We also need to install ffmpeg and python3, here’s the command:
    sudo apt install -y ffmpeg python3 python3-pip

Setting Up Icecast

First, we need to install Icecast on our server.

sudo apt-get install icecast2

During the installation, select Yes to configure Icecast.

Icecast Installation Prompt

You will be prompted for a hostname, and 3 passwords (source, relay and admin). You can leave the hostname as localhost, but you should change the passwords to something more secure.

(You can check and edit the passwords later in the configuration file.)

Icecast Installation Hostname Prompt


Next, we need to configure Icecast to create a mountpoint for our radio station.

sudo nano /etc/icecast2/icecast.xml

Next add the following snippet to the file inside the <icecast> tag:

<mount>
    <mount-name>/listen.mp3</mount-name>
    <bitrate>256</bitrate>
    <hidden>0</hidden>
</mount>

It should look like this:

Icecast Configuration Example

Save and exit the file. (It’s CTRL+X, Y, ENTER in nano)

Now we need to restart Icecast for the changes to take effect.

sudo systemctl restart icecast2

Setting Up LiquidSoap

Now that Icecast is set up, we can start configuring LiquidSoap. In our use case it will act as a router between Icecast and our Mopidy instance, to make sure that there’s always a stream available even if Mopidy is not streaming anything.

First, we need to install LiquidSoap by running the following command:

curl -Lo /tmp/liquidsoap.deb "https://github.com/savonet/liquidsoap/releases/download/v2.3.0/liquidsoap_2.3.0-ubuntu-oracular-1_$(dpkg --print-architecture).deb" && sudo apt-get install -y -f /tmp/liquidsoap.deb && rm /tmp/liquidsoap.deb

Check if it’s installed successfully by running liquidsoap --version.

It should print out something like this:

Liquidsoap 2.3.0
Copyright (c) 2003-2024 Savonet team
Liquidsoap is open-source software, released under GNU General Public License.
See <http://liquidsoap.info> for more information.

We’re going to use liquidsoap-daemon to run liquidsoap as a service in systemd, so we need to install that as well.

git clone https://github.com/savonet/liquidsoap-daemon.git ~/liquidsoap-daemon
chmod +x ~/liquidsoap-daemon/daemonize-liquidsoap.sh

Next, we need to create a new configuration file for LiquidSoap.

mkdir ~/liquidsoap-daemon/script
nano ~/liquidsoap-daemon/script/router.liq

And paste the following configuration into the file:

#!/usr/bin/liquidsoap
set("log.file.path", "/dev/null")
set("log.stdout", true)
set("server.telnet", false)
set("harbor.bind_addr","0.0.0.0")

# Reduce buffer sizes to reduce delay
set("frame.duration", 0.01)
set("root.max_latency", 0.1)

settings.init.allow_root := true

# Create the live input for mopidy (with a reduced buffer size to reduce delay further)
mopidy = buffer(buffer=0.1, max=0.5, input.harbor(port=8800, password="changeme", "/input"))

# Create a fallback source with track_sensitive=false for immediate transition to a blank source
stream_source = fallback(track_sensitive=false, [mopidy, blank(duration=5.)])

# Make the source safe
safe_source = mksafe(stream_source)

# Normalize the source
normalized_source = normalize(safe_source, target=-14., gain_max=12., gain_min=-12., down=0.1, up=5., threshold=-30., lufs=true)

# Output to Icecast (MP3)
output.icecast(
  %ffmpeg(format="mp3", %audio(codec="libmp3lame", b="256k")),
  mount="/listen.mp3",
  host="127.0.0.1", port=8000, password="CHANGE_ME_1",
  normalized_source)

Make sure to change the password in the output.icecast line to match the one you set up earlier for the Icecast Source.

Save and exit the file.

Now we need to use liquidsoap-daemon to run the script as a service.

cd ~/liquidsoap-daemon; ./daemonize-liquidsoap.sh router.liq

Let’s start the service.

sudo systemctl enable router-liquidsoap && sudo systemctl start router-liquidsoap

And let’s check if it’s running.

systemctl status router-liquidsoap

You should see something like this:

● router-liquidsoap.service - router Liquidsoap daemon
     Loaded: loaded (/etc/systemd/system/router-liquidsoap.service; enabled; preset: enabled)
     Active: active (running) since Thu 2024-12-12 13:59:07 UTC; 31s ago

Setting Up Mopidy

Now that LiquidSoap is set up, we can start configuring Mopidy to stream to our radio.

In this example we’re going to use a local music library, but you can use any music source that Mopidy supports. You can have a look at the Mopidy Extensions page for more information, and if you need any help feel free to reach out to me.

First, we need to install Mopidy:

sudo apt-get install mopidy

Install the web frontend and local library extension:

sudo python3 -m pip install Mopidy-Iris Mopidy-Local --break-system-packages

Let’s create a folder for our music library:

sudo mkdir -p /tank/music
chmod 777 /tank/music

And let’s throw in some music into the folder.

wget https://cdn.pixabay.com/download/audio/2024/11/29/audio_45bbd49c34.mp3 -O /tank/music/example_song.mp3

You can use any SFTP client such as FileZilla, or scp to upload your music to the server. There’s also an option to mount a network drive on the server, here’s a good guide on how to do that: How to mount CIFS shares permanently or instead use a streaming service such as Spotify via Mopidy-Spotify.

Next, we need to create a new configuration file for Mopidy.

nano /etc/mopidy/mopidy.conf

And paste the following configuration into the file:

[mpd]
hostname = 0.0.0.0

[http]
hostname = 0.0.0.0
default_app = iris

[audio]
output = lamemp3enc bitrate=256 ! shout2send mount=input ip=127.0.0.1 port=8800 password=changeme

[local]
enabled = true
media_dir = /tank/music

[m3u]
enabled = false

[iris]
enabled = true
country = US
locale = en_US
snapcast_enabled = false

Save and exit the file.

Now we need to restart Mopidy for the changes to take effect:

sudo systemctl restart mopidy

And one last thing, we need to scan the music library for new files by running this command:

sudo mopidyctl local scan

Playing Music

Now that we have LiquidSoap and Mopidy set up, we can start playing music.

Firstly we need to play some music on Mopidy, you can do this by going to the Mopidy web interface at http://server-ip:6680, and selecting some music from your library.

Mopidy Iris Web Interface

Once you’ve added some music to the queue mopidy will start streaming to the radio station.

We can check if the radio station is streaming by going to http://server-ip:8000/listen.mp3 in a web browser, once you press play you should hear some music. 🎉

Do keep in mind that this setup has around 10 to 20 seconds of delay, as far as I understand it’s because of the buffering between all the components which makes sure that the stream is not choppy.

You can also monitor your Icecast server by going to http://server-ip:8000 in a web browser.

If you have any questions or need any help feel free to reach out to me, my email is jan@rokita.me.

Thanks for reading! 🙏🏻

~ J