Force ffmpeg to ignore error when connecting failed - nginx

I'm trying to deploy a live stream delivery system with nginx and nginx-rtmp-module.
For every node in my system, I wish it could 'forward' the live stream received to downstream node. I try to implement it by following config in my nginx.conf:
exec_push ffmpeg -i rtmp://localhost/src/test -vcodec copy -strict -2 -ar 44100 -ac 1 -f flv rtmp://<downstreaming A>/src/test -f flv rtmp://<downstreaming B>/src/test
it works when everything runs well, but if the downstream node is down, this command will exit and none of the downstream nodes could receive the live stream.
How could I force ffmpeg to ignore the connetion refused, or is there any better alternative to my implementation?

You cannot ignore connection refused since RTMP uses TCP which needs a connection.
If I understood correctly you're trying to transcode a RTMP source and send it to a number of servers.
You could duplicate your command to send to each downstream node
individually but you'll be doing the transcoding twice.
An alternative is to transcode and publish the transcoded stream using
ffserver on the same machine and then push to / pull on each downstream server

Related

how to get the delay of ffmpeg?

I'm using ffmpeg to do some work on a network like this:
RtmpServer1 -- FfmpegServer -- RtmpServer2
I put a 6mins.mp4 on RtmpServer1(10.10.1.1) and play it on RtmpServer2(10.10.2.2) by this instruction:
ffmpeg -i rtmp://10.10.1.1:1935/play/6mins.mp4 -vcodec copy -c:v libx264 -f flv rtmp://10.10.2.2:1935/live
I would like to know is there a way to test the length of the time ffmpeg use to decode, compress and encode?(the duration from ffmpeg server get the data to the ffmpeg server send it out)
I tried tcpdump to listen on the both two eth ports(one for get and one for send) of ffmpeg server. But I can't match RTMP packets by pairs("pairs" means the packets containing the same data, one "got" packet matches one "sent" packet). I'd also like to know if there's a way to match the RTMP packets by their content(data).
I tried to use tcpdump on both of the input and output eths and get when the rtmp streamings starts and ends. It is helpful in some way.

RTMP proxy to crop original video and send it to another RTMP server

I need to crop the video from an RTMP stream and send it to another RTMP server which always change. My understanding is that I should use nginx-proxy and ffmpeg, can anybody help me on how to set it up?
I suppose that i need to send the stream to an endpoint like /stream/:stream-key/:next-server-ip process the stream with ffmpeg and then send it to the :next-server-ip, what language should I use in the backend for this?
There are 2 strategies for processing such task:
"Pull"
You have some published rtmp stream and use ffmpeg to pull it, convert and send result to another server:
ffmpeg -i rtmp://source-server/stream -filter:v "crop=out_w:out_h:x:y" -vcodec h264 -acodec copy -f flv rtmp://next-server/stream
"Push"
RTMP stream is pushed to your server which processes it and sends result to another server. For such task you can use nginx-rtmp module for nginx and setup ffmpeg command using exec_push directive:
application src {
live on;
exec_push ffmpeg -i rtmp://localhost/src/$name -filter:v "crop=out_w:out_h:x:y" -vcodec h264 -acodec copy -f flv rtmp://next-server/stream 2>>/var/log/ffmpeg-$name.log;
}
When someone start to stream to rtmp://your-server/src/stream_name this ffmpeg command will be executed and the processing will begin
For additional information about video cropping and related ffmpeg parameters see https://video.stackexchange.com/a/4571

RTP livestream to browser using FFMPEG/nginx

I have a streaming transcoder which converts a high bandwidth fiber stream to a multicast RTP stream. I want to be able to show this stream to a client in a browser. There are 2 issues if I understand correctly:
The client most likely does not support multicast over his network
RTP cannot be played in a browser, so this needs to be converted to another format
What I have done so far (using FFMPEG):
Method 1: copy the stream to a .m3u8 without muxing, then hosting it with a Webserver (Nginx)
ffmpeg -protocol_whitelist file,udp,rtp -i ./stream.sdp -c:v copy -c:a copy -bufsize 50k -flags -global_header -hls_time 1 -f hls -hls_playlist_type event -hls_list_size 3 ./video/stream.m3u8
Method 2: enable HLS on Nginx and convert the stream to RTMP
ffmpeg -protocol_whitelist file,udp,rtp -i ./stream.sdp -vcodec libx264 -vprofile baseline -acodec aac -strict -2 -f flv rtmp://localhost/show/stream
Both of these methods result in a working livestream, but the delay remains around 5 seconds.
Is there any way to make the livestream faster? The multicast livestream has around a 1 second delay at max.
Both of these methods result in a working livestream, but the delay remains around 5 seconds.
Thats actually really good for HLS. Yes, there are ways to be faster within things Luke WebRTC and CTE. But nothing standard, You would have to develop the player and a chunk of infrastructure yourself.

Sometimes HLS chunks does not generate in /tmp/hls directory

I am working on an adaptive HLS solution using Nginx RTMP module as a streaming server and VideoJs as a client. I have completed the setup i.e. NGINX configurations and client sample in VideoJs.
NGINX Configurations:
nginx.txt
I am using this Ffmpeg command to generate stream:
ffmpeg -re -i /home/user/Downloads/test.mp4 -vcodec libx264 -vprofile baseline -g 30 -acodec aac -strict -2 -f flv rtmp://192.168.1.68/live
My problem is that sometimes the Nginx does not generate .ts and .m3u8 files in /tmp/hls directory when I issue the above ffmpeg command. I have also enabled the nginx-rtmp module logs but they are only giving me access information and I am not getting any logs in error logs.
Do let me know if more information is required. Any help will be appreciated.
Thanks,

FFmpeg -> JSMpeg Websocket Closes Repeatedly

I'm trying to create a fairly simple streaming server/site. Here's the current flow:
OBS streams to an RTMP URL
Nginx accepts the RTMP stream and uses exec-push to have FFmpeg pick up the stream and transcode it
FFmpeg transcodes the stream and outputs it to a JSMpeg application, which displays the stream on a webpage.
When I have my exec_push statement as follows, everything seems to work perfectly, except the browser says Possible garbage data. Skipping. on every frame it receives:
exec_push /usr/bin/ffmpeg -re -i rtmp://127.0.0.1:1935/$app/$name -f mpeg1video http://localhost:8080/supersecret;
This behavior is understandable, because JSMpeg must receive MPEG-TS data, not MPEG1 data. It sees the MPEG1 frames and thinks they're garbage.
So through some online research, I found this:
exec_push /usr/bin/ffmpeg -re -i rtmp://127.0.0.1:1935/$app/$name -c:v copy -c:a copy -f mpegts http://localhost:8080/supersecret;
Supposedly, this is supposed to transcode my RTMP stream into an MPEG-TS format, which should be compatible with JSMpeg.
However, with the second version of the command, my FFmpeg -> JSMpeg stream keeps connecting and disconnecting, connecting and disconnecting, and so on. This behavior is observed in terminal:
Stream Connected: ::1:40208
close
Stream Connected: ::1:40212
close
Stream Connected: ::1:40216
close
Stream Connected: ::1:40220
close
Stream Connected: ::1:40224
close
...
What would cause this? I am pretty certain the issue is in my exec_push command. OBS is perfectly content, which tells me that the stream is making it to the server, and if I do a push, I can do a test push to Ustream just fine, which tells me that Nginx is at least processing the stream with some reasonable degree of success.
Disclaimer: I have no idea what I'm talking about. Everything I know about FFmpeg and JSMpeg/Node is from snippets of code that I found online.
Answer credit goes to #Mulvya.
In the second exec_push command, the -c:v copy -c:a copy should not be there. By using that, there isn't any transcoding going on-- it's just a stream passthrough.
Removing the -c:v copy -c:a copy from the command and restarting Nginx yields a successful stream.

Resources