Getting started with nginx-rtmp-module: a FOSS alternative to Wowza, FMS, et al.

ihatetonyy

New Member
(This is a repost from something I originally posted on That Other Forum Rife with Cluster Errors, but hopefully you guys find it useful here, too..)

nginx-rtmp-module: a free, open-source alternative to Wowza Media Server, FMIS, et al.

A short introduction:
nginx-rtmp-module is an open-source (BSD license) module for nginx, the One True Web Server, Saviour of the Internet, Infinitely Better than Apache and Other Lesser Web Servers that provides RTMP, Apple HLS, and MPEG-DASH streaming capabilities integrated into the webserver.

It's an incredibly powerful, light-weight (especially compared to Red5 and Wowza, the Java Beasts) and **free** module/server that's used in production at Vimeo and Smotri, and hopefully by the end of this tutorial you'll be able to:

  • appreciate funny strikethrough text
  • configure nginx-rtmp-module at a basic level
  • come away with basic skills to help you mold it to fit your needs
Apologies for inciting violence
This tutorial will assume you are running CentOS 6. At the risk of starting a holy war, I will be upfront and tell you that it is the best distribution ever. Just my opinion, but also a fact.

Anyone who can provide painless compilation instructions for the other distros, please do so in the thread - I didn't include instructions for other distributions because I don't have the time to test them, and don't want to provide anyone with unreliable information.

You may be able to just reuse the CentOS compilation instructions or use alien to install the provided RPM on Debian/Ubuntu. I don't know.

---

0. Prerequisite skills

  • If you can handle yourself on the command-line, that's really good.
  • An AP Stylebook to turn to in times of need and doubt.
  • Patience.
1. Finding a host to fit your needs

Before even thinking about starting, please be sure you're with a host that allows streaming media. Check their TOS and AUP  if you see no mentions of audio or video streaming, you should be good. Check even if you're on a dedicated server.

To be sure, if you plan for a large amount of viewers or streaming video at a large bitrate, you should consult with your host anyway. Unless you're on a dedicated server, your network port is shared with other users on the node.

In addition, if you plan to use Apple HLS or MPEG-DASH, make sure you check with your host about CPU usage limits. If you follow this tutorial properly, an ffmpeg instance will run on each published stream: this can quickly become a CPU hog if you plan to run multiple video streams.

2. System requirements

I can't state exact requirements because I don't know what they are, so the following is based on my own experience:

  • If you want to use Apple HLS or MPEG-DASH, you probably want at least 512MB RAM. You'll probably also want a decent CPU core or two. See the CPU warning above.
  • If you want to just stream RTMP (Flash-only), you can get away with 128MB and one core. Probably even less.
The module's developer says it should work fine on Linux/FreeBSD/MacOS and Windows. I'm only aiming for Linux here, and if the instructions work well on any other platforms, let us know!

The race to the bottom in the low end market has made the above requirements easy to meet on the cheap.

Quality is a more nebulous concept: my strong recommendations go to BuyVM, CatalystHost, Hostigation, RamNode, Prometeus/Iperweb, Terafire, BlueVM. They all provide great price/performance service and, to the best my knowledge, allow streaming.

3. Setting the foundation

nginx-rtmp-module is, as the name suggests, a module to nginx. It's not included by default, so you need to compile nginx yourself.

If you're on CentOS, I have compiled my own nginx+nginx-rtmp-module RPMs and SRPM, available here. They are based on nginx-rtmp-module commit 51c1459e04 and nginx 1.5.8 mainline.

You will also want to install ffmpeg - install the ATRPMs repository, then install ffmpeg:

32-bit:


rpm -Uvh http://dl.atrpms.net/all/atrpms-repo-6-7.el6.i686.rpm
yum -y install ffmpeg
64-bit:


rpm -Uvh http://dl.atrpms.net/all/atrpms-repo-6-7.el6.x86_64.rpm
yum -y install ffmpeg
If you'd prefer to compile this by hand, I adapted a random tutorial and tested it. Works well: Compiling on CentOS

You will need to punch out ports 80 and 1935 in your firewall.

4. Basic configuration
(If you have installed from the RPM, you can skip this step, but you should read it anyway.)

Installing the RPM or following the linked instructions above should bring you to a point where you have the basic skeleton nginx configuration up. If not, please try again, post in the thread for help, or PM me.

In the /etc/nginx/ directory, open up your text editor of choice (nano uber alles, vi, emacs..) and insert the following:


rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;
rtmp_socket_dir /var/sock;



Code:
rtmp {
server {
listen 1935;
chunk_size 4000;

application live {
live on;
wait_video on;
wait_key on;
drop_idle_publisher 10s;
exec ffmpeg -i rtmp://localhost/live/$name -threads 2 -c:a aac -ac 1 -strict -2 -b:a 64k -c:v libx264 -profile:v baseline -g 10 -b:v 500K -s 720x480 -f flv rtmp://localhost/hls/$name_mid;
}


application hls {
live on;

hls on;

hls_continuous off;
hls_fragment_slicing aligned;
hls_fragment 15s;
hls_path /tmp/hls;

allow publish 127.0.0.1;
deny publish all;
}
}
}
Save this as /etc/nginx/rtmp.conf and close the document.

Open up /etc/nginx/nginx.conf and and add this to the bottom:


include /etc/nginx/rtmp.conf;
include /etc/nginx/vhls.conf;
Save this and close the document.

5. Serving HLS files from a vhost

(If you have installed from the RPM, this configuration is already installed in /etc/nginx/conf.d/default.conf - instead, edit the server_name directive in this file to your liking.)

Open up your text editor of choice - add this:


server {
listen 80;
server_name PUT.A.DOMAIN.HERE.EVEN.IF.ITS.A.SUBDOMAIN.tld;

root /usr/share/nginx/html/;

access_log off;

index index.html;

location ~ /\.ht {
deny all;
}

location /hls {
# Serve HLS fragments
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp;
add_header Cache-Control no-cache;
}
}
Replace the server_name directive with a domain or subdomain you want to use for this experiment, or permanently. Your call.

The key in this configuration is the "location /hls" block - if you want to add this to your own premade vhost, go ahead.

Save this as /etc/nginx/vhls.conf.

6. Fasten your seatbelts and put all seats in the upright position

Start up nginx now:


service nginx start
7. Takeoff

Use streaming software of your choice here. My personal preference is Flash Media Live Encoder, but Open Broadcaster Software or ffmpeg should work, too.

Your RTMP URL for publishing should look something like:


rtmp://this.is.my.domain.there.are.many.like.it.but.this.is.mine.tld/live/stream
In FMLE, this would come out to:


FMS URL: rtmp://this.is.my.domain.there.are.many.like.it.but.this.is.mine.tld/live/
Backup URL: blank
Stream: stream
Once you get your test stream going, a quick and easy way to test it is to enter the same RTMP URL here and hit 'Preview.' It should play whatever you're streaming.

8. Proceed to destination

Provided everything works good, congratulations! You've configured your first streaming server!

If you plan to use this internally, you can probably stop here and ignore authentication. If not, continue on:

Streaming authentication with nginx-rtmp-module

Hopefully at this point you've got your server set up - we are continuing from Step 8 in the last tutorial.

Anyone used to dealing with FMS/Wowza/Red5/crtmpd will be used to seeing this friendly dialog greeting you every time you're streaming an event:

node9660-login.png

This dialog box, one of our dearest former friends, is dead. You may choose to mourn his death or to celebrate his loss.

nginx-rtmp-module does not support 'Adobe authentication,' which pops up the dialog box seen above.

Instead it has three notification configuration options:

  • on_connect
  • on_publish
  • on_play
You can set each of these to a URL that will receive connection information; the server will then check the response code to see whether the viewer/publisher/connector should be denied or allowed to continue.

The server also passes on any arguments after the 'stream' URL. In FMLE, for example, the connection information:


FMS URL: rtmp://this.is.my.domain.there.are.many.like.it.but.this.is.mine.tld/live/
Backup URL: blank
Stream: stream?passphrase=stuff
would pass along the passphrase parameter to the callback URL.

There are also other notify callbacks - you can read about them here.

Here are some examples of what is sent to the PHP script for these callbacks.

'Yeah okay whatever, but how the hell do I set a password already?'

1. Find somewhere to host a PHP script.

If you want to get fancy down the line, MySQL might be nice  but not required for the example script below. Shared hosting works fine, but get something stable because if the server can't reach the script, streams won't get authorized.

If you want to host it on the same box, even better  setting up php-fpm is outside the scope of this tutorial but tutorials are abound on LET and vpsB and other friendly places.

2. Download the example script.

The board will probably mangle the script if I paste it, so here's a pastebin link.

http://pastebin.com/UB3ZwBW6

Copy and paste that into a PHP file (I'm partial to the name 'authorize.php') and upload it to a host of your choice. For the purposes of this example, please change "uniquepasswordhere" to a unique password.

This script will automatically approve any published stream that gives the correct passphrase.

3. Give it a spin.

Open your /etc/nginx/rtmp.conf file.

Add this inside the application live { } block:


on_publish http://your.domain.tld/path/to/authorize.php;
Restart the server from SSH - you could probably just reload but I like to be safe:


service nginx restart
And publish a stream with passphrase you set as demonstrated with the parameters above.

4. Extend to fit your needs

You can work using the information above to stretch this to fit your needs. The server sends over any custom parameters to the on_publish URL. In addition, you can play with on_play if you need to authorize Flash/RTMP viewers.

Examples of what you could do, depending on your needs:

  • use on_publish + stream parameters to authorize user/pass against database
  • use on_publish and on_publish_done to keep track of active streams and automatically add them to a viewing page (think DIY twitch.tv, etc.)
  • use on_play to authorize playback with some sort of secure token to allow authorized user-only viewing (billing, etc.)
  • use on_record_done to automatically catalog recorded streams for easy management and playback
I'll post tomorrow about automatically recording streams. Is there anything anyone would like to see?
 
Last edited by a moderator:

drmike

100% Tier-1 Gogent
Yeah a Debian how to :)

Does this support mpg video - like mp4 and common stuff?  I am a video novice.. Interested though.
 

ihatetonyy

New Member
Yeah a Debian how to :)

Does this support mpg video - like mp4 and common stuff?  I am a video novice.. Interested though.
Gotta sit down some time this week and figure out how to make Debian packages!

It does support streaming pre-recorded mp4 and flv files over Flash/RTMP.

It doesn't support streaming prerecorded video over HLS (newer Android, all iPhones) or DASH (IE11, newer Chrome) - you have to segment the video manually for those.
 
Top