Host Your Own Radio Station using Icecast, DarkIce, Murmur and Mumble

UPDATE 2022-04-26: Changed Bash aliases for PipeWire.

UPDATE 2022-04-22: Found some possible alternative solutions in this awesome list’s Radio Production category. I’m sticking to this setup for now because it seems more lightweight. The live auto DJ features in AzuraCast looks really cool though.

Here’s the problem. My music files are stored somewhere. I need an easy way to listen to these music LIVE from any networked device. I also need greater control over the sound with crossfades, gapless playback or maybe even some live-mixing. The solution preferably is platform-independent so I can hear the music from a TV, a home sound system, etc. The best idea I could come up with to solve this is an audio streaming server that will serve up a livestream accessible by any network-capable media player. Basically, a radio station.

It’s unbelievable to me that I wasn’t able to find a single out-of-the-box solution to this problem. Or maybe I just didn’t look hard enough. In particular, I don’t know if OBS Studio can do all this too. If it can, well I think a big app like OBS might be overkill for this. This makeshift solution I have been using for months now is mostly thanks to two quite old articles I luckily found.

This setup is for Linux only and not Windows. All the tools used are free and open-source. I wrote this guide as an easier reference that is also updated for 2022.

The 7 Steps (to becoming a DJ!)

Step #1 - Setup: icecast, darkice, murmur, mumble

The steps to install the above tools are pretty straightforward. Just be sure to setup a password in icecast for darkice to use.

In my setup, I playback the stream over LAN. Specify the host server’s IP in the icecast and darkice configurations.

1
2
3
4
5
6
7
example IP config in /etc/icecast.xml
---
<hostname>192.168.0.22</hostname>
<listen-socket>
<port>7879</port>
<bind-address>192.168.0.22</bind-address>
</listen-socket>

And here’s a look at the relevant parts in the darkice config.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
in /etc/darkice.cfg
---
[general]
duration = 0
bufferSecs = 1
reconnect = yes
realtime = yes
rtprio = 2

[icecast2-0]
bitrateMode = vbr
quality = 1.0
format = mp3
bitrate = 256
server = 192.168.0.22
port = 7879
password = YOUR_ICECAST_PASSWORD
mountPoint = remix
name = DJ Remix
description = Remix broadcast

Step #2 - Start services: icecast, murmur

1
2
sudo systemctl start icecast
sudo systemctl start murmur

Step #3 - Create the audio sink output device in PulseAudio

This will create a kind of virtual soundcard for darkice to use as input and for the Mumble client and your audio player to use as output.

1
pactl load-module module-null-sink sink_name=stream

Note: I didn’t need to change anything with these setup steps when I upgraded to PipeWire in Manjaro. Everything worked just as smoothly as it did on just the PulseAudio sound server.

Step #4 - Set darkice to use the sink/null device and run it

darkice config using null input “stream.monitor”:

1
2
3
4
5
6
7
8
in /etc/darkice.cfg
---
[input]
device = pulseaudio
sampleRate = 44100
bitsPerSample = 16
channel = 2
paSourceName = stream.monitor

run darkice:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ darkice
DarkIce 1.4 live audio streamer, http://code.google.com/p/darkice/
Copyright (c) 2000-2007, Tyrell Hungary, http://tyrell.hu/
Copyright (c) 2008-2013, Akos Maroy and Rafael Diniz
This is free software, and you are welcome to redistribute it
under the terms of The GNU General Public License version 3 or
any later version.

Using config file: /etc/darkice.cfg
Using PulseAudio audio server as input device.
Using PulseAudio source: stream.monitor
Could not set POSIX real-time scheduling, this may cause recording skips.
Try to run darkice as the super-user.

Step #5 - Set Mumble and your media player to use the sink/null device

Mumble client using null output:

If you are on PipeWire already, it will appear like this:

“Mute Self” on Mumble unless you need it because you really want to talk over the music like a DJ!

On PulseAudio mixer, set your media player to use the sink/null output device:

Confirm darkice setup in the mixer too:

Step #6 - Start playing music!

Play some music on your media player. If you like, you can check the Icecast streaming status.

1
http://192.168.0.22:7879/admin

Using all of the above settings, you can access the livestream at this URL:

1
http://192.168.0.22:7879/remix

You can open up this address on the VLC app for example on a mobile device to listen to the stream LIVE!

Mumble allows this setup to offer really low latency. If you have latency or playback issues, try using a wired network connection on the Linux machine and ensuring a good, low interference WiFi signal for the listening device. As with all things networked, wired still trumps wireless in offering the best experience.

Step #7 - Shortcuts for convenience

You can have bash aliases to serve as quick shortcuts for starting or stopping the needed services.

1
2
3
alias djstart='sudo systemctl start icecast && sudo systemctl start murmur && nohup pactl load-module module-null-sink sink_name=stream &>> dj.log && nohup darkice &>> dj.log'

alias djstop='sudo systemctl stop icecast && sudo systemctl stop murmur && systemctl --user restart pipewire pipewire-pulse && rm dj.log'

Then launch Mumble and ensure it is on the correct audio output device. By default, it should auto-connect to the last server and remember the previous audio output settings anyway.

Uses & Limits

Any form of audio in a computer could be piped through this setup. Any program in which you can adjust output using the PulseAudio mixer is good here. You can have multiple apps streaming through one audio sink output. Your imagination really is your only limit. One thing I haven’t tried is having multiple streams (radio stations, if you will) under one machine. This is far above my present needs. It might take more tweaking than just the steps outlined here.

Wrap-up

Ideally, there would be a single lightweight tool to handle the tasks all these little bits of software contribute into making what is essentially a low-latency live audio recorder-streamer. As of this writing, I couldn’t find one that meets this requirement. And so I’m left with this improvised solution. The bulk of livestreaming these days is predominantly provisioned by big name companies so selfhosting folks are left with little to no choice. I regularly check awesome-selfhosted to see if there’s an approach I may have overlooked as regards this problem domain. But for now, this setup slaps! 😄