10

I am receiving a stream over the network with the following ffmpeg command:

ffmpeg -i rtmp://server:port/input.stream -f flv rtmp://server2:port/output.stream

When the input stream stalls, I want to display a still image. When the input stream continues, I want to continue showing the input stream. I have tried this:

ffmpeg -loop 1 -i Error.png -i rtmp://server:port/input.stream -filter_complex "[0:v][1:v] overlay=0:0" -f flv rtmp://server2:port/output.stream

That works, except when the input video stream stalls, it keeps showing the last frame received from the stream. I want it to show the .png file (i.e. the video input becomes transparent).

3
  • What happens when you change your filter from "[0:v][1:v] overlay=0:0" to "[0:v][1:v] overlay=0:0:repeatlast=0" ? repeatlast is an option for overlay. ffmpeg.org/ffmpeg-all.html#overlay-1
    – Jon Freed
    Dec 31, 2016 at 23:05
  • A combination of mkfifo and rtmp could be a kind of solution
    – miald
    Nov 12, 2019 at 20:47
  • You could probably do it with liquidsoap.info (I only just found out about it, but it looks to be pretty advanced)
    – Mint
    Nov 27, 2022 at 0:27

1 Answer 1

10

TL;DR : Nothing simple. Both solutions use a relay, and it's not suitable for real production.


Actually, you only have two possibilities, and both are ugly.

There is absolutely no open-source software capable to handle a non-permanent stream (GStreamer+forks, FFmpeg, VLC, MPlayer). Every single one of them have the same behavior: last frame still visible, and everything is stopped until data come again.

Option 1 — Tunneling + cache

You need two FFmpeg running, and a script using FFplay.

The first FFmpeg pull the RTMP stream. The output is a local port and the protocol need to be based on MPEG-TS. It's better if the input is tuned for the lowest latency.

Also, you need to optimize how FFmpeg start: no analysis of the stream (set the fps in the command line), early start, etc.

The second FFmpeg pull the local MPEG-TS stream, and transcode the stream to a new RTMP. You need to reencode it with x264, because the video packets will broke at the first switch (so you need a better quality for your original stream). You need to increase the input latency : default is 3s for FFmpeg, but you need something like 8s. It can be lowered, but only after you really understand what is going on and where is your margin.

The magic is with FFplay.
You have a script running, where FFmpeg read the original RTMP stream. When the stream as no more data, FFplay send an error and stop. Then, the script kill the first FFmpeg instance, and launch a new one. That FFmpeg is the “offline” stream. Whatever input you want, you need to encode it in x264 MPEG-TS, to the local port. And with the same fps/size than your normal stream.

During this time, the second FFmpeg is still playing his input cache. So the 4 or 5 seconds for the “offline” FFmpeg to launch is not a problem.

In the actual loop of the script, you need a new FFplay. When your stream is back, it kills the offline FFmpeg, and relaunch the normal one.

The input cache do the job, and the reencoding clean the broken video packets.

It works, but it's not a proper solution, like an overlay on FFmpeg, and FFmpeg not stopping when an input is unresponsive/missing/empty.

Option 2 - OpenBroadcaster Software

If I don't have a full script to post here, it's because I found a new solution : Use OBS on the server, capture the original stream, put your offline image behind, and send the stream to your distribution server.

But, there is a catch, OBS need OpenGL 3.1 (2?), and a desktop. So you need a real PC & GPU, or virtualize the desktop with ESXI (I don't know if VirtualBox make a virtual GPU compatible with OpenGL 3.1).

The logic is the same, but more friendly.

The only Good Solution

FFmpeg is capable to handle everything on a single instance. If you use overlays, you can have the offline layer and the original stream on the top of it. FFmpeg even know how to restart a stream when it's republished.

But, actually, FFmpeg stop everything when one input is offline/missing/empty.

An option to change the behavior of FFmpeg on an input is the only thing missing.

I tried the dev mailing list, no response. Same thing for my predecessors. The dev “community” of FFmpeg is not friendly, based on old tools (you better not criticize the use of a mailing list!), and conservative.

If someone has a better solution, a magical program to do a simple offline switcher, it's really needed ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.