Nginx RTMP Module receive x.264 , output HLS live stream

Chayemor picture Chayemor · Aug 4, 2016 · Viewed 16.5k times · Source

Goal: Stream from PC using OBS , receive stream with Nginx RTMP Module and output to viewers so that they can view the live stream both on PC and mobile. For that to happen, Nginx must output live stream with HLS.

My partner has set up the following Nginx file, but nothing occurs (it was done following this answer from stackoverflow --> answer )

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;


    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       8080;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }

    location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

    location /stat.xsl {
            # you can move stat.xsl to a different location
            root /usr/build/nginx-rtmp-module;
        }

        # rtmp control
        location /control {
            rtmp_control all;
        }

        # Client (VLC etc.) can access HLS here.
        location /hls {
           # Serve HLS fragments
           types {
             application/vnd.apple.mpegurl m3u8;
             video/mp2t ts;
           }
           root /tmp;
           add_header Cache-Control no-cache;
         }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

}

rtmp {
        server {
                listen 1935;
                chunk_size 4096;

                application live {
                        live on;
                        record off;
                }

                application directo {
                        live on;
                        record off;
                }

                # You should send x.264/aac RTMP Stream via ffmpeg to this application
                 application hls {
                   allow play all;
                   live on;
                   hls on;
                   hls_path /tmp/hls;
                 }
        }
}

And this is a capture of the OBS streaming configuration:

enter image description here

PC can view the stream just fine, but mobile can't.

Appreciate any input anyone may have.

Answer

Alexandre LICINIO picture Alexandre LICINIO · Jan 8, 2018

I did test over ubuntu 16.04 LTS and it works with that following instructions:

cd $HOME
git clone https://github.com/arut/nginx-ts-module.git
wget https://nginx.org/download/nginx-1.13.8.tar.gz
git clone https://github.com/sergey-dryabzhinsky/nginx-rtmp-module.git
sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev
tar -xf nginx-1.13.8.tar.gz 
cd nginx-1.13.8/
sudo apt update
sudo apt install autoconf automake build-essential libpcre3 libpcre3-dev libssl-dev
./configure --with-http_ssl_module --add-module=../nginx-rtmp-module --with-http_stub_status_module --add-module=../nginx-ts-module
make
sudo make install

Then you need to update the .conf file:

cd /usr/local/nginx/conf/
sudo nano nginx.conf

Conf file:

worker_processes  auto;
events {
    worker_connections  1024;
}

# RTMP configuration
rtmp {
    server {
        listen 1935; # Listen on standard RTMP port
        chunk_size 4000;

        application show {
            live on;
            # Turn on HLS
            hls on;
            hls_path /mnt/hls/;
            hls_fragment 3;
            hls_playlist_length 60;
            # disable consuming the stream from nginx as rtmp
            deny play all;
    # Instruct clients to adjust resolution according to bandwidth
            hls_variant _low BANDWIDTH=512000; # Low bitrate, sub-SD resolution
            hls_variant _mid BANDWIDTH=1024000; # Medium bitrate, SD resolution
            hls_variant _hd720 BANDWIDTH=2048000; # High bitrate, HD 720p resolution
        }

    }
}

http {
    sendfile off;
    tcp_nopush on;
    #aio on;
    directio 512;
    default_type application/octet-stream;

    server {
        listen 8080;

        location / {
            # Disable cache
            add_header 'Cache-Control' 'no-cache';

            # CORS setup
            add_header 'Access-Control-Allow-Origin' '*' always;
            add_header 'Access-Control-Expose-Headers' 'Content-Length';

            # allow CORS preflight requests
            if ($request_method = 'OPTIONS') {
                add_header 'Access-Control-Allow-Origin' '*';
                add_header 'Access-Control-Max-Age' 1728000;
                add_header 'Content-Type' 'text/plain charset=UTF-8';
                add_header 'Content-Length' 0;
                return 204;
            }

            types {
                application/dash+xml mpd;
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
        location /stats {
        stub_status;
        }


            root /mnt/;
        }

To start your nginx server (first kill it then start it):

sudo /usr/local/nginx/sbin/nginx -s stop
sudo /usr/local/nginx/sbin/nginx

To view stats of your nginx server: Where is the public ip of your server.

http://<ip_of_your_nginx_server>:8080/stats

From your encoder such as OBS: Stream to your nginx server with that adress:

  • rtmp:///show/stream_hd720 Do a 1280x720 at 2500kbps and 1 audio stereo at 128kbps

If you want to see your stream on VLC: Open a network stream then paste that:

http://<ip_of_your_nginx_server>:8080/hls/stream.m3u8

You should see your stream.

If you want to host a HLS player where your viewers can watch your stream for free:

sudo apt install screen

Put your http server in a screen session:

screen -dmS httpSTREAM

Access to your screen:

screen -r httpSTREAM

Then start your server:

python -m SimpleHTTPServer 7788

Create your html page with Hls player:

touch player.html
sudo nano player.html

and paste: Change that line with the correct ip hls.loadSource('http://<ip_of_your_nginx_server>:8080/hls/stream.m3u8'); to your needs

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>CHAN.1</title>

    <!-- Bootstrap -->
    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

    <!-- Optional theme -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

    <!-- Latest compiled and minified JavaScript -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
<body>

<h1>CHAN 2018 - STREAM.1</h1>

<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<div class="well">
<div class="embed-responsive embed-responsive-16by9">
   <video id="video" width=720 class="video-js vjs-default-skin" controls></video>
 </div>
</div>
<script>
  if(Hls.isSupported()) {
    var video = document.getElementById('video');
    var hls = new Hls();
    hls.loadSource('http://163.172.128.64:8080/hls/stream.m3u8');
    hls.attachMedia(video);
    hls.on(Hls.Events.MANIFEST_PARSED,function() {
      video.play();
  });
 }
</script>

<div id="footer">
      <font size="2">&nbsp;&copy; Ekla Ingenierie - 2018 <a href="http://www.ekla.tv">www.ekla.tv</a></font>
</div>

</body>
</html>
obe@scw-eklaingenierie-c2:~$ cat player.html 
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>CHAN.1</title>

    <!-- Bootstrap -->
    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

    <!-- Optional theme -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

    <!-- Latest compiled and minified JavaScript -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
<body>

<h1>My Stream</h1>

<div class="well">
<div class="embed-responsive embed-responsive-16by9">
   <video id="video" width=720 class="video-js vjs-default-skin" controls></video>
 </div>
</div>
<script>
  if(Hls.isSupported()) {
    var video = document.getElementById('video');
    var hls = new Hls();
    hls.loadSource('http://<ip_of_your_nginx_server>:8080/hls/stream.m3u8');
    hls.attachMedia(video);
    hls.on(Hls.Events.MANIFEST_PARSED,function() {
      video.play();
  });
 }
</script>

<div id="footer">
      <font size="2">&nbsp;&copy; MyStreaming - 2018</font>
</div>

</body>
</html>

Then access to your player from a chrome browser and paste that link:

http://<ip_of_your_nginx_server>:7788/player.html

Now you do a complete streaming !!