Category Archives: Tutorials

Stress testing RTMP server

After working with Nginx-RTMP, I wanted to see how much traffic I could actually put through my server setup. I tried just streaming a bunch of video feeds from the server, but I ran out of processing power on my desktop. I had to figure out a better solution.

Enter Flazr. Flazr is a Java application that allows you to, among other things, stress test an RTMP server.

What you’ll need is:

  • RTMP target – Hopefully with a FAT network connection
  • RTMP Client – This should be a device watching a video feed from the server, making sure video problems don’t pop up
  • RTMP Stress tester – This is the machine running Flazr. I used an Atom computer running Ubuntu 14.04 server for my Flazr machine. It should run on anything that runs Java.

For basic usage, just use the command line to initiate the test. Here’s an example of a configuration I used.

./client.sh -load 100 rtmp://10.0.0.10/live/willstare

The stream I was pulling was at 1500kbps. Here’s the bandwidth being used on the RTMP server.

 rx: 6.20 Mbit/s 8944 p/s tx: 169.46 Mbit/s 18667 p/s

And here’s the CPU usage on the RTMP server.

 load average: 0.01, 0.02, 0.05

Obviously, my server can handle more than 100 connections. Let’s crank it up to 675! 675*1.5mbps = 975mbps.. That’s just about hitting the top end of gigabit.

Before we do that, we should probably increase the heap size for Flazr. On Ubuntu, type nano cleint.sh to edit the script. Change -Xmx512m to -Xmx2048m (if you have at least 4gb of RAM in the machine).

./client.sh -load 675 rtmp://10.0.0.10/live/willstare

Server bandwidth @ 675 clients

 rx: 6.04 Mbit/s 8655 p/s tx: 961.13 Mbit/s 81735 p/s

And server load @ 675 clients

load average: 0.07, 0.03, 0.05

As you can see, RTMP streaming is very efficient. It only requires massive bandwidth. Even with 675 clients, the video was still smooth when viewing it from another machine.

Stress testing Shoutcast Server

If you’re like me, you’ve got a shoutcast server configured to handle thousands of connections. I was pretty sure my setup could handle the load, but I wanted to actually find out. After looking around online, I found out an easy way to stress test the server using curl. Here’s a little script I wrote that will allow you to murder your server :D. Run this script on a test machine with a decent internet connection so you can really stress the server. This script should run on basically any linux operating system. I used Ubuntu as my test box.

Just a few things before you run the script.. You will need vnstat (or you’ll have to comment it out) to get the most of the script. Also, be careful with how many threads you run. If your server has the ulimit too low, you could lock up the shoutcast server.

#!/bin/bash
echo "enter a URL to stress test. ex: http://radio.derp.com:8123"
read URL
echo "enter number of threads to run. ex: 50"
read THREADS

for ((N=0; N<$THREADS; N++))
	do  curl -o /dev/null $URL >> /dev/null 2>&1 &
done
echo "Created "$THREADS" threads connected to "$URL
echo "Live Bandwidth"
echo "hit ctrl-c when you are finished" 
vnstat -l 
echo "Press any button and hit enter to kill all curl processes! Thanks!"
read Q
killall -e curl

If you have any questions please leave a comment below. Thanks

Here’s an example of the script in action.

./shoutcast_stress.sh 
enter a URL to stress test. ex: http://radio.derp.com:8123
stream.willstare.com:8123
enter number of threads to run. ex: 50
1500
Created 1500 threads connected to stream.willstare.com:8123
Live Bandwidth
hit ctrl-c when you are finished
Monitoring em0... (press CTRL-C to stop)

 rx: 50.45 Mbit/s 4514 p/s tx: 2.48 Mbit/s 4503 p/s

And bandwidth usage on the server

 rx: 4.14 Mbit/s 7706 p/s tx: 66.88 Mbit/s 8105 p/s

And what Shoutcast looks like with 1500+ connections:

shoutcast stress

There’s a few glitches (backspace might now work when entering stream URL), but I think its a good tool.

Nginx-RTMP & WordPress Debian

Alright, let’s get started. This guide assumes you meet the following prerequisites:

  • Fresh Debain 7 64 bit installation (no ‘web server’) or any other packages installed.
  • 4 CPU, 1G memory, 250+gb HDD
  • SSH, sudo, NTP, and a static IP address configured
  • User account streamer with sudo
  • DNS SERVER – It is highly recommended you have a local DNS server to handle requests to your server. This will allow the hard-coded URLs in wordpress and the script to continue working even if the IP addressing scheme changes.

Everything can be done to a physical installation or a virtual machine.

Install NGINX-RTMP

First we will install nginx-rtmp from a PPA. These steps are taken from HERE.

sudo apt-get install dpkg-dev
sudo mkdir /usr/src/nginx
cd /usr/src/nginx
sudo apt-get source nginx
sudo apt-get install git-core
sudo git clone https://github.com/arut/nginx-rtmp-module.git
cd nginx-1.2.1/

 

– Note: This will depend on what version you have. As of this writing, nginx was at 1.2.1.

 

List the directory. The following files should be shown in /usr/src/nginx/nginx-1.2.1/

sudo nano debian/rules

 

Add the following to the add-modules configuration.

 module=/usr/src/nginx/nginx-rtmp-module \

 

So it looks like this

--add-module=$(MODULESDIR)/nginx-upstream-fair \
--add-module=$(MODULESDIR)/nginx-dav-ext-module \
--add-module=/usr/src/nginx/nginx-rtmp-module \ 

 

sudo apt-get build-dep nginx
sudo dpkg-buildpackage -b

 

Building the package may take a while.

cd ..
sudo dpkg -i nginx-common_1.2.1-2.2+wheezy3_all.deb nginx-full_1.2.1-2.2+wheezy3_amd64.deb
sudo service nginx start

 

Great! Now we have nginx-rtmp installed on our Debian installation. Next, we will configure some stuff within Nginx!

NGINX-RTMP Configuration for WordPress AND Streaming

Start by changing nginx worker processes to 1. This is to make sure the streaming stats don’t get all screwy.

sudo nano /etc/nginx/nginx.conf

So it looks like this.

user www-data;
worker_processes 1;
pid /var/run/nginx.pid;

 

Then scroll down and add the following to the end of the file.

rtmp {
        server {
                listen 1935;
                chunk_size 4096;

                application live {
                        live on;
                        record all;
                        record_path /opt/nginx_scripts/live_recording/;
                        record_suffix -%d-%b-%y-%T.flv;
                        record_lock on;
                }
        }
}

Save the file. Next we will make some directories and get some more files.

sudo mkdir /var/www
cd /var/www
sudo wget https://raw.githubusercontent.com/arut/nginx-rtmp-module/master/stat.xsl
sudo chown www-data:www-data stat.xsl 

Next we will edit some nginx settings.

sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo service nginx reload
sudo mkdir sudo mkdir /var/www/wordpress -p

Next we will install PHP and MySQL.

sudo apt-get install php5-common php5-mysqlnd php5-xmlrpc php5-curl php5-gd php5-cli php5-fpm php-pear php5-dev php5-imap php5-mcrypt
sudo su
apt-key adv --keyserver keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A

echo "deb http://repo.percona.com/apt `lsb_release -cs` main" >> /etc/apt/sources.list.d/percona.list
echo "deb-src http://repo.percona.com/apt `lsb_release -cs` main" >> /etc/apt/sources.list.d/percona.list

apt-get update
exit
sudo apt-get install percona-server-server-5.6 percona-server-client-5.6

You might get 404 errors with the php PPA stuff.. It doesn’t officially support debian. Create a password for percona when it prompts.

mysql -u root -p -e 'create database wordpress'
mysql -u root -p -e "create user 'wordpress'@'localhost' identified by 'PASSWORD';"
mysql -u root -p -e "grant all privileges on wordpress.* to 'wordpress'@'localhost';"

Great, now we have a sql database configured for wordpress!

sudo nano /etc/nginx/sites-available/wordpress

Place the following information into the file. Change as necessary

server {
    listen 80;
    server_name _;
    access_log   /var/log/nginx/wordpress.access.log;
    error_log    /var/log/nginx/wordpress.error.log;
    root /var/www/wordpress;
    index index.php;
    location / {
            try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
            try_files $uri =404;
            include fastcgi_params;
            fastcgi_pass unix:/var/run/php5-fpm.sock;
    }

    location /viewers {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
    }
    location /stat.xsl {
            root /var/www/;
    }
    location /rec {
            autoindex on;
    }
}
sudo ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-available/default
sudo nginx -t && sudo service nginx reload

Okay, we are pretty much finished with nginx configuration! Time for installing and customizing WordPress!

WordPress installation and configuration

I assume that you will be able to install WordPress on the server. There are probably hundreds of guides on the internet explaining it.

After installing it, you should be at your admin window. Follow THIS GUIDE I wrote earlier to customize WordPress for an RTMP frontend.

 

Additional Utilities and directories

After configuring WordPress, we still need to add some more utilities and directories to the server.

First we will create a directory to hold the scripts. These will be the heart of the server.

sudo mkdir /opt/nginx_scripts
sudo chown www-data:www-data -R /opt/nginx_scripts
cd /opt/nginx_scripts
sudo wget https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
sudo chmod +x wp-cli.phar 
sudo mv wp-cli.phar /usr/local/bin/wp
sudo apt-get install xmlstarlet ffmpeg
sudo mkdir /var/www/wordpress/assets
sudo mkdir /var/www/wordpress/rec
sudo mkdir /var/www/wordpress/rec/mp4
sudo mkdir /var/www/wordpress/jwplayer
cd /var/www/wordpress/jwplayer
cd /var/www/wordpress/jwplayer
sudo wget https://www.willstare.com/wp-content/uploads/2014/12/jwplayer.tar
sudo tar -xvf /var/www/wordpress/jwplayer/jwplayer.tar
sudo chown www-data:www-data -R /var/www/wordpress/assets
sudo chown www-data:www-data -R /var/www/wordpress/rec
sudo chown www-data:www-data -R /var/www/wordpress/jwplayer

Great, now we can add the scripts! First we will create the nginx_watcher script. This will listen for new RTMP streams, and then do some WordPress magic to create a user profile page with the stream information.

sudo nano /opt/nginx_scripts/nginx_watcher.sh

Paste this script in. Make sure the IP/URL’s are correct. Nothing will work unless they are correctly configured.

#!/bin/bash

#MASTER contains a list of registered usernames for the event. To clear it, simply delete the file!
MASTER="rtmp_users.list"

#Enter the IP address of the server. (ex. 10.0.0.10)
IP_ADDRESS=10.0.0.10
#Enter the path to this script. Follow this syntax. Note the absence of a trailing '/' (ex: /home/user/scripts)
SCRIPT_PATH=/opt/nginx_scripts
#Enter the path to your WordPress installation. Follow this syntax. Note the absence of a trailing '/' (ex: /var/www/html)
WP_PATH=/var/www/wordpress
#Enter the URL of the Nginx statistics page. (ex: http://10.0.0.241/stats)
NGINX_STATS=http://10.0.0.10/viewers
#Enter the path to the HTML assets folder. This is where the server will hold the .m3u files. YOU MUST CHOWN this folder! (ex: /var/www/html/assets)
ASSETS=/var/www/wordpress/assets
#Enter the URL to the assets folder. (ex: http://10.0.0.241/assets)
WEB_ASSETS=http://10.0.0.10/assets
#Enter the path to the recording folder. (ex: /var/www/wordpress/rec/mp4)
REC=/var/www/wordpress/rec/mp4
#Enter the rec path. This is where the recordings will be stored. (ex: http://10.0.0.202/rec/mp4)
REC_PATH=http://10.0.0.10/rec/mp4
#Enter the RTMP server path. (ex: rtmp://10.0.0.242/live)
RTMP_PATH=rtmp://10.0.0.10/live
#Optional: Enter the path to a background image for JWPLayer. (ex: http://10.0.0.241/assets/site_logo.png)
IMAGE_PATH=
#Changes directory to the script-path for execution (required for cron)
cd $SCRIPT_PATH
#Creating the master list file.
MASTER="rtmp_users.list"
/bin/touch $MASTER
/bin/touch toadd.list
/bin/rm toadd.list
/bin/touch toadd.list
#Getting the current statistics from the streaming server
wget -O stats.xml $NGINX_STATS
#Parsing the XML file to get all the handles/keys currently streaming. These should correspond with the usernames of the streamers.
xmlstarlet sel -t -m '//name' -v . -n <stats.xml | grep -v live > unsanitized.list
sed -r 's/^\s*(.*\S)*\s*$/\1/;/^$/d' unsanitized.list > livestreams.list
#The loop below cycles through the livestreams.list file and compares each line to the current master list. If it doesn't exist, it adds it to the master list. It also adds it to the list of things we need to add to the website.
while read NAME
do
if ! /bin/grep -Fxq $NAME $MASTER; then
echo $NAME >> $MASTER
echo $NAME >> toadd.list
fi
done <livestreams.list
#Getting the existing post titles and ID's from WordPress. These will be compared to the currently active streams.
/usr/local/bin/wp --path=$WP_PATH post list --post_type=page --fields=ID,post_title > $SCRIPT_PATH/id_title.list
#Loop to find names to add. If they don't exist, a new page is created for them. This will display at the top of the menu. It is currently empty at this stage. Also checks and makes a blog post that will feature recordings from the user.

while read NEW; do
if ! /bin/grep $NEW id_title.list; then
/usr/local/bin/wp --path=$WP_PATH post create --post_type=page --post_status=publish --post_title=$NEW
/usr/local/bin/wp --path=$WP_PATH post create --post_type=post --post_status=publish --post_title=$NEW" Recordings"
fi
done <$MASTER

#The loop below checks to see if the stream is currently live or dead (depends on if its in the livestreams.list file). If its live, it generates a page with the relavent
#stream information customized for the user. If its dead, it will generate a dead page to notify browsers that the user is not currently streaming. This loop will update
# ALL streams in the master_rtmp.list as often as the cronjob is executed.
while read STREAM; do
echo $STREAM
/bin/ls $REC | grep $STREAM > $STREAM.record.list
cat $STREAM.record.list

POST_ID=`/usr/local/bin/wp --path=$WP_PATH post list --fields=ID,post_title | /bin/grep $STREAM | /usr/bin/awk '{print $1}'`
/bin/echo "<html>" >> $STREAM.record.html
/bin/echo "<head>" >> $STREAM.record.html
/bin/echo "<!--more-->" >> $STREAM.record.html
/bin/echo "</head>" >> $STREAM.record.html
/bin/echo "<body>" >> $STREAM.record.html
/bin/echo "<p>EXPERIMENTAL! Use Chrome or Firefox. Fullscreen for higest quality. If there is nothing here, "$STREAM" doesn't have any recordings. Page is regenerated every 3 minutes</p>" >> $STREAM.record.html
while read LINKS; do
/bin/echo "<a href="$REC_PATH/$LINKS">"$LINKS"</a>" >> $STREAM.record.html
/bin/echo "<video width='100%' controls>" >> $STREAM.record.html
/bin/echo "<source src='$REC_PATH/$LINKS' type='video/mp4'>" >> $STREAM.record.html
/bin/echo "Your browser does not support the HTML5 video player. Please download the file and play locally. Thank you." >> $STREAM.record.html
/bin/echo "</video>" >> $STREAM.record.html
done <$STREAM.record.list
/bin/echo "</body>" >> $STREAM.record.html
/bin/echo "</html>" >> $STREAM.record.html
RECORD_HTML=`cat $STREAM.record.html`
echo "ID BELOW"
echo $POST_ID

/usr/local/bin/wp --path=$WP_PATH post update $POST_ID --post_content="$RECORD_HTML"

ID=`/usr/local/bin/wp --path=$WP_PATH post list --post_type=page --fields=ID,post_title | /bin/grep $STREAM | /usr/bin/awk '{print $1}'`
/bin/rm $STREAM.record.list

if /bin/grep $STREAM livestreams.list; then
echo $STREAM" is online"
/bin/echo $RTMP_PATH/$STREAM > $ASSETS/$STREAM.m3u
/bin/echo "<html>" >> $STREAM.livetemplate.html
/bin/echo "<head>" >> $STREAM.livetemplate.html
/bin/echo "<script src=http://"$IP_ADDRESS"/jwplayer/jwplayer.js></script>" >> $STREAM.livetemplate.html
/bin/echo "</head>" >> $STREAM.livetemplate.html
/bin/echo "<body>" >> $STREAM.livetemplate.html
/bin/echo "<div id="$STREAM"></div>" >> $STREAM.livetemplate.html
/bin/echo "<script>// <![CDATA[" >> $STREAM.livetemplate.html
/bin/echo "jwplayer('"$STREAM"').setup({ file: '"$RTMP_PATH/$STREAM"', image: '//"$IMAGE_PATH"', title: '"$STREAM"', width: '100%', aspectratio: '16:9' });" >> $STREAM.livetemplate.html
/bin/echo "// ]]></script>" >> $STREAM.livetemplate.html
/bin/echo $STREAM" is online and streaming as of "`date` >> $STREAM.livetemplate.html
/bin/echo "<a href="$WEB_ASSETS/$STREAM".m3u>VLC LINK</a> (Right Click and Save-as)" >> $STREAM.livetemplate.html
/bin/echo "<p></p>" >> $STREAM.livetemplate.html
/bin/echo "<h1><a href="http://$IP_ADDRESS"/"$STREAM"-recordings>"$STREAM"'s past recordings</a></h1>" >> $STREAM.livetemplate.html
/bin/echo "</body>" >> $STREAM.livetemplate.html
/bin/echo "</html>" >> $STREAM.livetemplate.html
LIVE_HTML=`cat $STREAM.livetemplate.html`
/usr/local/bin/wp --path=$WP_PATH post update $ID --post_content="$LIVE_HTML"
/bin/rm $STREAM.livetemplate.html

else
/bin/echo $STREAM" is offline"
/bin/echo "<html>" >> $STREAM.deadtemplate.html
#/bin/echo "<head></head>" >> $STREAM.deadtemplate.html
/bin/echo "<h1>"$STREAM" is not streaming as of "`date`" </h1>" >> $STREAM.deadtemplate.html
/bin/echo "<body>" >> $STREAM.deadtemplate.html
#/bin/echo "<p></p>" >> $STREAM.deadtemplate.html
/bin/echo "<h1><a href="http://$IP_ADDRESS"/"$STREAM"-recordings>"$STREAM"'s past recordings</a></h1>" >> $STREAM.deadtemplate.html
/bin/echo "Page is regenerated every 60 seconds, please check again shortly." >> $STREAM.deadtemplate.html
/bin/echo "If this is your stream and it should be running, please contact an event administrator." >> $STREAM.deadtemplate.html #This string can be modified to meet your requirements.
/bin/echo "</body>" >> $STREAM.deadtemplate.html
/bin/echo "</html>" >> $STREAM.deadtemplate.html
DEAD_HTML=`cat $STREAM.deadtemplate.html`
/usr/local/bin/wp --path=$WP_PATH post update $ID --post_content="$DEAD_HTML"
/bin/rm $STREAM.deadtemplate.html
fi
/bin/rm $STREAM.record.html
done <$MASTER
#CLEANUP to remove some temp files that we don't need. These could be converted into arrays at a later point, but it makes it very simple to use files/grep.
/bin/rm stats.xml
/bin/rm id_title.list
/bin/rm livestreams.list
/bin/rm unsanitized.list
/bin/rm toadd.list
#This last line is useful for logging. If you run this script as a cronjob and send the output to a log file, you will see when the last time the script ran.
/bin/echo "Script finished at" `date`

Then we will create the recording_watcher.sh script. This will check for new recordings, and if it finds any, it will process them and move them to the web server directory. From there, users can view them.

sudo nano /opt/nginx_scripts/recording_watcher.sh
#!/bin/bash
#This script watches the /opt/ngnix_rtmp/live_recording directory for .flv files and converts them to .mp4 to make sharing the videos easier within a web browser.

#Enter the path to the script (ex: /opt/nginx_scripts)
SCRIPT_PATH=/opt/nginx_scripts
#Enter the path that NGINX-RTMP is saving files to. (ex: /opt/nginx_scripts/live_recording)
RTMP_RECORD=/opt/nginx_scripts/live_recording
#Enter the path to the webserver directory that the videos will be placed into. (ex: /var/www/wordpress/rec/mp4)
REC=/var/www/wordpress/rec/mp4

cd $RTMP_RECORD
#List all files in the /opt/nginx_rtmp/live_recording directory that match .flv. It writes the list to the flash_vids.list file with the full path.
ls -d -1 $PWD/** | grep .flv > $SCRIPT_PATH/flash_vids.list
#lsof is used to find what files are currently open by the OS. We use it here to see what files are open in the /opt/nginx_rtmp/live_recordings directory that match .flv. If it finds a
#file currently open, it places the name of the file into the writing_vids.list file.
lsof $RTMP_RECORD/* | grep .flv | /usr/bin/awk '{print $9}' > $SCRIPT_PATH/writing_vids.list
cd $SCRIPT_PATH

#Loop below reads through the writing_vids.list file and cross references it to the flash_vids.list file. If there's a match, it removes the active file from the flash_vids.list file.
#These files will not be processed in the next loop.
while read WRITING; do
grep -v $WRITING flash_vids.list > flash.tmp
mv flash.tmp flash_vids.list
done <writing_vids.list

#Sed strips the full path from the file names within the flash_vids.list file.
#!!!!!!!!!!!!!!!!!! ENTER THE CORRECT PATH BELOW. SHOULD BE THE SAME AS RTMP_RECORD VARIABLE. THANK YOU !!!!!!!!!!!!!!!!!!!!!!!!!!!

sed -i 's/\/opt\/nginx_scripts\/live_recording\///g' flash_vids.list
#Loop below reads through the flash_vids.list file and processes each .flv with avconv. It losslessly (and quickly!) converts the .flv video file to .mp4. It then removes the .flv pattern
#from the filenames. At the end it removes the .flv file.
while read FLASH; do
/usr/bin/avconv -i $RTMP_RECORD/$FLASH -vcodec copy -acodec copy $RTMP_RECORD/$FLASH.mp4
/usr/bin/rename 's/.flv//g' $RTMP_RECORD/$FLASH.mp4
/bin/rm $RTMP_RECORD/$FLASH
done <flash_vids.list

#Cleanup. Move all .mp4 files to the /var/www/wordpress/rec/mp4/ directory, and deletes the flash_vids.list and writing_vids.list files.
/bin/mv $RTMP_RECORD/*.mp4 $REC
/bin/rm flash_vids.list
/bin/rm writing_vids.list

Save that file as well. Now you should have 2 scripts, nginx_watcher and recording_watcher. Now we need to assign some final permissions and ownerships, and create a cron job to run every 60 seconds.

sudo chmod a+x nginx_watcher.sh
sudo chmod a+x recording_watcher.sh
sudo chown www-data:www-data nginx_watcher.sh
sudo chown www-data:www-data recording_watcher.sh
sudo mkdir /opt/nginx_scripts/live_recording
sudo chown www-data:www-data /opt/nginx_scripts/live_recording

sudo -u www-data -s #change to the www-data user to add a cronjob. 
./nginx_watcher.sh
./recording_watcher.sh
#those should both run.
crontab -e
*/1 * * * * /opt/nginx_scripts/nginx_watcher.sh >> /opt/nginx_scripts/nginx_watcher.log
*/3 * * * * /opt/nginx_scripts/recording_watcher.sh >> /opt/nginx_scripts/recording_watcher.log
touch /opt/nginx_scripts/nginx_watcher.log
touch /opt/nginx_scripts/recording_watcher.log
exit

If all went well, you should now have a fully functional Nginx-RTMP + WordPress installation capable of handling streaming sources and clients. It should be able to record all streams running through it.

Troubleshooting Tips

  • Make sure paths are correct in all scripts, symlinks, etc
  • Doublecheck permissions, especially in the www folder and the scripts folder
  • Make sure all paths exist
  • If you’re having problems, check the log for nginx and the script
  • Run the scripts and check for errors in their output
  • If all else fails, leave a comment below.

If you have a large event coming up and would like to use this for your streaming needs, please feel free to email me at coast.willstare [@] gmail.com. I can work with you to provide assistance, or even meet additional requirements.

There may be errors in this guide. If you spot any, please leave a comment. Thanks!

Finishing the RTMP WordPress project

If you have been following these tutorials, you should now have a fully functional Nginx RTMP server as well as a WordPress site optimized for showing live streams.

We just need to install a few more things and this project will be complete!

The first package we need is wp-cli. This program will allow us to modify our WordPress site from the CLI! Cool!

 user@websvr:~$ wget https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar 

Check to see if it works by typing

 user@websvr:~$ php wp-cli.phar --info 

If it works, we can make it an executable so you just type “wp” to call it.

user@websvr:~$ chmod +x wp-cli.phar

user@websvr:~$ sudo mv wp-cli.phar /usr/local/bin/wp 

That’s all we have to do to enable wp-cli. Next we need to install xmlstarlet, a utility to parse xml files.

 user@websvr:~$ sudo apt-get install xmlstarlet 

After that installs, we are finished adding software to the server.  Everything else should be included in your distro.

The script we will be using automatically generates .m3u playlist files that will need a directory in the webserver to reside. I like to use an ‘assets’ folder, but you can name it anything you’d like. Make a folder in the www root of your webserver, where WordPress is installed. After we create the folder, we must ‘chown’ it, which means change owner. Change ownership to the user that will be running the script.

 user@websvr:~$ sudo mkdir /var/www/html/assets/

user@websvr:~$ sudo chown user /var/www/html/assets/ 

 

What follows is a custom script that will allow the WordPress site to update based on the status of the nginx RTMP server. It will require some input before you run it, but once its set it can take care of itself.


#!/bin/bash

#MASTER contains a list of registered usernames for the event. To clear it, simply delete the file!
MASTER="rtmp_users.list"

#Enter the path to this script. Follow this syntax. Note the absence of a trailing '/' (ex: /home/user/scripts)
SCRIPT_PATH=
#Enter the path to your WordPress installation. Follow this syntax. Note the absence of a trailing '/' (ex: /var/www/html)
WP_PATH=
#Enter the URL of the Nginx statistics page. (ex: http://10.0.0.241/stats)
NGINX_STATS=
#Enter the path to the HTML assets folder. This is where the server will hold the .m3u files. YOU MUST CHOWN this folder! (ex: /var/www/html/assets)
ASSETS=
#Enter the URL to the assets folder. (ex: http://10.0.0.241/assets)
WEB_ASSETS=
#Enter the RTMP server path. (ex: rtmp://10.0.0.242/live)
RTMP_PATH=
#Optional: Enter the path to a background image for JWPLayer. (ex: http://10.0.0.241/assets/site_logo.png)
IMAGE_PATH=
#Changes directory to the script-path for execution (required for cron)
cd $SCRIPT_PATH
#Creating the master list file.
MASTER="rtmp_users.list"
/bin/touch $MASTER
/bin/touch toadd.list
/bin/rm toadd.list
/bin/touch toadd.list
#Getting the current statistics from the streaming server
wget -O stats.xml $NGINX_STATS
#Parsing the XML file to get all the handles/keys currently streaming. These should correspond with the usernames of the streamers.
xmlstarlet sel -t -m '//name' -v . -n <stats.xml | grep -v live > livestreams.list
#The loop below cycles through the livestreams.list file and compares each line to the current master list. If it doesn't exist, it adds it to the master list. It also adds it to the list of things we need to add to the website.
while read NAME
do
if ! /bin/grep -Fxq $NAME $MASTER; then
echo $NAME >> $MASTER
echo $NAME >> toadd.list
fi
done <livestreams.list
#Getting the existing post titles and ID's from WordPress. These will be compared to the currently active streams.
/usr/local/bin/wp --path=$WP_PATH post list --post_type=page --fields=ID,post_title > $SCRIPT_PATH/id_title.list
#Loop to find names to add. If they don't exist, a new page is created for them. This will display at the top of the menu. It is currently empty at this stage.
while read NEW; do
if ! /bin/grep $NEW id_title.list; then
/usr/local/bin/wp --path=$WP_PATH post create --post_type=page --post_status=publish --post_title=$NEW
fi
done <$MASTER
#The loop below checks to see if the stream is currently live or dead (depends on if its in the livestreams.list file). If its live, it generates a page with the relavent
#stream information customized for the user. If its dead, it will generate a dead page to notify browsers that the user is not currently streaming. This loop will update
# ALL streams in the master_rtmp.list as often as the cronjob is executed.
while read STREAM; do
ID=`/usr/local/bin/wp --path=$WP_PATH post list --post_type=page --fields=ID,post_title | /bin/grep $STREAM | /usr/bin/awk '{print $1}'`
if /bin/grep $STREAM livestreams.list; then
echo $STREAM" is online"
/bin/echo $RTMP_PATH/$STREAM > $ASSETS/$STREAM.m3u
/bin/echo "<html>" >> $STREAM.livetemplate.html
/bin/echo "<head>" >> $STREAM.livetemplate.html
/bin/echo "<script src=http://jwpsrv.com/library/UjjVOi7iEeSiiiIAC0MJiQ.js></script>" >> $STREAM.livetemplate.html
/bin/echo "</head>" >> $STREAM.livetemplate.html
/bin/echo "<body>" >> $STREAM.livetemplate.html
/bin/echo "<div id="$STREAM"></div>" >> $STREAM.livetemplate.html
/bin/echo "<script>// <![CDATA[" >> $STREAM.livetemplate.html
/bin/echo "jwplayer('"$STREAM"').setup({ file: '"$RTMP_PATH/$STREAM"', image: '//"$IMAGE_PATH"', title: '$NEW', width: '100%', aspectratio: '16:9' });" >> $STREAM.livetemplate.html
/bin/echo "// ]]></script>" >> $STREAM.livetemplate.html
/bin/echo $STREAM" is online and streaming as of "`date` >> $STREAM.livetemplate.html
/bin/echo "<a href="$WEB_ASSETS/$STREAM".m3u>VLC LINK</a> (Right Click and Save-as)" >> $STREAM.livetemplate.html
/bin/echo "</body>" >> $STREAM.livetemplate.html
/bin/echo "</html>" >> $STREAM.livetemplate.html
LIVE_HTML=`cat $STREAM.livetemplate.html`
/usr/local/bin/wp --path=$WP_PATH post update $ID --post_content="$LIVE_HTML"
/bin/rm $STREAM.livetemplate.html
else
/bin/echo $STREAM" is offline"
/bin/echo "<html>" >> $STREAM.deadtemplate.html
/bin/echo "<head></head>" >> $STREAM.deadtemplate.html
/bin/echo "<h1>"$STREAM" is not streaming as of "`date`" </h1>" >> $STREAM.deadtemplate.html
/bin/echo "<body>" >> $STREAM.deadtemplate.html
/bin/echo "Page is regenerated every 60 seconds, please check again shortly." >> $STREAM.deadtemplate.html
/bin/echo "If this is your stream and it should be running, please contact an event administrator." >> $STREAM.deadtemplate.html #This string can be modified to meet your requirements.
/bin/echo "</body>" >> $STREAM.deadtemplate.html
/bin/echo "</html>" >> $STREAM.deadtemplate.html
DEAD_HTML=`cat $STREAM.deadtemplate.html`
/usr/local/bin/wp --path=$WP_PATH post update $ID --post_content="$DEAD_HTML"
/bin/rm $STREAM.deadtemplate.html
fi
done <$MASTER
#CLEANUP to remove some temp files that we don't need. These could be converted into arrays at a later point, but it makes it very simple to use files/grep.
/bin/rm stats.xml
/bin/rm id_title.list
/bin/rm livestreams.list
/bin/rm toadd.list
#This last line is useful for logging. If you run this script as a cronjob and send the output to a log file, you will see when the last time the script ran.
/bin/echo "Script finished at" `date` 

Create a folder in the home directory of the user that will be running the script. Inside that folder, create a new file.

 user@websvr:~$ nano nginx_watcher.sh 

Edit the file

Paste the script into this file, and save it. Make the file executable by typing

 user@websvr:~$ chmod +x nginx_watcher.sh 

 

We are almost finished! Start a stream to the Nginx-RTMP server using your streaming software.  Then on the webserver, run the script by typing

 user@websvr:~$ ./nginx_watcher.sh 

If all goes well, there will be no errors reported, and your WordPress site will have a new page set up for the stream. The live video should be playable through JWPlayer, and an m3u file will be available for download. You should also be able to stop the stream, run the script again, and the page will be updated to state the the stream is offline.

The last step is to create a cronjob for this script to run every minute. This will allow users to begin streaming and a page for them will be created no more than 1 minute after.

Type

 user@websvr:~$ crontab -e 

and create a job run every minute. Here’s mine:

 */1 * * * * /home/user/nginx_water/nginx_watcher.sh >> /home/user/nginx_watcher/log/nginx_watcher.log 2>&1 

That will run the script every minute and send the output to a log file.

After that, your Nginx-RTMP/WordPress Frankenstein should be ready to roll!

Screenshots of it working!

Screenshot of the webpage when someone is actively streaming.

Screenshot of the webpage when someone is actively streaming.

Screenshot of the webpage when that same person has stopped streaming.

Screenshot of the webpage when that same person has stopped streaming.

I plan on releasing some prebuilt virtual machines soon for download for those who just want to get something running. THEY’RE HERE!

If you have any questsions, please leave a comment  below. If you have any suggestions for the script, I’d love to hear them. Thanks for reading.

Customizing WordPress for RTMP

If you are following along in this mini-series, you should now have a fully functional nginx based RTMP server capable of receiving and broadcasting live video streams. As cool as that is, its not very user friendly, especially for potential viewers.

In this post we will go over the steps to get a frontend set up for our RTMP server. This will serve as a central hub for our streaming environment. It will host information about how to watch the streams, how to broadcast to the server, as well as some cool statistics. You will need the following.

  • Fully functional WordPress installation – This guide will not cover WordPress installation or configuration. There are dozens of quality guides on the internet for this. Basically you need an Ubuntu server running the LAMP stack.

So, let’s start!

Log into your fully up to date WordPress installation via the web browser. I have found a few customization options that make the website look better for streaming.

  1. Change the theme to “TwentyTwelve”. Its a simple, clean theme that won’t distract viewers.2012
  2. Remove all widgets from the side panel. This will clean up the pages even more. Removing the “meta” widget will remove the “login” link on the side of pages. To login in the future, you will have to go to your WordPress admin URL (ex. 10.0.0.242/wp-admin) .widgets
  3. Create a menu via the Appearance menu. In the menu options, click the checkbox for “Automatically add new top-level pages to this menu”. Also select Primary Menu. This will automatically make our links on the website when the script makes new pages. menu
  4. Create some informational pages for your viewers/streamers to learn about how to use the website to stream/watch streams. Here’s some screenshots of mine.
    How to stream

    A basic how-to guide on streaming to the RTMP server with OBS. This page also includes directions for Xsplit as well.

    statsfor nerds

    A simple iframe within a page that shows the RTMP stats. Not necessary, but its kind of cool 🙂

how to watch

A basic how to watch page with download links for VLC.

Install nginx-rtmp server

For this guide I am following this post.

Requirements

For this guide you will need an up to date Ubuntu Server 14.04 virtual or physical machine.

Update your operating system. If you’re on Ubuntu, its a simple process. Simply type

 user@websvr:~$ sudo apt-get update 

After that, just type

 user@websvr:~$ sudo apt-get upgrade 

This will download updates for all the installed software. When that finishes, we need to grab the dependencies for nginx. Type or paste the following into the server.

 user@streamsvr:~$ sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev

Now that we have the dependencies, we can download the source code of nginx from their webpage.  As of this post, the most recent version is 1.7.4. To download it, type the following.

 user@streamsvr:~$ wget http://nginx.org/download/nginx-1.7.4.tar.gz

We also need to grab the RTMP module because it isn’t included in the main nginx distribution.

 user@streamsvr:~$ wget https://github.com/arut/nginx-rtmp-module/archive/master.zip 

Before we continue, we need to install the unzip program.

 user@streamsvr:~$ sudo apt-get install unzip 

Now we open the archives we downloaded and get cracking!

 user@streamsvr:~$ tar -zxvf nginx-1.7.4.tar.gz
user@streamsvr:~$ unzip master.zip
user@streamsvr:~$ cd nginx-1.7.4/ 

We can now configure the source and build the binary.

user@streamsvr:~/nginx-1.7.4$ ./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-master
user@streamsvr:~/nginx-1.7.4$ make
user@streamsvr:~/nginx-1.7.4$ sudo make install

Now nginx is installed! It is install ed in /usr/local/nginx. To start it type

 user@streamsvr:~$ sudo /usr/local/nginx/sbin/nginx 

Test it by going to your server IP with your web browser. It should display the following:

nginx installed

We are almost done. To add RTMP functionality, we must enable it in the nginx configuration file.

 user@streamsvr:~$ sudo nano /usr/local/nginx/conf/nginx.conf 

Paste this in at the end of the file.

rtmp {
        server {
                listen 1935;
                chunk_size 4096;

                application live {
                        live on;
                        record off;
                }
        }
}

To save, hit Crtl+x , yes, and enter.

To make the rest of the project easier, we should make nginx into a system service that runs automatically and can be controlled with the service command.

 sudo nano /etc/init/nginx.conf 

Paste this into the file

# nginx

description "nginx http daemon"
author "Philipp Klose <me@'thisdomain'.de>"

start on (filesystem and net-device-up IFACE=lo)
stop on runlevel [!2345]

env DAEMON=/usr/local/nginx/sbin/nginx
env PID=/var/run/nginx.pid

expect fork
respawn
respawn limit 10 5
#oom never

pre-start script
 $DAEMON -t
 if [ $? -ne 0 ]
 then exit $?
 fi
end script

exec $DAEMON

We can now start and stop nginx with the sudo service nginx start | stop | restart commands. Yes! It will also start when the server boots, so you don’t need to worry about that.

Next we need to go back to the nginx configuration file and prepare it for stats delivery. The ability to display server statistics will be crucial to this project. This page will ensure that live streams have the correct pages generated for them.

Go back to the nginx configuration and add the following inside the server directive in the /usr/local/nginx/conf/nginx.conf.

# rtmp statistics
        location /viewers {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        location /stat.xsl {
            # you can move stat.xsl to a different location
            # under linux you could use /var/user/www for example
            root html;
}

The server directive should now start like this:


server {
listen 80;
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
root html;
index index.html index.htm;
}
#rtmp statistics
location /viewers {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}

location /stat.xsl {
# you can move stat.xsl to a different location
# under linux you could use /var/user/www for example
root html;
}
#error_page 404 /404.html; 

We have to do one more quick thing before the stats page will work. In order to generate the XML, the RTMP module uses an XSL file. This will need to be placed in the HTML root of the nginx server. Create a file called stat.xsl containing the following. Save it, and we should be good to go. For whatever reason, pasting the stat.xsl file into this page is messing things up, so I’ll just include a link to the file. 

 user@streamsvr:~$ sudo nano /usr/local/nginx/html/stat.xsl 

After you paste that in, save the nginx configuration. Restart the entire server. After it boots should be able to see the rtmp server stats if you go to your server IP address /viewers.

And that’s it for the nginx-rtmp installation/configuration. The server is now running and ready for the next section of this series… Web server configuration and scripting!

 

 

 

 

 

Install Mcmyadmin on Ubuntu 14.04 Server

I followed this guide: https://www.digitalocean.com/community/questions/how-to-install-mcmyadmin-and-start-it-up-for-the-first-time-not-a-question-a-howto-guide

It worked great until the end. Upon running the script, SSH session would get flooded with errors. At first it appeared that they were Java errors, but upon further inspection it appeared to be related to my SSH session itself. I was using SecureCRT, and by default some of the color codes from the Linux terminal are not enabled. Here is the error I was getting.

Running in 64-bit mode.
McMyAdmin Core Exception: Argument cannot be null.
Parameter name: format
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentNullException: Argument cannot be null.
Parameter name: format
at System.String.FormatHelper (System.Text.StringBuilder result, IFormatProvider provider, System.String format, System.Object[] args) [0x00000] in <filename unknown>:0
at System.String.Format (IFormatProvider provider, System.String format, System.Object[] args) [0x00000] in <filename unknown>:0
at System.String.Format (System.String format, System.Object arg0) [0x00000] in <filename unknown>:0
at System.TermInfoDriver.set_ForegroundColor (ConsoleColor value) [0x00000] in <filename unknown>:0
at System.ConsoleDriver.set_ForegroundColor (ConsoleColor value) [0x00000] in <filename unknown>:0
at System.Console.set_ForegroundColor (ConsoleColor value) [0x00000] in <filename unknown>:0
at nu.a (a A_0) [0x00000] in <filename unknown>:0
at nu.a () [0x00000] in <filename unknown>:0
at System.Threading.Thread.StartInternal () [0x00000] in <filename unknown>:0

 

As you can see, its all talking about colors. Mcmyadmin attempts to mirror Powershell in its color scheme, and that includes changing the background color to blue. For whatever reason SecureCRT doesn’t allow for this to happen, and the result is a bunch of errors. By switching to Putty, I was able to get the server up without an issue. I’ll include some screenshots below to show what I am talking about.

securecrt
SecureCRT throwing an error while connected.

putty
Putty working fine. Notice the blue background.

I hope this post helps anybody having issues with this problem. I couldn’t find anything online that helped. Comment below if you have questions.

How to use your domain with Gmail (no Google Apps required)

domain.com

So I was looking for a solution for using a Gmail account with my domain (willstare.com). After finding out that the free version of Google Apps is no longer offered to new customers, I was forced to come up with my own solution. I knew that Gmail allowed users to have an ‘alias address’ to send and receive from, but that required an active email account to work (for verification). Here’s what I did to get around that requirement.

Go to your domain host (I use domain.com), and configure a new email forwarder. You do not need to make an email account, only a forwarder. Forward the email address that you would like to create (ex: test@willstare.com) and point it to a Gmail account (ex: test.willstare@gmail.com). After doing that, make your Gmail account, and login. Open the settings and select Accounts and Import. Then select ‘Send mail as:’ and add your test account that you set up earlier (test@willstare.com).

Now it will require a verification email to be sent to confirm that you own the email account. Because you have already configured the email address to forward to your Gmail account, it will arrive in your inbox, technically confirming that you ‘own’ that address. Enter the verification number, and you should be set. This worked for me, I hope it helps others.

How to configure a shoutcast relay server in ubuntu

So you want to relay your favorite shoutcast stream with your ubuntu VPS, but don’t know where to start? Here’s a quick guide to relaying DNAS v1.9.8 shoutcast server streams.

Step 1: Download the sc_serv_1.9.8 file from this thread, or from another website (afterdawn, shoutcast.com, etc)

sc_serv_1.9.8_Linux.tar.gz

Step 2: Unzip the .zip and .tar, and FTP them to your server. I use /var/shoutcast for my folder root, but that might not be the most secure. You could use /home/shoutcast or anything really.

Step 3: If you are going to run the server as root (not recommended) you can skip this. Otherwise, make an account (ex. shoutcast) and place the files into a folder in their home.

Step 4: Edit the sc_serv.conf using nano or vi. Edit any and all settings that you find fit. Here is what I have mine set as.

[spoiler]

; SHOUTcast Distributed Network Audio Server configuration file
; Copyright (C) 1998-2004 Nullsoft, Inc.
; All Rights Reserved.
; Last modified Mar 17 2004

; If you want to manage multiple configurations, just copy
; this file to another name, and run sc_serv with that name
; such as:
; sc_serv.exe sc_leet.conf

; ***************************
; Required stuff
; ***************************

; MaxUser.  The maximum number of simultaneous listeners allowed.
; Compute a reasonable value for your available upstream bandwidth (i.e. if
; you have 256kbps upload DSL, and want to broadcast at 24kbps, you would
; choose 256kbps/24kbps=10 maximum listeners.)  Setting this value higher
; only wastes RAM and screws up your broadcast when more people connect
; than you can support.
MaxUser=100

; Password.  While SHOUTcast never asks a listener for a password, a
; password is required to broadcast through the server, and to perform
; administration via the web interface to this server.  This server should
; consist of only letters and numbers, and is the same server your broadcaster
; will need to enter in the SHOUTcast Source Plug-in for Winamp.  THIS VALUE
; CANNOT BE BLANK.
Password=************

; PortBase. This is the IP port number your server will run on.  The
; value, and the value + 1 must be available.  If you get a fatal error when
; the DNAS is setting up a socket on startup, make sure nothing else on the
; machine is running on the same port (telnet localhost portnumber — if you
; get connection refused then you’re clear to use that port).  Ports < 1024
; may require root privledges on *nix machines.  The default port is 8000.
PortBase=8100

; ***************************
; Optional Parameters
; ***************************

; ***************************
; Logging configuration
; ***************************

; LogFile: file to use for logging. Can be ‘/dev/null’ or ‘none’
; or empty to turn off logging. The default is ./sc_serv.log
; on *nix systems or sc_serv_dir\sc_serv.log on win32.
; Note: on win32 systems if no path is specified the location is
; in the same dir as the executable, on *nix systems it is in the
; current directory.
LogFile=sc_serv.log

; RealTime displays a status line that is updated every second
; with the latest information on the current stream (*nix and win32
; console systems only)
RealTime=1

; ScreenLog controls whether logging is printed to the screen or not
; on *nix and win32 console systems. It is useful to disable this when
; running servers in background without their own terminals. Default is 1
ScreenLog=1

; ShowLastSongs specifies how many songs to list in the /played.html
; page.  The default is 10.  Acceptable entries are 1 to 20.
ShowLastSongs=10

; TchLog decides whether or not the DNAS logfile should track yp
; directory touches.  Adds and removes still appear regardless of
; this setting.
; Default is yes
; TchLog=yes

; WebLog decides whether or not hits to http:// on this DNAS will
; be logged.  Most people leave this off because the DSP plug-in
; uses http:// calls to update titles and get the listener count,
; which takes up a lot of log space eventually.  If you want to
; see people making hits on your admin.cgi or index pages, turn
; this back on.  Note that this setting does NOT affect XML stats
; counters for hits to http:// pages.
; Default is no.
; WebLog=no

; W3CEnable turns on W3C Logging.  W3C logs contain httpd-like accounts
; of every track played for every listener, including byte counts those listeners
; took.  This data can be parsed with tools like Analog and WebTrends, or given
; to third parties like Arbitron and Measurecast for their reporting systems.
; Default is Yes (enabled).
W3CEnable=Yes

; W3CLog describes the name of the logfile for W3C logging.  Default logfile is
; sc_w3c.log, in the same directory wherever the DNAS gets started from.
W3CLog=sc_w3c.log

; ***************************
; Network configuration
; ***************************

; SrcIP, the interface to listen for source connections on (or to make relay
; connections on if relaying). Can and usually will be ANY or 127.0.0.1
; (Making it 127.0.0.1 will keep other machines from being able to
; broadcast using your shoutcast server )
SrcIP=ANY

; DestIP, IP to listen for clients on (and to contact yp.shoutcast.com)
; can and usually will be be ANY. If your machine has multiple IP addresses,
; set this to the one you want it to be accessed by.
DestIP=ANY

; Yport, port to connect to yp.shoutcast.com on. For people behind caching
; webproxies, change this to the alternate port (666 is what it might be,
; check www.shoutcast.com if you have problems). Otherwise, leave this at 80.
; We’re actively working on re-opening port 666, but as of release the only
; working port is port 80.
Yport=80

; NameLookups.  Specify 1 to perform reverse DNS on connections.
; This option may increase the time it takes to connect to your
; server if your DNS server is slow.  Default is 0 (off).
NameLookups=0

; RelayPort and RelayServer specify that you want to be a relay server.
; Relay servers act as clients to another server, and rebroadcast.
; Set RelayPort to 0, RelayServer to empty, or just leave these commented
; out to disable relay mode.
RelayPort=8000
RelayServer=stream1.yourfavoritestream.com

; ***************************
; Server configuration
; ***************************

; AdminPassword.  This password (if specified) changes the
; behavior of Password to be a broadcast-only password, and
; limits HTTP administration tasks to the password specified
; here.  The broadcaster, with the password above, can still
; log in and view connected users, but only the AdminPassword
; will grant the right to kick, ban, and specify reserve hosts.
; The default is undefined (Password allows control for both
; source and admin)
; AdminPassword=************

; AutoDumpUsers controls whether listeners are disconnected if the source
; stream disconnects. The default is 0.
AutoDumpUsers=0

; AutoDumpSourceTime specifies how long, in seconds, the source stream is
; allowed to be idle before the server disconnects it. 0 will let the source
; stream idle indefinately before disconnecting. The default is 30.
AutoDumpSourceTime=30

; ContentDir specifies the directory location on disk of where to stream
; on-demand content from.  Subdirectories are supported as of DNAS 1.8.2.
; Default is ./content, meaning a directory named content in the same directory
; as where sc_serv was invoked from.
; ContentDir=./content

; IntroFile can specify a mp3 file that will be streamed to listeners right
; when they connect before they hear the live stream.
; Note that the intro file MUST be the same samplerate/channels as the
; live stream in order for this to work properly. Although bitrate CAN
; vary, you can use ‘%d’ to specify the bitrate in the filename
; (i.e. C:\intro%d.mp3 would be C:\intro64.mp3 if you are casting at 64kbps).
; The default is no IntroFile
; IntroFile=c:\intro%d.mp3

; BackupFile can specify a mp3 file that will be streamed to listeners over
; and over again when the source stream disconnects. AutoDumpUsers must be
; 0 to use this feature. When the source stream reconnects, the listeners
; are rejoined into the live broadcast.
; Note that the backup file MUST be the same samplerate/channels as the
; live stream in order for this to work properly. Although bitrate CAN
; vary, you can use ‘%d’ to specify the bitrate in the filename
; (i.e. C:\backup%d.mp3 would be C:\backup32.mp3 if you are casting at 32kbps).
; The default is no BackupFile
; BackupFile=C:\intro%d.mp3

; TitleFormat specifies a format string for what title is sent to the listener.
; For example, a string of ‘Justin Radio’ forces the title ‘Justin Radio’ even
; when the source changes the title. You can use up to one ‘%s’ in the string
; which lets you contain the title from the source. For example, if your
; TitleFormat is ‘Justin Radio: %s’, and the source plug-in’s title is
; ‘Billy plays the blues’, then the net title is
; ‘Justin Radio: Billy plays the blues’. Note: only works on non-relay servers.
; The default is no format string.
; TitleFormat=Justin Radio: %s

; URLFormat specifies a format string for what url is sent to the listener.
; Behaves like TitleFormat (see above).
; The default is no format string.
; URLFormat=http://www.server.com/redirect.cgi?url=%s

; PublicServer can be always, never, or default (the default, heh)
; Any setting other than default will override the public status
; of the source plug-in or of a SHOUTcast server that is being relayed.
PublicServer=default

; AllowRelay determines whether or not other SHOUTcast servers will be
; permitted to relay this server.  The default is Yes.
AllowRelay=Yes

; AllowPublicRelay, when set to No, will tell any relaying servers not
; to list the server in the SHOUTcast directory (non-public), provided
; the relaying server’s Public flag is set to default.  The default is
; Yes.
AllowPublicRelay=Yes

; MetaInterval specifies how often, in bytes, metadata sent.
; You should really leave this at the default of 8192, but the option is
; provided anyway.
MetaInterval=32768

[/spoiler]

The main things that I changed were maxlisteners (set to 100), the passwords, and the relay information.

For the relay, you need the port of the stream, as well as the address. To find this information you must open the listen.pls and find the data in there.

*If you are going to run more than 1 server at a time, you will need to change the portbase. I run my streams at 8100 and 8200.

Step 5:

Now that you have configured your server, ssh in and cd to the appropriate folder. To start the server type

./sc_serv sc_serv.conf

It will now start!

If all goes well, the server will pick up the stream, and start relaying. Shoucast will do some magic, and you will soon be taking some of the load off of the main stream and onto yours. Contact the stream owner ahead of time so you can coordinate reserved slots in their streams.

If you have any questions, please leave them below. Remember, this only works with version 1.9.8!