knowledge

View the Project on GitHub ethericlabs/knowledge

Turn an MP3 file into a live audio broadcast with Icecast on CentOS

My goal is to broadcast an MP3 encoded audio file at a specific time on a specific IP address so that anyone who has the IP address can connect at that time and hear the broadcast.

To keep cost and complexity manageable :

Check your content file, audio.mp3

Set up a server

Create a server with CentOS 7 and configure the network to enable TCP and UDP traffic on port 8000. On GCP this means setting a network tag icecast-8000 on the virtual machine and creating a new firewall rule to allow TCP and UDP traffic on port 8000 to servers tagged icecast-8000 :

Name : icecast-8000
Logs : Off
Direction of traffic : ingress
Action on match : Allow
Targets : Specified target tags
Target tags : icecast-8000
Source filter : IP ranges
Source IP ranges : 0.0.0.0/0
Second source filter : None
Protocols and ports : Specified protocols and ports
[x] tcp 8000
[x] udp 8000

Other cloud providers will have different ways to accomplish this

Install and configure Icecast and EZStream on CentOS 7

Update the server

[you@icecast ~]$ sudo yum update -y

Open the firewall for port 800 TCP and port 8000 UDP

[you@icecast ~]$ sudo firewall-cmd --permanent --add-port=8000/tcp
[you@icecast ~]$ sudo firewall-cmd --permanent --add-port=8000/udp
[you@icecast ~]$ sudo firewall-cmd --reload

Check the firewall configuration

[you@icecast ~]$ sudo firewall-cmd --list-all # Expect ports: 8000/tcp 8000/udp

Test connectivity by setting up netcat as a listener on port 8000

[you@icecast ~]$ sudo yum -y install nmap-ncat
[you@icecast ~]$ sudo nc -l 8000

Open a new session to the server and make sure netcat is really listening

[you@icecast ~]$ sudo netstat -plunt | grep \:8000
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      12518/nc
tcp6       0      0 :::8000                 :::*                    LISTEN      12518/nc

From your local machine, connect to netcat on the Icecast server

[you@laptop ~]$ curl 35.222.4.30:8000

Netcat will show the connection on the server

GET / HTTP/1.1
Host: 35.222.4.30:8000
User-Agent: curl/7.54.0
Accept: */*

Stop cURL on your laptop with ^C and netcat will stop on the server

Install Icecast and EZStream

[you@icecast ~]$ sudo yum install -y icecast ezstream

Upload your audio

[you@laptop ~]$ scp audio.mp3 you@server:.

Edit the Icecast configuration file at /etc/icecast.xml and set

Start Icecast

[you@icecast ~]$ sudo systemctl enable icecast
[you@icecast ~]$ sudo systemctl start icecast

Check that Icecast started

[you@icecast ~]$ sudo systemctl status icecast
● icecast.service - Icecast Network Audio Streaming Server
   Loaded: loaded (/usr/lib/systemd/system/icecast.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2020-03-21 09:18:02 UTC; 4s ago
Mar 21 09:18:02 blueroom-broadcast systemd[1]: Started Icecast Network Audio Streaming Server.

[you@icecast ~]$ sudo netstat -plunt | grep icecast
tcp        0      0 0.0.0.0:8000          0.0.0.0:*               LISTEN      12980/icecast

From your local machine, check that the Icecast server responds to TCP requests with a 200 OK status code

[you@laptop ~]$ curl --write-out '%{http_code}\n' --output /dev/null --silent 35.222.4.30:8000
200

Create a playlist at ~/playlist.m2u

[you@icecast ~]$ echo audio.mp3 > playlist.m3u

Create an EZStream configuration file at ~/ezstream.xml, defining

Your EZStream configuration file might end up looking like

<ezstream>
  <url>http://35.222.4.30:8000/stream</url>
  <sourcepassword>XXXXXXXXXXXX</sourcepassword>
  <format>MP3</format>
  <filename>playlist.m3u</filename>
  <stream_once>1</stream_once>
  <svrinfoname>XXXXXXXX</svrinfoname>
  <svrinfourl>XXXXXXXX</svrinfourl>
  <svrinfogenre>XXXXXXXX</svrinfogenre>
  <svrinfodescription>XXXXXXXX</svrinfodescription>
  <svrinfobitrate>128</svrinfobitrate>
  <svrinfochannels>2</svrinfochannels>
  <svrinfosamplerate>44100</svrinfosamplerate>
  <svrinfopublic>0</svrinfopublic>
</ezstream>

Configure the permissions of the EZStream configuration file at ~/exstream.xml so that it is not writeable by world or group

[you@icecast ~]$ chmod g-w ezstream.xml

To start your broadcast, start EZStream

[you@icecast ~]$ ezstream -c ezstram.xml

When the playlist has been broadcast, EZStream will quit and you can destroy the server

Provide a web server and a link to the stream

[you@icecast ~]$ sudo yum install -y httpd
[you@icecast ~]$ sudo sed -i'' 's/^/\#/' /etc/httpd/conf.d/welcome.conf
[you@icecast ~]$ echo '<a href="http://35.222.4.30:8000/stream.m3u">Tune in</a>' | sudo tee index.html &> /dev/null
[you@icecast ~]$ sudo systemctl enable httpd
[you@icecast ~]$ sudo systemctl start httpd

Provide a countdown timer that turns into a link

<html>
<head>
</head>
<body>
<div id="hold">Broadcast launch link will appear here in <span id="time"></span></div>
<a style="display:none;" href="http://35.222.4.30:8000/stream.m3u" id='launch'>Tune in</a>
<script>
function start(duration, display) {
  console.log( 'start' );
  var timer = duration, minutes, seconds;
  setInterval(function () {
    minutes = parseInt( timer / 60, 10 );
    seconds = parseInt( timer % 60, 10 );
    minutes = minutes < 10 ? "0" + minutes : minutes;
    seconds = seconds < 10 ? "0" + seconds : seconds;
    display.textContent = minutes + ':' + seconds;
    if ( --timer < 0 ) {
      document.getElementById('hold').style.display = 'none';
      document.getElementById('launch').style.display = 'inline';
    }
  }, 1000);
}
window.onload = function () {
  var current = new Date();
  var activate = new Date( 'Sat Mar 21 2020 17:00:05 GMT+0000' );
  var diff = activate - current;
  var seconds = parseInt( diff / 1000 );
  var display = document.getElementById("time");
  start(seconds, display);
};
</script>
</body>
</html>
</div>
</body>
</html>

Launching the broadcast

You can do this manually

[you@icecast ~]$ ezstream -c ezstream.xml

or you can have the operating system do it for you

[you@icecast ~]$ sudo yum install -y at
[you@icecast ~]$ sudo systemctl enable atd
[you@icecast ~]$ sudo systemctl start atd
[you@icecast ~]$ ezstream -c ezstram.xml | at 17:00

The at command only knows about minutes, so make the Javascript timer activate the link a few seconds later to give ezstream time to start up

Connecting to the broadcast

With VLC or similar audio client open a connection to the broadcast

http://35.222.4.30:8000/stream.m3u

Helping listeners

Naming and tagging your MP3 file properly helps audio clients display appropriate information to the listeners

Keep an eye on your server performance

[you@icecast ~]$ sudo yum install -y glances
[you@icecast ~]$ glances