Nginx RTMP/HLS - stream to ffmpeg and output HLS - nginx

At this point my solution is working but only as RTMP, i can watch perfectly my stream using the URL:
rtmp://X.X.X.X:1935/show/name
But the problem is that my LG Smart Tv which uses WebOS don't support RTMP and i would really like to play my stream there. The only solution that i can see right now is to use HLS. With HLS all works fine too, but i need to execute my ffmpeg command before open the HLS stream in TV, otherwise it will not create the files necessary to display the stream on my TV.
So my goal is to serve a stream as HLS without having to trigger the RTMP endpoint or the FFMPEG manually.
I'm really struggling with this, waste 3 days trying to make it work :(
http
{
location /hls
{
# 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/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /mnt/;
}
}
}
rtmp {
server {
listen 1935;
chunk_size 4000;
buflen 5s;
application show {
live on;
exec_pull ffmpeg -re -i http://stream-coming.com/$name.ts -c:v libx264 -preset faster -pix_fmt yuv420p -c:a aac -f flv rtmp://localhost/show/$name;
# 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;
}
}
}
Thanks for your time ;)

Try instead something like this:
rtmp {
server {
listen 1935;
application show {
live on;
exec_push ffmpeg -re -i rtmp://stream-coming.com:1935/$name.ts
-c:v libx264 -preset faster -pix_fmt yuv420p -c:a aac -f flv rtmp://localhost:1935/hls/$name;
exec_kill_signal term;
}
application hls {
# Turn on HLS
live on;
hls on;
hls_path /mnt/hls/;
hls_fragment 3;
hls_playlist_length 12;
# disable consuming the stream from nginx as rtmp
allow publish 127.0.0.1;
deny play all;
}
}
}

Related

How to trigger nginx-rtmp pull from the ingest server on client requests a .m3u8 video through load balancer

I have a ingest nginx-rtmp server which act as a single source of rtmp streams for worker nodes.
Ingest instance gets the rtmp through OBS. Now when client request a video through load balancer like https://load-balancer.com/hls/test.m3u8
Load balancer sends this request to one of the worker nodes.
The worker nodes has following nginx config file.
worker_processes auto;
events {
worker_connections 1024;
}
# RTMP configuration
rtmp {
server {
listen 1935; # Listen on standard RTMP port
chunk_size 4000;
# Define the Application
application show {
live on;
pull rtmp://localhost:1935/stream/ live=1;
# 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;
}
}
}
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;
}
root /mnt/;
}
}
}
The nginx-rtmp pull of this worker node will not work until anyone request for it. Hence it will not generate the hls file for the http request.
Note: I can not push the stream to the worker nodes as the worker noders are being auto scalled and does not have a fix number.
I wasn to know a solution by which, Whenever a client request a video which and the worker node gets the https request, Some how the rtmp server application show gets a hit and pull the video from the ingest server and generates the hls block and the http request can be fulfilled.

NGINX-RTMP-MODULE: [error] hls: force fragment split

I am trying to transcode incoming live RTMP stream to HLS stream using nginx-rtmp-module.
The HLS streaming works fine for few seconds and then it starts throwing the following error:
2020/08/22 00:14:18 [error] 10#10: *3 hls: force fragment split: 10.027 sec, , client: 127.0.0.1, server: 0.0.0.0:1935
This is my nginx configuration file.
daemon off;
error_log /dev/stdout info;
events {
worker_connections 1024;
}
rtmp {
server {
listen ${RTMP_PORT};
chunk_size 4000;
application stream {
live on;
exec ffmpeg -i rtmp://localhost:1935/stream/$name -v verbose
-c:a libfdk_aac -b:a 128k -c:v libx264 -b:v 2500k -f flv -g 150 -r 30 -s 1280x720 -preset superfast -profile:v baseline rtmp://localhost:1935/hls/$name_720p2628kbs;
}
application hls {
live on;
hls on;
hls_fragment_naming sequential;
hls_fragment 5s;
hls_max_fragment 10s;
hls_playlist_length 20s;
hls_path /opt/data/hls;
hls_nested on;
hls_variant _720p2628kbs BANDWIDTH=2628000,RESOLUTION=1280x720;
}
}
}
http {
access_log /dev/stdout combined;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
server {
listen ${HTTP_PORT};
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /opt/data;
add_header Cache-Control no-cache;
add_header Access-Control-Allow-Origin *;
}
location /live {
alias /opt/data/hls;
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
add_header Cache-Control no-cache;
add_header Access-Control-Allow-Origin *;
}
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet static/stat.xsl;
}
location /static {
alias /www/static;
}
location = /crossdomain.xml {
root /www/static;
default_type text/xml;
expires 24h;
}
}
}
Can someone please help me with this issue?

nginx rtmp conf using argument

i configure server using nginx - rtmp plugin module.
The Problem is rtmp publish.
rtmp plugin module support "on_publish_done" command.
https://github.com/arut/nginx-rtmp-module/wiki/Directives#on_publish_done
and i want like this.
on_publish_done http://MY_SERVER/$APP/$NAME ;
In nginx configure file(nginx.conf) can use $arg_XXX value.
But my conf-file can not observe value. Observe just string "$arg_app", "$arg_name".
How to observe $arg_app, $arg_name ??
this is my conf file.
# HTTP can be used for accessing RTMP stats
http {
access_log /Users/steve/dev/workspace/nginx/logs/access.log;
server {
listen 8080;
location /local_redirect {
rewrite ^.*$ newname? permanent;
}
location /cast {
# Serve HLS fragments
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /Users/steve/dev/workspace/nginx/tmp;
add_header Cache-Control no-cache;
}
}
}
rtmp {
access_log /PATH/nginx/logs/rtmp-access.log;
server {
listen 1935;
chunk_size 4000;
application cast {
live on;
publish_notify on;
hls on;
hls_path /PATH/workspace/nginx/out;
hls_nested on;
hls_fragment 1s;
hls_playlist_length 12s;
}
notify_method get;
on_publish_done http://127.0.0.1:5000/$arg_app/$arg_name ; ##PROBLEM HERE!!
}
}
[the image below shows that a variable with an underscore which is located between character r and b works well! ][1]
for me the code below using bash command with a -c flag works! try it bro
exec_publish_done bash -c "/var/hls/ex.sh ${name}";

How to fix RTMP_Connect0, failed to connect socket. 111 (Connection refused)?

I'm getting this error when trying to push m3u8 stream source to my Nginx RTMP server
this my FFmpeg command
ffmpeg -re -i https://xxxxxxxxxxxxxxx.akamaihd.net/hls/live/621275/1539097700001/master_1080p.m3u8 -c:v copy -c:a aac -ar 44100 -ab 128k -ac 2 -strict -2 -flags +global_header -bsf:a aac_adtstoasc -bufsize 700k -f flv rtmp://xx.xxx.xx.156/tmp/hls/stream
and this is my Nginx conf file:
#user nobody;
worker_processes 1;
error_log logs/rtmp_error.log debug;
pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
location /hls {
# Serve HLS fragments
# 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/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp;
add_header Cache-Control no-cache;
}
}
}
rtmp {
server {
listen 1935;
chunk_size 8192;
application hls {
live on;
meta copy;
hls on;
hls_path /tmp/hls/stream;
}
}
}
I assume this is a clear indicator of my problem.
If anyone knows, feel free to comment of course.
regards
your firewall's 1935 port is not open.
open port by:
firewall-cmd --permanent --add-service=http # permanently enable HTTP connections on port 80
firewall-cmd --zone=public --add-port=1935/tcp --permanent
firewall-cmd --list-ports # check
firewall-cmd --reload
for the whole flow of building ffmpeg in Centos, see my tutorial at https://github.com/magictomagic/magictomagic.github.io/blob/master/_posts/2020-05-04-CentOS-FFmpeg-%E6%B5%81%E5%AA%92%E4%BD%93%E6%92%AD%E6%94%BE.md
the environment is CentOS 8.

Setting up nginx to stream HLS/RTMP simultaneously

I have an nginx web server with the RTMP module running perfectly and pushing out video to several RTMP destinations (Facebook, YouTube, Periscope, etc.).
I now need the stream to output in the HLS protocol so I can build a custom player for it without flash dependency. I've tried following a few other tutorials, but I am struggling.
I have the default config file that came with the installation of nginx with the following added to the end:
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
push rtmp://<streaming-service/key>
}
}
}
What exactly do I need to add to this config file to retain my ability to push out video to these RTMP destinations as well as have a HLS feed I can use in a player without Flash?
I already have FFMPEG installed on the machine in order to send video to Periscope. I've seen solutions that do not need FFMPEG, but I just wanted to add that I did have it installed and am somewhat familiar with it.
EDIT: for more information, I am sending video through the server via a Teradek encoder.
I solved this with FFMPEG. The pull directive wasn't working properly. Here's the config file that worked for me:
#user nobody;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
server {
listen 80;
server_name localhost;
location /hls {
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp/;
add_header Cache-Control no-cache;
add_header 'Access-Control-Allow-Origin' '*';
}
location / {
root html;
index index.html index.htm;
}
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;
push rtmp://<location/key>
exec ffmpeg -i rtmp://localhost/live/test -vcodec libx264 -vprofile baseline -x264opts keyint=40 -acodec aac -strict -2 -f flv rtmp://localhost/hls/test;
}
application hls {
live on;
hls on;
hls_path /tmp/hls/;
hls_fragment 6s;
hls_playlist_length 60s;
}
}
}

Resources