How to display static image if the input stream ends using ffmpeg?
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 &amp; 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 ;)