HLS using Nginx RTMP Module not working - nginx

So I installed NGINX and the RTMP MODULE on my mac in the usr/local/nginx location. RTMP stream works fine just not the HLS version. Here is my config file:
events {
worker_connections 1024;
}
rtmp {
server {
listen 1936;
chunk_size 4000;
application small {
live on;
# Video with reduced resolution comes here from ffmpeg
}
# video on demand
application vod {
play /var/flvs;
}
application vod2 {
play /var/mp4s;
}
# Many publishers, many subscribers
# no checks, no recording
application videochat {
live on;
# The following notifications receive all
# the session variables as well as
# particular call arguments in HTTP POST
# request
# Make HTTP request & use HTTP retcode
# to decide whether to allow publishing
# from this connection or not
on_publish http://localhost:8080/publish;
# Same with playing
on_play http://localhost:8080/play;
# Publish/play end (repeats on disconnect)
on_done http://localhost:8080/done;
# All above mentioned notifications receive
# standard connect() arguments as well as
# play/publish ones. If any arguments are sent
# with GET-style syntax to play & publish
# these are also included.
# Example URL:
# rtmp://localhost/myapp/mystream?a=b&c=d
# record 10 video keyframes (no audio) every 2 minutes
record keyframes;
record_path /tmp/vc;
record_max_frames 10;
record_interval 2m;
# Async notify about an flv recorded
on_record_done http://localhost:8080/record_done;
}
# HLS
# For HLS to work please create a directory in tmpfs (/tmp/hls here)
# for the fragments. The directory contents is served via HTTP (see
# http{} section in config)
#
# Incoming stream must be in H264/AAC. For iPhones use baseline H264
# profile (see ffmpeg example).
# This example creates RTMP stream from movie ready for HLS:
#
# ffmpeg -loglevel verbose -re -i movie.avi -vcodec libx264
# -vprofile baseline -acodec libmp3lame -ar 44100 -ac 1
# -f flv rtmp://localhost:1935/hls/movie
#
# If you need to transcode live stream use 'exec' feature.
#
application hls {
live on;
hls on;
hls_path /tmp/hls;
}
# MPEG-DASH is similar to HLS
application dash {
live on;
dash on;
dash_path /tmp/dash;
}
}
}
# HTTP can be used for accessing RTMP stats
http {
server {
listen 8080;
# This URL provides RTMP statistics in XML
location /stat {
rtmp_stat all;
# Use this stylesheet to view XML as web page
# in browser
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
# XML stylesheet to view RTMP stats.
# Copy stat.xsl wherever you want
# and put the full directory path here
root /path/to/stat.xsl/;
}
location /hls {
# Serve HLS fragments
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp;
add_header Cache-Control no-cache;
}
location /dash {
# Serve DASH fragments
root /tmp;
add_header Cache-Control no-cache;
}
}
}
I am using the hls application to stream to. When I view the stream located at rtmp://ip:1936/hls/test i can see it fine. When I try and view http://ip:1936/hls/test.m3u8 I cannot see it. I created a folder in this location for hls /usr/local/nginx/tmp/hls. Im wondering if this is in the right place as nothing is being created in the folder? Could it be permission issues?
I am using OBS to stream which uses x246 encoding video but not sure if it's AAC for audio.
A similar issue is being had here: https://groups.google.com/forum/#!topic/nginx-rtmp/dBKh4akQpcs
but no answer :(.
Any help is appreciated. Thanks.

you content for HLS is over port 8080 and rtmp is over 1936
meaning that rtmp://ip:1936/hls/test
or http://ip:8080/hls/test.m3u8

I got it fixed by changing to recording, with the following settings:
next to that, I also changed what JPhix mentioned.

seeing your config, but you place files under /tmp folder not under /usr/local/nginx (full path). If problem persists , an good strategy is start with one application with all of codecs (hls,mpeg-dash) ( like the config examples in github ).
P.D: this module is only for h264 and aac

Related

How to convert cctv footage to h265 for streaming and recording in nginx-rtmp module?

I am using the nginx-rtmp-module here to pull an rtsp stream from a camera on local network and convert it to rtmp. This rtmp stream is then converted to hls and made available for livestreaming. It is also being recorded in 5 min segments. (these things can all be seen in the nginx.conf below).
I want to change the video codec to h265 to save storage space, since each 5 min video is ~230mb, and using opencv and python, I was able to get <100mb per 5 min video using h265, so I know there is a lot of space for storage saving.
How can I change the codec of the stream to h265?
I have tried installing libx265-dev and setting -vcodec libx265, however this tells me flv is an invalid container and I'm getting nowhere with finding a valid container for streaming + recording.
My nginx.conf:
rtmp {
server {
listen 1935; # Listen on standard RTMP port
application relay {
live on;
hls on;
hls_path /tmp/hls;
hls_fragment 15s;
exec_static /usr/bin/ffmpeg -i rtsp://test:test#192.168.100.10:8554/fhd -vcodec copy -f flv rtmp://localhost:1935/relay/fhd;
# record block
record video;
record_path /tmp/hls;
record_unique on;
record_interval 5m;
}
}
}
The RTMP protocol does not have support for the h.265 codec. There is no standard way to do this.

nginx push rtmp stream to ffmpeg

On my Raspberry Pi with camera module, I try to setup a web-based streaming platform. I want to preview the stream in my browser and use CGI scripts to start/stop broadcasting to youtube (,...).
This is how I did the streaming setup so far:
Nginx puts up an RTMP application webcam. This is where I'll send the camera and audio stream usig ffmpeg. It publishes the stream as HLS for the web preview. It's also pushing the stream to another application source. That's where I want to (occasionally) hook up another ffmpeg process for broadcasting to youtube (,...) RTMP end points.
I initiate the stream using ffmpeg like this:
ffmpeg -loglevel debug -f v4l2 -framerate 15 -video_size 1280x720 -input_format h264 -i /dev/video0 -f alsa -i hw:2 -codec:v copy -g 15 -codec:a aac -b:a 128k -ar 44100 -strict experimental -f flv "rtmp://localhost:1935/webcam/hhart"
So far everything works fine. I can preview the HLS stream using a video.js viewer on my website (also served by nginx).
Now I want to start another ffmpeg process for broadcasting to my youtube channel, hooked up to the source application like this:
ffmpeg -loglevel debug -f flv -listen 1 -i rtmp://localhost:1935/source/hhart -c copy 'rtmp://a.rtmp.youtube.com/live2/<KEY>'
(in the final setup, launching and killing this process will be done via CGI scripts)
This is what ffmpeg returns:
Opening an input file: rtmp://localhost:1935/source/hhart.
[flv # 0x2032480] Opening 'rtmp://localhost:1935/source/hhart' for reading
[rtmp # 0x2032a10] No default whitelist set
[tcp # 0x20330f0] No default whitelist set
and then... nothing happens. There's no stream coming in at Youtube studio, but there are no error messages either.
Some other tests I did:
from the webcam application, push directly to the Youtube RTMP => that works! (but it's not what I want, because I want the HLS stream to be online always, but the broadcasting only when I'm going live.)
from VLC display the stream at rtmp://localhost:1935/source/hhart => similar to ffmpeg, there's no error message, the progress bar keeps loading.
So I have the impression that there is something going on, but there's no actual data transmitted.
RTMP section in nginx.conf:
rtmp {
server {
listen 1935;
chunk_size 4000;
application webcam {
live on;
hls on;
hls_path /Services/Webcam/HLSStream;
hls_fragment 3;
hls_playlist_length 60;
#deny play all;
push rtmp://localhost:1935/source/;
#push rtmp://a.rtmp.youtube.com/live2/<KEY>;
}
application source {
live on;
record off;
}
}
}
Of course, I may be totally on the wrong track, so any suggestions how I can realize my requirements in a better way, are welcome!
OK, I recompiled nginx with --with-debug and that got me to a solution.
Rather than pushing the stream to another application, I have to push the stream to an RTMP address on another port, and there the second ffmpeg process can pick it up. And it seems to be better to use 127.0.0.1 instead of localhost.
Like this:
rtmp {
server {
listen 1935;
chunk_size 4000;
application webcam {
live on;
hls on;
hls_path /Services/Webcam/HLSStream;
hls_fragment 3;
hls_playlist_length 60;
#deny play all;
push rtmp://127.0.0.1:1936/test/; # ADDED
record off;
}
}
}
Launching the broadcast to youtube:
ffmpeg -loglevel debug -f flv -listen 1 -i rtmp://127.0.0.1:1936/test/ -c copy -f flv 'rtmp://a.rtmp.youtube.com/live2/<KEY>'
Now my HLS stream is always online, and I can control broadcasting to youtube by launching/killing the second ffmpeg process.

Nginx limit upload speed

I use Nginx as the reverse proxy.
How to limit the upload speed in Nginx?
I would like to share how to limit the upload speed of reverse proxy in Nginx.
Limiting download speed is easy as a piece of cake, but not for upload.
Here is the configuration to limit upload speed
find your directory
/etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 1;
}
# 1)
# Add a stream
# This stream is used to limit upload speed
stream {
upstream site {
server your.upload-api.domain1:8080;
server your.upload-api.domain1:8080;
}
server {
listen 12345;
# 19 MiB/min = ~332k/s
proxy_upload_rate 332k;
proxy_pass site;
# you can use directly without upstream
# your.upload-api.domain1:8080;
}
}
http {
server {
# 2)
# Proxy to the stream that limits upload speed
location = /upload {
# It will proxy the data immediately if off
proxy_request_buffering off;
# It will pass to the stream
# Then the stream passes to your.api.domain1:8080/upload?$args
proxy_pass http://127.0.0.1:12345/upload?$args;
}
# You see? limit the download speed is easy, no stream
location /download {
keepalive_timeout 28800s;
proxy_read_timeout 28800s;
proxy_buffering off;
# 75MiB/min = ~1300kilobytes/s
proxy_limit_rate 1300k;
proxy_pass your.api.domain1:8080;
}
}
}
If your Nginx doesn't support the stream.
You may need to add a module.
static:
$ ./configure --with-stream
$ make && sudo make install
dynamic
$ ./configure --with-stream=dynamic
https://www.nginx.com/blog/compiling-dynamic-modules-nginx-plus/
Note:
If you have a client such as HAProxy, and Nginx as a server.
You may face 504 timeout in HAProxy and 499 client is close in the Nginx while uploading large files with limiting the low upload speed.
You should increase or add timeout server: 605s or over in HAProxy because we want HAProxy not to close the connection while Nginx is busy uploading to your server.
https://stackoverflow.com/a/44028228/10258377
Some references:
https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_upload_rate
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_limit_rate
You will find some other ways by adding third-party modules to limit the upload speed, but it's complex and not working fine
https://www.nginx.com/resources/wiki/modules/
https://www.nginx.com/resources/wiki/modules/upload/
https://github.com/cfsego/limit_upload_rate
Thank me later ;)

How to make Nginx HLS application pull RTMP on request

This is my situation: I want to use Nginx to serve streams over HTTP using HLS. The thing is, I want the HLS streams to be generated/started when I get a request for them.
I can successfully achieve this behavior with RTMP, as I have the following config file
application myApp {
live on;
exec_pull myScript.sh $app $name;
exec_kill_signal term;
}
In my myScript.sh file I have something like this:
ffmpeg -i sourceLink.m3u8 -codec copy -bsf:a aac_adtstoasc -f flv rtmp://localhost/$APP/$NAME;
So that when I request rtmp://myAddress/myApp/someLink it works perfectly.
However, I want to stream HLS instead of RTMP. I have seen other solutions that do this by having an application that starts the RTMP module and pushes it to the HLS application. However, what I want is that when I recieve a request for an HLS stream THEN the RTMP is started (which starts the FFmpeg), and as soon as the requests for the stream are over the RTMP stops receiving requests and thus stops the FFmpeg.
Here is my config file with what I have tried so far:
application myHLSApp {
live on;
pull rtmp://localhost:1935/myApp/someLink name=test static;
# 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;
}
My main objective is to start the FFmpeg in myScript.sh ONLY when it is needed to then stream that incoming file as HLS from my machine. Any ideas?
Thanks a lot for the help!

is that possible to serv hls and dash mpeg both at a time

actually i'm a kind a newbie to the Nginx RTMP server. I had setup my nginx.conf file to accept both hls and dash-mpeg. but the now problem is at a once I can able to serve either of the hls or dash-mpeg. so now my question is that possible to serve both hls and dash-mpeg at the same time for two different videos? I'm streaming video from OBS Studio.
here are my MPEG and hls code in nginx.conf file
rtmp {
server {
listen 1935; # Listen on standard RTMP port
chunk_size 4000;
application show {
live on;
# Turn on HLS
hls on;
hls_path /nginx/hls/;
hls_fragment 3;
hls_playlist_length 60;
deny play all;
}
application dash {
live on;
dash on;
dash_path /nginx/dash;
}
}
}
thank you advance.
yes, that is possible you can serve how many you need. it having 2 options(as i tried,)
1. you can use the OBS studio for streaming. or
2. You can use the FFmpeg command in the terminal to achieve it.
I suggest you use two terminals or 2 windows of OBS studio to make it possible. but be sure that your network is as strong to support the streaming 2 videos at once. try it and let us to know. and I guess you need to add some more configuration in the dash config. for more details refer to this page.peer5.com, if it is working give an upvote too;-)

Resources