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

19,328

Solution 1

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 !!

Solution 2

First of all, you have to point your encoders to your server's ip address through the RTMP option, that would be the first thing. Then, after that you have to add a directive to the configuration file you just posted, for example:

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

    # This application is to accept incoming stream
    application live {
        live on; # Allows live input

        # Once receive stream, transcode for adaptive streaming
        # This single ffmpeg command takes the input and transforms
        # the source into 4 different streams with different bitrate
        # and quality. P.S. The scaling done here respects the aspect
        # ratio of the input.
        exec ffmpeg -i rtmp://localhost/$app/$name -async 1 -vsync -1
                    -c:v libx264 -c:a libvo_aacenc -b:v 256k -b:a 32k -vf "scale=480:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://localhost/show/$name_low
                    -c:v libx264 -c:a libvo_aacenc -b:v 768k -b:a 96k -vf "scale=720:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://localhost/show/$name_mid
                    -c:v libx264 -c:a libvo_aacenc -b:v 1024k -b:a 128k -vf "scale=960:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://localhost/show/$name_high
                    -c:v libx264 -c:a libvo_aacenc -b:v 1920k -b:a 128k -vf "scale=1280:trunc(ow/a/2)*2" -tune zerolatency -preset veryfast -crf 23 -f flv rtmp://localhost/show/$name_hd720
                    -c copy -f flv rtmp://localhost/show/$name_src;
    }

    # This application is for splitting the stream into HLS fragments
    application show {
        live on; # Allows live input from above
        hls on; # Enable HTTP Live Streaming

        # Pointing this to an SSD is better as this involves lots of IO
        hls_path /mnt/hls/;

        # Instruct clients to adjust resolution according to bandwidth
        hls_variant _low BANDWIDTH=288000; # Low bitrate, sub-SD resolution
        hls_variant _mid BANDWIDTH=448000; # Medium bitrate, SD resolution
        hls_variant _high BANDWIDTH=1152000; # High bitrate, higher-than-SD resolution
        hls_variant _hd720 BANDWIDTH=2048000; # High bitrate, HD 720p resolution
        hls_variant _src BANDWIDTH=4096000; # Source bitrate, source resolution
    }
}
}

http {

# This optimizes the server for HLS fragment delivery
sendfile off;
tcp_nopush on;
aio on;
directio 512;

# HTTP server required to serve the player and HLS fragments
server {
    listen 80;

    location / {
        root /path/to/web_player/;
    }

    location /hls {
        types {
            application/vnd.apple.mpegurl m3u8;
        }

        root /mnt/;
        add_header Cache-Control no-cache; # Prevent caching of HLS fragments
        add_header Access-Control-Allow-Origin *; # Allow web player to access our playlist
    }
}
}
Share:
19,328
Chayemor
Author by

Chayemor

When I'm not musing over technology I deviate to my creative side, helps me clear out. You can find some repos over at my Bitbucket account. You can check that side out in: Instagram or Twitter If I'm not there then I'm probably getting code-shamed in the CodeFights arena, that ticking timer reminds me of Super Mario's wall chasing you and making you fall into the lava, hahaha. Clk clk!!

Updated on June 20, 2022

Comments

  • Chayemor
    Chayemor almost 2 years

    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.

  • Meirza
    Meirza over 5 years
    Whois trigger rtmp://ip/live ?
  • Ashad Nasim
    Ashad Nasim over 3 years
    what endpoint we need to send the input and where we will get it?