ffmpeg overlay transparent animated gif over video and keep gif background transparency - ffmpeg

I'm trying to overlap an animated gif over a video with no success.
My goals are the next:
gif animation have to loop until video ends.
gif is scaled so it covers the whole video.
gif preserves transparency.
The most I have achieved regarding this is that the gif covers the whole video with the scale filter and that it loops until video ends (but this not in the best way, I guess).
Regarding loop I know I can use -ignore_loop 0 gif filter parameter with shortest=1 in overlay but this way it is not working so I ended up with -frames:v 900 (my video is 30fps and 30sec long so 900 is the number of frames).
My most important issue is I'm not able to keep gif transparency and everything I've tried resulted in no success.
This is my ffmpeg command with arguments, so I hope anybody can help (I'm using ffmpeg 4.1).
ffmpeg -y
-i videoin.mp4
-i anim01.gif
-filter_complex [1:v]scale=1080:1920[ovrl] [0:v][ovrl]overlay=main_w-overlay_w:main_h-overlay_h
-frames:v 900
-codec:a copy
-codec:v libx264
-preset ultrafast
video.mp4

Ok, I'll answer my own question. The first part, not being able to achieve gif transparency, such a silly issue!! The gif I was using was not transparent and I didn't realized!! OMG, I thought, so this is the first thing to check whenever you have a transparency issue.
The second, looping the gif until the video ends, I wasn't able to do it with -ignore_loop 0 along with shortest=1 but what I did is -ignore_loop 0 and -frames:v 900 and that worked like a charm.
What was not working was not the -ignore_loop 0 but the shortest=1 and so ffmpeg was never ending encoding but if you set it to finish at a certain number of frames that resolves the problem.
900 comes from 30fps x 30 sec video.
In the end, my complete ffmpeg command line parameters ended up as follows:
ffmpeg -y -i xxx.mp4 -ignore_loop 0 -i xxx.gif -filter_complex "[1:v]scale=1080:1920[ovrl];[0:v][ovrl]overlay=0:0" -frames:v 900 -codec:a copy -codec:v libx264 -max_muxing_queue_size 2048 video.mp4

Hello Guys if anyone want to add gif to video use this command. Deffienetly you will get the right answer
String strFilter = "[1:v]scale=h=-1:w=100[overlay_scaled],"
+ "[0:v][overlay_scaled]overlay=shortest=1:x=W*0:y=H*0";
String[] complexCommand = new String[] {
"-i",
yourRealPath,
"-itsoffset",
String.valueOf(0),
"-ignore_loop", "0", "-i",
fullPath,
"-filter_complex",
strFilter,
"-frames:v", "900", "-preset",
"ultrafast",
"-g",
"120",
dest.getAbsolutePath()
};

Related

FFMPEG Blending for VP9 format videos

I get a darker background, almost like a placeholder for the asset that is to be blended, whereas the background should be transparent, and should show the same colour as the rest of the background.
I have two webm vp9 files that I am trying to blend using FFMPEG blending functionality.
One of the videos is a zoom animation that starts from 1 pixel in size and then increases in size to 50 x 50 pixels.
The other is a solid red background video 640 px x 360 px
At frame 1 the result looks like this:-
At about 0.5 seconds through, the result looks like this:-
At the end of the sequence, the zoom animation webm fills that darker square you see (50 x 50 pixels).
The code to do the blending of the two webm files looks like this:-
filter_complex.extend([
"[0:v][1:v]overlay=0:0:enable='between(t,0,2)'[out1];",
'[out1]split[out1_1][out1_2];',
'[out1_1]crop=50:50:231:251:exact=1,setsar=1[cropped1];',
'[cropped1][2:v]blend=overlay[blended1];',
"[out1_2][blended1]overlay=231:251:enable='between(t,0,2)'[out2]"
])
This overlays a red background onto a white background, making the red background the new background colour.
It then splits the red background into two, so that there is one output for cropping and another output for overlaying.
It then crops the location and size of the layer to be blended out of the red background. We do this because blending works only on an asset of the same size.
It then performs the blend of the zoom animation onto the cropped background.
It then overlays the blended over the red background
Unfortunately I'm unable to attach videos in stackoverflow, otherwise I would have included them.
The full command looks like this:-
ffmpeg -i v1_background.webm -itsoffset 0 -c:v libvpx-vp9 -i v2_red.webm -itsoffset 0 -c:v libvpx-vp9 -i v3_zoom.webm -filter_complex "[0:v][1:v]overlay=0:0[out1];[out1]split[out1_1][out1_2];[out1_1]crop=50:50:231:251:exact=1,setsar=1[cropped1];[cropped1][2:v]blend=overlay[blended1];[out1_2][blended1]overlay=231:251" output_video_with_blended_overlaid_asset.mp4
I have checked the input vp9 webm zoom video file by extracting the first frame of the video
ffmpeg -vcodec libvpx-vp9 -i zoom.webm first_frame.png
and inspecting the colours in all the channels in GIMP. The colours (apart from the opaque pixel in the middle) are all zero, including the alpha channel.
Note that I tried adding in all_mode, so that the blend command is blend=all_mode=overlay, however this still shows the darker placeholder under the animation asset. In other words, this command
ffmpeg -i v1_background.webm -itsoffset 0 -c:v libvpx-vp9 -i v2_red.webm -itsoffset 0 -c:v libvpx-vp9 -i v3_zoom.webm -filter_complex "[0:v][1:v]overlay=0:0[out1];[out1]split[out1_1][out1_2];[out1_1]crop=50:50:231:251:exact=1,setsar=1[cropped1];[cropped1][2:v]blend=all_mode=overlay[blended1];[out1_2][blended1]overlay=231:251" output_video_with_blended_all_mode_overlay_asset.mp4
also doesn't work
and trying to convert the formats to rgba first doesn't help either, command below is simplified a bit
ffmpeg -c:v libvpx-vp9 -i v2_red.webm -c:v libvpx-vp9 -i v3_zoom.webm -filter_complex "[0:v]format=pix_fmts=rgba[out1];[1:v]format=pix_fmts=rgba[out2];[out1]split[out1_1][out1_2];[out1_1]crop=50:50:0:0:exact=1,setsar=1[cropped1];[cropped1][out2]blend=all_mode=dodge[blended1];[out1_2][blended1]overlay=50:50" output_video_with_blended_all_mode_dodge_rgba_and_alpha_premultiplied_overlay.mp4
adding in an alpha premultiply didn't help either
ffmpeg -c:v libvpx-vp9 -i v2_red.webm -c:v libvpx-vp9 -i v3_zoom.webm -filter_complex "[0:v]format=pix_fmts=rgba[out1];[1:v]setsar=1,format=pix_fmts=rgba,geq=r='r(X,Y)*alpha(X,Y)/255':g='g(X,Y)*alpha(X,Y)/255':b='b(X,Y)*alpha(X,Y)/255'[out2];[out1]split[out1_1][out1_2];[out1_1]crop=50:50:0:0:exact=1,setsar=1[cropped1];[cropped1][out2]blend=all_mode=dodge[blended1];[out1_2][blended1]overlay=50:50" output_video_with_blended_all_mode_dodge_rgba_and_alpha_premultiplied_overlay.mp4
Wondering if there is a workaround I could use so that the background stays transparent?
I was looking for maybe a way of changing the input pixel format in the filter_complex stream to see if that works, but couldn't see anything about this.

ffmpeg transparent background with colorkey shows background bleeding

I am creating a video with transparent background video with the following command. After creation I want to overlay this video on another video
ffmpeg -f lavfi -i color=red:s=1920x1080,colorkey=red,format=rgba -loop 1 -t 0.08 -i "CreditWhite.png" -filter_complex "[1:v]scale=1920:-2,setpts=if(eq(N\,0)\,0\,1+1/0.02/TB),fps=60[fg]; [0:v][fg]overlay=y=-'t*h*0.02':eof_action=endall[v]" -map "[v]" -pix_fmt yuva444p10le -vcodec prores_ks credits.mov
Creating the video works fine but when I overlay this on another video (using openshot) I get a lot of color bleeding of the background colour around the edges. Any suggestions to improve the ffmpeg prompt to stop this from happening? I tried very slightly increasing the opacity (0.06) as mentioned in another thread without success.
Video uploaded to youtube for reference
UPDATE
Using different colours had the same effect

I can't overlay and center a video on top of an image with ffmpeg. The output is 0 seconds long

I have an mp4 that I want to overlay on top of a jpeg. The command I'm using is:
Ffmpeg -y -i background.jpg -i video.mp4 -filter_complex "overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" -codec:a copy output.mp4
But for some reason, the output is 0 second long but the thumbnail does show the first frame of the video centred on the image properly.
I have tried using -t 4 to set the output's length to 4 seconds but that does not work.
I am doing this on windows.
You need to loop the image. Since it loops indefinitely you then must use the shortest option in overlay so it ends when video.mp4 ends.
ffmpeg -loop 1 -i background.jpg -i video.mp4 -filter_complex \
"overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1" \
-codec:a copy -movflags +faststart output.mp4
See overlay documentation for more info.
Well you should loop the image until the video duration. So to do the you need to add -loop 1 before the input image. Then the image will have a infinite duration. So to control it specify -shortest before the output file which will trim all the streams to the shortest duration among them. Else you can use -t to trim the image duration to the video length. This will do what you want.
Hope this helps!

gifs not loops in ffmpeg movie filter

I have a gif that loops infinite(loop.gif). I want to overlay this gif to top left corner of video.mpg. So I am using this code to make this:
ffmpeg -i video.mpg -vf "movie=loop.gif [logo]; [in][logo] overlay=10:10 [out]" -vcodec mpeg2video out.mpg
The problem is; gif loops only 1 time and last frame of the gif showing until end of video.mpg.
How can I loop this gif continuously?
Use the -ignore_loop option from the GIF demuxer:
ffmpeg -i video.mp4 -ignore_loop 0 -i loop.gif -filter_complex "[0:v][1:v]overlay=10:10:shortest=1" output.mp4
See the GIF demuxer documentation or run ffmpeg -h demuxer=gif for more options.
No need to use the movie source filter.
This example uses the shortest option in the overlay filter. Otherwise the encoding will run indefinitely due to the looping GIF.

Show watermark at the beginning of the video

Need to add watermark for first 3 seconds the video using ffmpeg. Here's what I got right now:
ffmpeg -y -i '255871.mov' -qscale:v 0 -qscale:a 0 -vf '[in] transpose=1 [out];movie=watermark.png , select=lte(t\,3) [bg]; [out][bg] overlay=x=20:y=main_h-60 [out]' output.mp4
It rotates video to the right and adds watermark at the bottom of the video for first 3 seconds. The problem is watermark is visible during the whole video.
Thought that select doesn't work at all. Tried following command
ffmpeg -y -i '255871.mov' -qscale:v 0 -qscale:a 0 -vf '[in] transpose=1 [out];movie=watermark.png , select=0 [bg]; [out][bg] overlay=x=20:y=main_h-60 [out]' output.mp4
Watermark is not visible. This is correct and proves that select filter works as expected. As I understand this is how ffmpeg works: it leaves last frame of the shortest video visible.
How can I force ffmpeg to discard show watermark after N seconds?
Have to answer it myself. ffmpeg mailing list helped me to solve the issue.
The main idea is to convert existing watermark into video using Apple Animation codec (it supports transparency) and fade out last frame of created video using fade filter.
Example:
ffmpeg -loop 1 -i watermark.png -t 3 -c qtrle -vf 'fade=out:73:1:alpha=1' watermark.mov
ffmpeg -y -i '255871.mov' -qscale:v 0 -qscale:a 0 -vf '[in] transpose=1 [out];movie=watermark.mov [bg]; [out][bg] overlay=x=20:y=main_h-60 [out]' output.mp4
Fade out is required because ffmpeg uses last frame of overlaid video for the rest of the video. This filter makes last frame fully transparent via alpha=1 parameter. In fact it should be fade=out:74:1:alpha=1, but it didn't work for me, don't know why

Resources