Make Your Own Radio Station

This document explains how to make and manage one or more Internet radio feeds using MusicPD and Icecast 2.

Install the packages
Icecast settings
MusicPD settings
Control scripts
start-radio
restart-station
Going further: a request tracker

Install the packages

If you're using Ubuntu, you will want the mpd, mpc, and icecast2 packages, along with their dependencies. I recommend using MusicPD version 0.13.0 or greater, because several important shoutcast-related bugs were fixed in that release.

Icecast settings

Now I will provide sample configurations files for each part of the setup. Here's my /etc/icecast2/icecast.xml file, with commented-out items removed and passwords scrubbed.

<icecast>
    <limits>
        <clients>100</clients>
        <sources>10</sources>
        <threadpool>5</threadpool>
        <queue-size>524288</queue-size>
        <client-timeout>60</client-timeout>
        <header-timeout>30</header-timeout>
        <source-timeout>20</source-timeout>
        <!-- If enabled, this will provide a burst of data when a client
             first connects, thereby significantly reducing the startup
             time for listeners that do substantial buffering. However,
             it also significantly increases latency between the source
             client and listening client.  For low-latency setups, you
             might want to disable this. -->
        <burst-on-connect>1</burst-on-connect>
        <!-- same as burst-on-connect, but this allows for being more
             specific on how much to burst. Most people won't need to
             change from the default 64k. Applies to all mountpoints  -->
        <burst-size>65535</burst-size>
    </limits>

    <authentication>
        <!-- Sources log in with username 'source' -->
        <source-password>password_1</source-password>
        <!-- Relays log in username 'relay' -->
        <relay-password>password_2</relay-password>

        <!-- Admin logs in with the username given below -->
        <admin-user>admin</admin-user>
        <admin-password>password_3</admin-password>
    </authentication>

    <!-- Uncomment this if you want directory listings -->
    <directory>
        <yp-url-timeout>15</yp-url-timeout>
        <yp-url>http://dir.xiph.org/cgi-bin/yp-cgi</yp-url>
    </directory>

    <!-- This is the hostname other people will use to connect to your server.
    It affects mainly the urls generated by Icecast for playlists and yp
    listings. -->
    <hostname>music.purduelug.org</hostname>

    <!-- You may have multiple <listener> elements -->
    <listen-socket>
        <port>8000</port>
        <!-- <bind-address>127.0.0.1</bind-address> -->
    </listen-socket>

    <fileserve>1</fileserve>

    <paths>
                <!-- basedir is only used if chroot is enabled -->
        <basedir>/usr/share/icecast2</basedir>

        <!-- Note that if <chroot> is turned on below, these paths must both
             be relative to the new root, not the original root -->
        <logdir>/var/log/icecast2</logdir>
        <webroot>/usr/share/icecast2/web</webroot>
        <adminroot>/usr/share/icecast2/admin</adminroot>
        <!-- <pidfile>/usr/share/icecast2/icecast.pid</pidfile> -->

        <!-- Aliases: treat requests for 'source' path as being for 'dest' path
             May be made specific to a port or bound address using the "port"
             and "bind-address" attributes.
          -->
        <!--
        <alias source="/foo" dest="/bar"/>
          -->
        <!-- Aliases: can also be used for simple redirections as well,
             this example will redirect all requests for http://server:port/ to
             the status page
          -->
        <alias source="/" dest="/status.xsl"/>
    </paths>

    <logging>
        <accesslog>access.log</accesslog>
        <errorlog>error.log</errorlog>
        <!-- <playlistlog>playlist.log</playlistlog> -->
        <loglevel>2</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
        <logsize>10000</logsize> <!-- Max size of a logfile -->
        <!-- If logarchive is enabled (1), then when logsize is reached
             the logfile will be moved to [error|access|playlist].log.DATESTAMP,
             otherwise it will be moved to [error|access|playlist].log.old.
             Default is non-archive mode (i.e. overwrite)
        -->
        <!-- <logarchive>1</logarchive> -->
    </logging>

    <security>
        <chroot>0</chroot>
        <!--
        <changeowner>
            <user>nobody</user>
            <group>nogroup</group>
        </changeowner>
        -->
    </security>
</icecast>

MusicPD settings

Here's a MusicPD configuration file that I placed in ~/.mpd/8bitpeoples.conf. There are 2 more of them, similarly configured, each using a different control port (6600 - 6602). Again, commented out parts are removed and passwords have been scrubbed.

# MPD CONFIG FILE
# For a full description of all config parameters,
# Check the mpd man page, "man mpd".

##################### REQUIRED ###########################
music_directory         "/home/mwolson/music/"
playlist_directory      "/home/mwolson/playlists"
db_file                 "~/.mpd/mpd.db"
log_file                "~/.mpd/8bitpeoples.log"
error_file              "~/.mpd/8bitpeoples.error"
pid_file                "~/.mpd/8bitpeoples.pid"
state_file              "~/.mpd/8bitpeoples.state"
##########################################################

#
# Hack to make MPD work properly, with no audio being sent to the
# system:
#
audio_output {
        type                    "ao"
        driver                  "null"
        name                    "Dummy output"
}

#
# An example of a shout output (for streaming to Icecast):
#
audio_output {
        type            "shout"
        name            "8bitpeoples"
        host            "127.0.0.1"
        port            "8000"
        mount           "/8bitpeoples.ogg"
        password        "password_1"
        quality         "5.0"
#       bitrate         "128"
        format          "44100:16:1"
        user            "source"
        description     "http://www.8bitpeoples.com/ -- Retro electronica"
        genre           "Electronica"
} # end of audio_output

# Software Mixer
mixer_type              "software"

################# REPLAYGAIN #############################
#
# Use Replay Gain (album or track)
#       http://www.replaygain.org
#
replaygain              "track"
#
# Sets the pre-amp used for files that have replaygain
# info.  Valid values are between -15 to 15 (in dB).
#
#replaygain_preamp      "0"
#
##########################################################

# Set this value if you only have one
# address you want to allow connection to.
#
bind_to_address                 "127.0.0.1"
port                            "6601"

# This sets the metadata mpd will use, to disable all metadata, set to "none"
# NOTE: comments are disabled by default
#
metadata_to_use "artist,album,title,genre,date,track,composer,performer,comment"

Control scripts

start-radio

This is a script that is used to restart all of the radio stations.

#!/bin/sh
#
# Usage: start-radio
#
# Assumes that MusicPD settings are in the .mpd directory, and that
# music is located in the $STATION directory, where $STATION
# corresponds with the names of the available stations.

PORT=6600

for i in OCR 8bitpeoples FSF; do
    echo "Starting $i feed ..."
    mpd .mpd/$i.conf
    sleep 1
    export MPD_PORT=$PORT
    export MPD_HOST=localhost
    mpc stop
    echo "Updating database ..."
    mpc update $i
    sleep 5
    mpc clear > /dev/null
    echo "Adding songs ..."
    mpc search filename "$i/" | mpc add > /dev/null
    mpc random on > /dev/null
    mpc repeat on > /dev/null
    mpc play
    PORT=`expr $PORT + 1`
done

echo "Done."

restart-station

Here's a script that can be used to restart one particular station, if it needs to have new songs added to its lineup.

#!/bin/sh
#
# Usage: restart-station <station name>
#
# Assumes that MusicPD settings are in the .mpd directory, and that
# music is located in the $STATION directory, where $STATION
# corresponds with the names of the available stations.

case "$1" in
    OCR )
        port=6600
        ;;
    8bitpeoples )
        port=6601
        ;;
    FSF )
        port=6602
        ;;
    * )
        echo "Usage: restart-station <station>"
        echo "Available stations: OCR 8bitpeoples FSF OpenMusic"
        exit 1
        ;;
esac

echo "Restarting $1 station ..."

# kill station
PID=`cat .mpd/$1.pid 2>/dev/null`
[ -n "$PID" ] && kill $PID

# bring station back up
mpd .mpd/$1.conf
sleep 1
export MPD_PORT=$port
export MPD_HOST=localhost

# update song database
echo "Updating database ..."
mpc update $1
sleep 5
mpc clear > /dev/null

# add songs
echo "Adding songs ..."
mpc search filename "$1/" | mpc add > /dev/null
mpc random on >/dev/null
mpc repeat on >/dev/null
mpc play

echo "Done."

Going further: a request tracker

It would be neat to see a request tracker that works with MusicPD, so that listeners can choose a song that they want to hear next. I really liked that feature when listening to VGamp (http://vgamp.com). It ought to be reasonably easy to implement, even the parts that prevent abuse.

It looks like Ampache might be able to do this, along with its Democratic Play functionality. I haven't checked it out yet.