Streaming HLS with Nginx’s RTMP Module

In this post I’m going to show you how to use Nginx’s RTMP module to stream a live video (over RTMP) from your desktop and then play it back with HLS. I’ll also cover how to encrypt the video.

RTMP was initially a proprietary protocol by Adobe for streaming video and audio between a Flash player and a server but is still widely used today for broadcasting video despite the demise of Flash.

Note: I’m working on a live streaming solution that runs in your own cloud. Right now, only AWS is supported. A hosted option will also be available. Features will include, among other things, low-latency HLS and encryption. If you’re interested, send me a message, and I’ll let you know when it’s released.

Installation

I built the RTMP module on Ubuntu 18.04 but the installation instructions should work for any Debian-based Linux distribution.

The first thing to do is install Nginx if you haven’t already. You can install it from your distribution’s default package repositories but the provided version is usually outdated. A better option is to install it from the official Nginx repository. The current stable version is 1.18.

To install Nginx, run the following command: $ sudo apt install nginx

To build the RTMP module, first install the required dependencies then check out the source code of the module. We also need the source code of the version of Nginx that is installed. To build the module, run the following commands:

$ sudo apt install build-essential dpkg-dev libpcre3 libpcre3-dev libssl-dev zlib1g zlib1g-dev
$ git clone https://github.com/arut/nginx-rtmp-module.git
$ apt-get source nginx
$ cd nginx-1.18.0/
$ ./configure --with-compat --add-dynamic-module=../nginx-rtmp-module
$ make modules
$ sudo cp objs/ngx_rtmp_module.so /etc/nginx/modules/

This will build the RTMP module as a dynamic module. To load the module at runtime, add the following line to the Nginx configuration file (/etc/nginx/nginx.conf):

Now that Nginx has been installed and the RTMP module has been built, we need to configure it.

Configuring RTMP

The first thing we need to do is define an RTMP section in the Nginx configuration file:

The server will listen for connections on port 1935. Within the server block, we define an application called live. (You can call it whatever you like, I just happened to called it live.) We’ll refer back to this later on when we start streaming. To enable HLS, set hls to on. The next two parameters determine the location where the playlist and the segments will be written and the segment duration. In this instance, the playlist and segments are written to the /srv/www directory and the segment duration is set to 6 seconds.

To enable encryption (optional) set hls_keys to on. The next two values specify the directory where the keys will be written, and the base URL of the keys. Finally, we specify the key rotation period. This determines how many segments are encrypted with a key before a new key is generated. For example, if hls_fragments_per_key is set to 10 and the segment duration is 6 seconds, the encryption key will be rotated every minute.

The next step is to configure Nginx to serve the HLS playlist and segments. We do that by defining an http block in the configuration file:

The root location is set to /srv/www, which you’ll recall is the same location where the playlist and segments are written to. The expires parameter (line 48) specifies how long the playlist and the segments can be cached for, which is determined by looking up the value from a map based on the content type (line 38). In this case, the expiry time of the playlist (application/vnd.apple.mpegurl) is set to some time in the past (epoch) so it won’t be cached. Segments can be cached for 24 hours.

Note: Everything is served over HTTP. If you are encrypting the video then you should serve the keys over HTTPS. This is left as an exercise for the reader.

To start Nginx, run the following: $ sudo nginx

The next step is to prepare the live stream.

Preparing the Live Stream

If you want to stream the output of a webcam, I suggest downloading and installing OBS Studio. Alternatively, you can use ffmpeg to “live” stream a video.

However you decide to set-up your live stream, the format of the RTMP URL is the same. It must be in the following format: rtmp://<host>/<application name>/<stream key>

The host is either the IP address or the name of the server. As we are running it locally, it will be localhost.The application name must match the name in the Nginx configuration file, which in this example is live. The stream key can be anything – we’ll use test – and is used by the RTMP module to name the playlist and the segments. For example, if the stream key is test the playlist will be called test.m3u8 and the segments will be test-0.ts, test-1.ts, test-2.ts, and so on.

Setting the RTMP URL in OBS

Here’s an example of how to use ffmpeg to stream a video over RTMP:
$ ffmpeg -re -i big_buck_bunny_720p_h264.mov -c copy -f flv rtmp://localhost/live/test

Start the live stream. After a few seconds you should see some files in /srv/www.
Next, copy the following HTML and save it as index.html in the /srv/www directory:

(If you are using a different stream key, you’ll need to change the name of the playlist in the HTML.)

To play the live video, open up a browser and navigate to http://localhost/.

If you have any questions, feel free to leave a comment.

Leave a Reply