Friday, January 21, 2011

Your Own Private Radio (Station)

"Radio Knobs" by Joe Lencioni
I had to add a streaming radio station to a client's web site last year.
This particular installation was a for a music library. We already had all the tracks in multiple formats including mp3. We simply wanted to push out a random stream of content from the library.
The web server was running Debian "Lenny" on Intel.

The process was pretty straightforward except for having the streamer launch when the server restarted.

If all is working, you  can listen to the radio station using your favorite streaming music player.

Choosing the Tech
We need a basic mp3 stream that will work with popular music players.
icecast2 is the most popular Open Source system for publishing streams. That one's a no-brainer.
Unfortunately Ices, the program from the Icecast group that creates those streams no longer supports the mp3 format. And iTunes doesn't play Ogg. So we need another solution for creating the original stream.

The ezstream application does exactly what need. But the Debian package didn't include a script to run when the server boots.

Use your favorite method of installing Debian packages.
Both "icecast2" and "ezstream" are in the Stable distribution.

Create a playlist for ezstream (instructions are in the README), and configure icecast by editing /etc/icecast2/icecast.xml

The icecast2 package provided a launch script, but ezstream did not.
While I'm not an expert on launch scripts, I was able cobble something together.
Here's my init.d script for ezstream:

#! /bin/sh
# Provides:          ezstream
# Required-Start:    $remote_fs
# Required-Stop:     $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.

# Author: Lon Koenig

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the script
DESC="EZstream streaming audio source for icecast"
DAEMON_ARGS="-c /var/www/ezstream/ezstream_mp3.xml"

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
#[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Not using a "default." Configuration file is defined above in DAEMON_ARGS

# Load the VERBOSE setting and other rcS variables
. /lib/init/

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

# Function that starts the daemon/service
# Return
#   0 if daemon has been started
#   1 if daemon was already running
#   2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --background --quiet --pidfile $PIDFILE --exec $DAEMON -- \
|| return 2
# Add code here, if necessary, that waits for the process to be ready
# to handle requests from services started subsequently which depend
# on this one.  As a last resort, sleep for some time.

# Function that stops the daemon/service
# Return
#   0 if daemon has been stopped
#   1 if daemon was already stopped
#   2 if daemon could not be stopped
#   other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently.  A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"

# Function that sends a SIGHUP to the daemon/service
do_reload() {
# If the daemon can reload its configuration without
# restarting (for example, when it is sent a SIGHUP),
# then implement that here.
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
return 0

case "$1" in
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;

# If do_reload() is not implemented then leave this commented out
# and leave 'force-reload' as an alias for 'restart'.

log_daemon_msg "Reloading $DESC" "$NAME"
log_end_msg $?
# If the "reload" option is implemented then remove the
# 'force-reload' alias
log_daemon_msg "Restarting $DESC" "$NAME"
case "$?" in
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
  # Failed to stop
log_end_msg 1
echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
#echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 3


That's it! Log into the server at http://{your_host_here}:8000/admin/ to see the management panel.
Pull up http://{your_host_here}:8000/live.nsv.3mu in your favorite streamer to hear the tunes.

No comments:

Post a Comment

Please leave your comment here.