Reputation: 335
I've been playing around with ffmpeg over the past months and can't get rid of an issue I'm facing when adding a GIF file as an overlay.
Basically what I'm trying to achieve is to add a transparent GIF animation as an overlay on top of a MP4 video.
Please find below an example command that I'm using:
ffmpeg \
-i 0689a8a9-43b5-45d2-b0e8-acbea6905ce1.mp4 \
-ignore_loop 0 \
-i 02a6e696-969b-4a90-9444-e4b0b4d6f6da.gif \
-t 10.000000 \
-filter_complex "[0:v][1:v]overlay=enable='between(t, 1, 3)'[overlay]" \
-map '[overlay]' \
-pix_fmt yuv420p \
output.mp4
For a better understanding, please note that:
-ignore_loop 0
allows me to loop the animation as long as the overlay is enabled-t
makes my video last 10soverlay=enable='between(t, 1.0, 3.0)'
sets the interval during which it's visibleHowever, when I run this command, a very few milliseconds before the GIF disapears (at 3s), it starts blinking. If I run take a look at it frame by frame, it actually disappears from the video, then comes back, and eventually goes away as expected.
Please find an example with a black background and a random GIF from giphy at this link. The assets can be found here.
I'm probably missing something here. Do you have any hints ?
I'm running ffmpeg
in 4.3.1
.
Thank you in advance
Upvotes: 6
Views: 880
Reputation: 301
In the official FFmpeg community there is a ticket for this, which hasn't been fixed though: https://trac.ffmpeg.org/ticket/4803
The ticket mentions that a GIF is being shown before the specified enable time. On my tests, given a 60
fps video, a 10.42
fps GIF (that needs to be shown from 5
to 10
s) blinks once 5 frames before the desired time (at 4.933
s) and becomes visible again right at 5
s. Should be something connected to the GIF's fps which doesn't match the video's fps.
Anyways, I've found the most elegant workaround, which solves the problem in a single pass and doesn't require converting GIFs to temporary MP4s (because in some cases that could be undesired). So, given the video fps, to overlay a GIF at a certain position (x=10
, y=20
) from 5
to 10
s without blinking we should use the following:
ffmpeg -y -i "video.mp4" -ignore_loop 0 -i "giphy.gif" \
-filter_complex "[1:v]fps=60[gif];[0:v][gif]overlay=x=10:y=20:enable='between(t,5,10)'" \
-c:a copy -shortest "overlay.mp4"
We can go further and come up with a command line which doesn't require a prior knowledge of the video fps (but you should know the output video fps instead, which is 60
fps in this case):
ffmpeg -y -i "video.mp4" -ignore_loop 0 -i "giphy.gif" \
-filter_complex "[0:v]fps=60[video];[1:v]fps=60[gif];[video][gif]overlay=x=10:y=20:enable='between(t,5,10)'" \
-acodec copy -shortest "overlay.mp4"
Upvotes: 0
Reputation: 5010
I can replicate this with an arbitrary gif. I suspect a bug in the overlay filter. Feel free to present this to https://trac.ffmpeg.org.
This happens as soon as the temporal filtering is set (filter is listed as having timeline support) and furthermore changes depending on the time boundaries. The latter should never be the case.
MWE
ffmpeg \
-t 10 -s qcif -f rawvideo -pix_fmt rgb24 -r 25 -i /dev/zero \
-ignore_loop 0 -i 'https://media.tenor.com/images/c50ca435dffdb837914e7cb32c1e7edf/tenor.gif' \
-filter_complex "overlay=enable='between(t,3,7)'" \
-f flv - | ffplay -
You could try, as a workaround, converting the gif to an mp4 (ffmpeg -re -i <gif> [...]
) and set the white areas to transparent.
Upvotes: 2