hack33r.com

Getting Started With NGINX, RTMP, and HLS Streams

Oct
11

In this article I will provide an overview of getting started with the nginx-rtmp-module and populating HTTP Live Streaming (HLS) streams using FFMPEG. Using HLS over RTMP should allow you to scale things out when needed using more traditional web technologies rather than dedicated media servers.  I won’t go into great deal on setup here, to follow along you should be familiar with nginx, the nginx-rtmp-module and the ffmpeg command line tool. I may write a more in depth post about setting every thing up at some point in the future. If you find this information useful and would like to know more, comments are welcome. 🙂

Assuming you have nginx and the nginx-rtmp-module setup correctly. You may want to setup HLS for live streaming. There is not a lot of information about this so I’m just covering a few things I found. The following snippet sets up 3 HLS stream variants for different bandwidth scenarios:


application video {

  # Configure live streaming, both publish and subscribe are wide open.
  live on;
  allow publish all;
  allow play all;

  # Execute a command to populate the hls streams. 
  # FFMPEG pushes three streams back to nginx-rtmp-module at /hls.
  # NOTE: The exec command requires and ending ';'
  exec ffmpeg -i rtmp://localhost/video/$name
    -c:a libfdk_aac -b:a 32k  -c:v libx264 -b:v 128K -f flv rtmp://localhost/hls/$name_low
    -c:a libfdk_aac -b:a 64k  -c:v libx264 -b:v 256k -f flv rtmp://localhost/hls/$name_mid
    -c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 512K -f flv rtmp://localhost/hls/$name_hi;

}

application hls {
  # Configure live streaming and HLS, only allow publish from localhost.
  live on;
  hls on;
  allow publish 127.0.0.1;
  allow play all;
  hls_path /tmp/hls;
  hls_nested on;
  hls_variant _low BANDWIDTH=160000;
  hls_variant _mid BANDWIDTH=320000;            
  hls_variant _hi  BANDWIDTH=640000;
  hls_base_url https://hack33r.com/hls/;
}
http {
  server {
    listen 127.0.0.1:80;
    server_name hack33r.com;
    location /hls {
      if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
	add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

	add_header 'Access-Control-Max-Age' 1728000;
	add_header 'Content-Type' 'text/plain charset=UTF-8';
	add_header 'Content-Length' 0;

	return 204;
      }
      if ($request_method = 'POST') {
	add_header 'Access-Control-Allow-Origin' '*';
	add_header 'Access-Control-Allow-Credentials' 'true';
	add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
	add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

      }
      if ($request_method = 'GET') {

	add_header 'Access-Control-Allow-Origin' '*';
	add_header 'Access-Control-Allow-Credentials' 'true';
	add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
	add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

      }
      # Serve HLS fragments
      types {
        application/vnd.apple.mpegurl m3u8;
        video/mp2t ts;
      }
      root /tmp;
      add_header Cache-Control no-cache;
    }
  }
}

In the above configuration we are allowing anyone to publish and rtmp stream to the ‘/live’ path on the web server. If a stream is published to ‘/live/foo’ the nginx-rtmp-module will execute an ffmpeg command that subscribes to the stream being published and pushes 3 different rtmp streams to the ‘/hls’ location. With this config, the stream could be subscribed too 4 different ways. Through one of the three HLS variants at ‘/hls/foo*’ in addition to the one at ‘/video/foo’. The server block configures nginx to server up the hls segments and adds some CORS headers which allow clients to connect from any domain.

That is all I have for this post as time is short today, In my next post I will give an example of using hls.js to play one of the HLS streams. Until then, happy streaming.

Leave a Reply

Your email address will not be published. Required fields are marked *