Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 547
Chayemor Avatar asked Aug 04 '16 10:08

Chayemor


People also ask

Does Nginx accept RTMP as input?

nginx accepts rtmp stream as input. For a proper HLS stream the video codec should be x264 and audio codec aac / mp3 / ac3 most commonly being aac. if you have an existing rtmp stream in the correct codec, you can skip ffmpeg and tell nginx to pull the stream directly.

How do I push a live stream to Nginx?

4. Pushing live stream to nginx using rtmp nginx accepts rtmp stream as input. For a proper HLS stream the video codec should be x264 and audio codec aac / mp3 / ac3 most commonly being aac. if you have an existing rtmp stream in the correct codec, you can skip ffmpeg and tell nginx to pull the stream directly.

What is the host and stream key in Nginx?

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.

How to make a RTMP stream using FFmpeg?

There are several source from which you can produce an rtmp stream. here are couple examples: Update localhost to your nginx server ip/domain Capture webcam on /dev/video0 and stream it to nginx 1 ffmpeg -re -f video4linux2 -i /dev/video0 -vcodec libx264 -vprofile baseline -acodec aac -strict -2 -f flv rtmp://localhost/show/stream


2 Answers

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

like image 57
Alexandre LICINIO Avatar answered Oct 05 '22 11:10

Alexandre LICINIO


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
    }
}
}
like image 41
superdianix Avatar answered Oct 05 '22 12:10

superdianix