1

My goal is to transform an image .jpg into a .mp4 video and then add a .gif overlay on the video created. The problem is the GIF overlay on the video created is not playing/looping.

Here is the command for the image -> video :

"-framerate 1/10 -i image.jpg -vf scale=720:1280 -t 10 -pix_fmt yuv420p -c:v libx264 -movflags faststart output.mp4"

This create successfully a video of 10seconds from my image.

Here is the command for applying the gif as overlay :

-i video.mp4 -ignore_loop 0 -i animated.gif -filter_complex '[1:v]scale=321.0:-1[ovrl0];[0:v][ovrl0]overlay=160.5:487.28:shortest=1' -codec:a copy -codec:v libx264 -preset ultrafast output.mp4

The overlay is correctly applied but it's not playing or looping at all.

I don't know what I am doing wrong because the last command (overlay) is working perfectly when it's triggered from a classic video file (like from recorded camera or something) -> the gif is looping as expected.

So I'm assuming the real issue come from the video I created from my image but result I've got seems to be good so can't find what's wrong with the image or video created.

Can someone could help me please to fix it and understand this case ?

nicover
  • 2,213
  • 10
  • 24

1 Answers1

1

Your (image->video) has only one frame over 10 seconds. I believe by default the output stream configuration is drawn from the first input so its framerate is set to 0.1 fps. (not 100% certain of who actually sets what but this should be the expected behavior). So, the output video also has only one frame, and consequently, it won't show any of the gif animation. You need to use higher framerate.

A simple solution with video.mp4 assuming the gif framerate is 25 fps:

-i video.mp4 -ignore_loop 0 -i animated.gif \
-filter_complex '[1:v]scale=321.0:-1[ovrl0];\
                 [0:v]fps=25[main0];\
                 [ovrl0]overlay=160.5:487.28:shortest=1' \
-codec:a copy -codec:v libx264 -preset ultrafast output.mp4

Change fps=25 to the actual gif framerate if you want the lowest framerate possible.

Alternately, you can do the whole thing in one command:

-ignore_loop 0 -i animated.gif \
-loop 1 -i image.jpg \
-filter_complex '[0:v]scale=321.0:-1[ovrl0];\
                 [1:v]scale=720:1280[main0];\
                 [main0][ovrl0]overlay=160.5:487.28' \
-t 10 -pix_fmt yuv420p -c:v libx264 -movflags faststart output.mp4

I think this should make the framerate of the output to match that of the gif. If not, insert -r xx output option like above.

I see in your second command audio stream is set to copy. If you added audio between your 2 commands, you can add it to this unified command as well.

kesh
  • 4,515
  • 2
  • 12
  • 20
  • Thanks a lot for this. I had already tried to add -r 25 to boost the framerate and it was also not working with 2 separated command. But do the whole thing in only one is great you rock – nicover Oct 15 '22 at 19:50
  • my bad, the framerate needed to be changed before overlay. Fixed the first solution, but glad the second one worked. – kesh Oct 15 '22 at 23:20
  • do you know how to build image -> video with a correct framerate to make it work with separated command ? My app architecture is complex and separated method would be easier to handle – nicover Oct 16 '22 at 12:08
  • have you tried the updated first command in the post with the `fps` filter? – kesh Oct 16 '22 at 14:06
  • ```-r 25 -i image.jpg -vf scale=720:1280 -t 10 -pix_fmt yuv420p -c:v libx264 -movflags faststart output.mp4``` will return a 0 seconds video with -r 25. can't find how to build this correctly – nicover Oct 16 '22 at 15:20
  • Solved ! I was missing the ```loop=-1:1```parameter with the scale group from this answer https://stackoverflow.com/a/73073276/12566751 thanks for your help – nicover Oct 16 '22 at 15:54