How to set up your own private RTMP server using nginx

All Versions How to set up your own private RTMP server using nginx

kpcenti

New Member
Code:
rtmp {
    server {
        listen 1935;
       
        application view {
            live on;
            recorder all {
                record all;
                record_path html; #this folder should exist before streaming to your server
                record_lock on;
                record_unique on;
            }
        }
    }
}

Thanks! I'll try this soon

Also is there a extra config to set up 2 simultaneous streams? It gets finicky when i try to send 2 streams to the server
 

Tarumes

Member
Thanks! I'll try this soon

Also is there a extra config to set up 2 simultaneous streams? It gets finicky when i try to send 2 streams to the server

add a second aplication in your config is the easy way
Code:
rtmp {
    server {
        listen 1935;
        
        application view {
            live on;
            recorder all {
                record all;
                record_path html; #this folder should exist before streaming to your server
                record_lock on;
                record_unique on;
            }
        }
        application view2 {
            live on;
            recorder all {
                record all;
                record_path html; #this folder should exist before streaming to your server
                record_lock on;
                record_unique on;
            }
        }
    }
}
 

ev3rla5t

New Member
Hi, can anyone help?
I followed the OP guide for streaming to a raspberry pi, I have compiled nginx with this rtmp module:

https://github.com/arut/nginx-rtmp-module
Version 1.2.1 because it seems that its updated more often.
I have my obs streaming to the raspberry pi (I also managed to stream to my own website, so it can be watched from a web browser).

The problem I have is that I don't get any audio.
There is audio coming in because I am able to hear it if I monitor the inputs on the obs screen, but when I check my stream in VLC, I don't get any sound.

I've tried it with and without several "exec ffmpeg" settings also, and also without ffmpeg commands at all. I still get no audio.
I'm unsure what the problem is.
Would anyone be able to help?
Thanks.
 

ev3rla5t

New Member
Hi, can anyone help?
I followed the OP guide for streaming to a raspberry pi, I have compiled nginx with this rtmp module:

https://github.com/arut/nginx-rtmp-module
Version 1.2.1 because it seems that its updated more often.
I have my obs streaming to the raspberry pi (I also managed to stream to my own website, so it can be watched from a web browser).

The problem I have is that I don't get any audio.
There is audio coming in because I am able to hear it if I monitor the inputs on the obs screen, but when I check my stream in VLC, I don't get any sound.

I've tried it with and without several "exec ffmpeg" settings also, and also without ffmpeg commands at all. I still get no audio.
I'm unsure what the problem is.
Would anyone be able to help?
Thanks.

Update: I think I got it working, there was a problem with the coreaudio encoder, I followed the instructions on a post about extracting and installing the Apple MSI, works like a charm!
 

Tuxnician

New Member
Great guide! I have a working server that sends out to Youtube properly. When I use OBS to send a stream to the rtmp server I created it streams to Youtube and I can watch it on VLC. When I use the same server and stream from a Tricaster the stream works to Youtube but I cannot see the stream on VLC. The only difference is the source sending to the nginx server. I'm not sure why it doesn't work on VLC.
 

Tarumes

Member
i have not given up
did find and tested with nginx-rtmp and Novage p2p-media-loader a working p2p-hls-stream.
here are the links to their demo and to github
Demo
Github
 

Tuxnician

New Member
Great guide! I have a working server that sends out to Youtube properly. When I use OBS to send a stream to the rtmp server I created it streams to Youtube and I can watch it on VLC. When I use the same server and stream from a Tricaster the stream works to Youtube but I cannot see the stream on VLC. The only difference is the source sending to the nginx server. I'm not sure why it doesn't work on VLC.
Fixed it. The tricaster added an extra stream key and once added VLC started to work as well.
 

visio

New Member
I couldn't get it to work the HLS part, if there is no HLS then it is useless. HLS is mandatory for streaming to mobile devices and tablets. Given that mobile devices now make up the majority of internet traffic (around 52.2% of traffic in 2018), HLS is essential for these users as well. RTMP is still very useful for the broadcaster to stream to a server, then this server must encode to HLS URL so it can stream on most devices. I love OBS and actually to our customers we recommend the use of OBS as encoder.
I think this kind of RTMP servers Nginx or red5, are really difficult to setup and manage, and how much it would cost? with our RTMP server it is setup in a moment with a stable and easily configured by the customer rtmp control panel.
 

MikeRen

New Member
It takes a decent amount. Tonight, I had 2 cameraman streams upload to my server at 2500 kbps (2.5 Mbps), and then I downloaded both of them simultaneously, so the bandwidth cost was doubled with both upload and download). Overall, I burned through over 11 gigs of transfer on my VPS for a 2-hour cast.

As for bandwidth pipe size, you'll need enough to download at the speed they are uploading, probably with some headroom. It's something you'll need to experiment with.

Nice
 

Flimmykins

New Member
hey, I'm trying to set up a private stream on my site. I'm trying to use HLS, but when I try load it, the video doesn't play then says: "The media could not be loaded, either because the server or network failed or because the format is not supported. "

I had it set up last year, but I forgot everything I did at the time. If I link someone the rtmp url, it plays fine for them in VLC, but the HLS part isn't working on my site. Can someone help me figure out what I'm doing wrong? Thanks.
Code:
worker_processes  auto;
events {
    worker_connections  1024;
}

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

        application live {
            live on;
            hls on;
            hls_path c:/nginx/hls/;
            hls_fragment 3;
            hls_playlist_length 10;
            # disable consuming the stream from nginx as rtmp
            # deny play all;
        }
    }
}

http {
    sendfile off;
    tcp_nopush on;
    aio off;
    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;
            }

            root /nginx/;
        }
    }
}

This produces a stream.m3u8 file in "c:/nginx/hls", and in OBS I have it set like this:
Server: rtmp://public-ip-address/live
Key: stream

This is what my stream html looks like, with all the code removed besides the video parts:
Code:
<!DOCTYPE html>
<html>

<head>
    <meta charset=utf-8 />
    <title>blah</title>
    <link rel="icon" href="blah">

    <link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
    <script src="https://unpkg.com/video.js/dist/video.js"></script>
    <script src="https://unpkg.com/videojs-contrib-hls/dist/videojs-contrib-hls.js"></script>
    <link rel="stylesheet" href="style.css">

</head>

<body>
    <img class="overlay" src="blah" />
    <video class="video-js vjs-default-skin center" autoplay width="1280" height="720" poster="https://i.imgur.com/bQoBOiB.png" data-setup='{}'>
        <source src="http://public-up-address/hls/stream.m3u8" type="application/x-mpegURL">
    </video>
</body>

</html>
 

Tarumes

Member
hey, I'm trying to set up a private stream on my site. I'm trying to use HLS, but when I try load it, the video doesn't play then says: "The media could not be loaded, either because the server or network failed or because the format is not supported. "

I had it set up last year, but I forgot everything I did at the time. If I link someone the rtmp url, it plays fine for them in VLC, but the HLS part isn't working on my site. Can someone help me figure out what I'm doing wrong? Thanks.
Code:
worker_processes  auto;
events {
    worker_connections  1024;
}

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

        application live {
            live on;
            hls on;
            hls_path c:/nginx/hls/;
            hls_fragment 3;
            hls_playlist_length 10;
            # disable consuming the stream from nginx as rtmp
            # deny play all;
        }
    }
}

http {
    sendfile off;
    tcp_nopush on;
    aio off;
    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;
            }

            root /nginx/;
        }
    }
}

This produces a stream.m3u8 file in "c:/nginx/hls", and in OBS I have it set like this:
Server: rtmp://public-ip-address/live
Key: stream

This is what my stream html looks like, with all the code removed besides the video parts:
Code:
<!DOCTYPE html>
<html>

<head>
    <meta charset=utf-8 />
    <title>blah</title>
    <link rel="icon" href="blah">

    <link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
    <script src="https://unpkg.com/video.js/dist/video.js"></script>
    <script src="https://unpkg.com/videojs-contrib-hls/dist/videojs-contrib-hls.js"></script>
    <link rel="stylesheet" href="style.css">

</head>

<body>
    <img class="overlay" src="blah" />
    <video class="video-js vjs-default-skin center" autoplay width="1280" height="720" poster="https://i.imgur.com/bQoBOiB.png" data-setup='{}'>
        <source src="http://public-up-address/hls/stream.m3u8" type="application/x-mpegURL">
    </video>
</body>

</html>
I can give you my working example
Code:
worker_processes  auto;
worker_priority -20;
worker_shutdown_timeout 5;

error_log  logs/error.log;

events {
    worker_connections  1024;
}
rtmp_auto_push on;
rtmp_auto_push_reconnect 1s;

rtmp {
    server {
        listen 1935;
       
        application local {
            live on;
            deny play all;
            push rtmp://127.0.0.1/view/stream;
        }
       
        application view {
            live on;
            allow publish 127.0.0.1;
            deny publish all;
            hls on;
            hls_path html/hls;
            hls_fragment 5s;
            hls_playlist_length 30s;
            hls_fragment_naming timestamp;
            hls_fragment_slicing aligned;
            hls_type live;
            hls_cleanup on;
            recorder all {
                record all;
                record_path html/record/stream;
                record_lock on;
                record_unique on;
            }
        }
    }
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        off;
    server_tokens off;
   
    server {
        listen      8080;
       
        location / {
            root html;
        }
       
        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        location /stat.xsl {
            #auth_basic           "closed site";
            #auth_basic_user_file htpasswd;
            root html;
        }
        location /control {
            #auth_basic           "closed site";
            #auth_basic_user_file conf/htpasswd;
            rtmp_control all;
        }
    }
}
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta name="description" content="MediaDB">
    <meta name="author" content="Tarumes">
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
   
    <link href="css/style.css" rel="stylesheet" type="text/css"/>
    <link href="css/style_video.css" rel="stylesheet" type="text/css"/>
    <link href="css/bootstrap.css" rel="stylesheet" type="text/css"/>
   
    <script src="js/jquery-3.4.1.min.js"></script>
    <script src="js/p2p-media-loader-core.min.js"></script>
    <script src="js/p2p-media-loader-hlsjs.min.js"></script>
    <script src="js/hls.js"></script>
    <title></title>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="h-auto col">
                <video id="video" autoplay=true controls muted style="max-height: 720px;"></video>
            </div>
            <div id="chat_container" class="col-m-2 col-l-2 col-xl-2">
                <div class="container">
                    <div class="row">
                        <div id="chat_main" class="col">Chat Main</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
   
    <script src="js/jquery-3.4.1.min.js"></script>
    <script src="js/popper.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <script>
        if (Hls.isSupported() && p2pml.hlsjs.Engine.isSupported()) {
            var engine = new p2pml.hlsjs.Engine();
            var hls = new Hls({
                liveSyncDurationCount: 2, // To have at least 6 segments in queue
                loader: engine.createLoaderClass()
            });
            p2pml.hlsjs.initHlsJsPlayer(hls);
            hls.loadSource("hls/stream.m3u8");
            var video = document.getElementById("video");
            hls.attachMedia(video);
        } else {
            document.write("Not supported :(");
        }
    </script>
</body>
</html>
the files for this p2p and hls you can get from
https://github.com/Novage/p2p-media...er-hlsjs#p2p-media-loader---hlsjs-integration
 

dude225

New Member
anyone mind giving me a hand? i seem to have everything working but i can't seem to get playback support on android. I'm using NGINX with videojs, things seem great except just no android playback.
 

yogesh12

New Member
Hey Guys! Sorry to be a pain here...

I jsut want to know how can i make dynamic variables in nginx cconf file.. i have got a lot of stream keys and i wish to pass them via parameters and then stream via stunnel! Any Help is much appreciated!
 

Tarumes

Member
Hey Guys! Sorry to be a pain here...

I jsut want to know how can i make dynamic variables in nginx cconf file.. i have got a lot of stream keys and i wish to pass them via parameters and then stream via stunnel! Any Help is much appreciated!
This is only be possible with exec
only aviable at linux
https://github.com/arut/nginx-rtmp-module/wiki/Directives#exec

ffmpeg -re -i rtmp://127.0.0.1/$app/$name -c copy -f flv rtmp://live-fra.twitch.tv/app/$name
 

yogesh12

New Member
This is only be possible with exec
only aviable at linux
https://github.com/arut/nginx-rtmp-module/wiki/Directives#exec

ffmpeg -re -i rtmp://127.0.0.1/$app/$name -c copy -f flv rtmp://live-fra.twitch.tv/app/$name

Command i am using is

ffmpeg -re -i http://my.ip.of.video.file/videos/filename.mp4 -c:v libx264 -profile:v main -level 31 -preset slow -b:v 800k -c:a aac -strict -2 -ar 44100 -ab 128k -ac 2 -flags +global_header -f flv rtmp://127.0.0.1:19350/rtmp/key

and yes i am on Centos 7.3 64 Bit.

So will the code will look like

exec ffmpeg -re -i http://my.ip.of.video.file/videos/filename.mp4 -c:v libx264 -profile:v main -level 31 -preset slow -b:v 800k -c:a aac -strict -2 -ar 44100 -ab 128k -ac 2 -flags +global_header -f flv rtmp://127.0.0.1:19350/rtmp/$my_Variable=mykey

and in nginx will i have to do this

push rtmp://127.0.0.1:19350/rtmp/$my_variable;

how to send and catch the variable and use that in push statement?
 

Aiursrage2k

New Member
Is there any updated tutorials to do this. I tried with both AWS windows, and unbutu AWS ? I was able to get it to stream to RTMP, but was not able to get it to HSL (or it did but didnt work in the encoder).
 

Yensid

New Member
Hiya,

I have read through most of the comments and keep getting more confused. Here is my setup & what I am trying to accomplish.

I have a PC running OBS with
- Stream/Service set as Custom
- Server: rtmp://computername:1935/live
- Stream Key: live
- output encoder is x264

I also on the same computer have NGINX running with videojs.

I have it setup so I can view the RTMP remotly via VLC however whenever I try to get it to work via a web browser via HLS all I get is:
The media could not be loaded, either because the server or network failed or because the format is not supported.
or
A black screen.

I can confirm that the the HLS folder I have set is getting an m3u8 file and .ts files.

What am I doing wrong
 
Top