I am trying to make a quick and easy morph video using two frames (png images) with ffmpeg's minterpolate filter, in a bash script on Ubuntu Linux. The intent is to use the morphs as transitions between similar video in a different video editor later.
It will work on 3+ frames/images, but fails using just 2 frames/images.
First the code that works: 3 frames
This is using three 1080p png files:
test01_01.png
test01_02.png
test01_03.png
input01="test01_%02d.png"
ffmpeg -y -fflags +genpts -r 30 -i $input01 -vf "setpts=100*PTS,minterpolate=fps=24:scd=none" -pix_fmt yuv420p "test01.mp4"
This takes a bit of processing time, then creates a 414kb, roughly three second mp4 video of a morph starting with the first frame, morphing to the second, then morphing to the third.
The code that fails: 2 frames
This is using just two of the same 1080p png files:
test02_01.png
test02_02.png
input01="test02_%02d.png"
ffmpeg -y -fflags +genpts -r 30 -i $input01 -vf "setpts=100*PTS,minterpolate=fps=24:scd=none" -pix_fmt yuv420p "test02.mp4"
This almost immediately creates a 262 byte corrupt mp4 file. There are no differences except the number of frames.
Things I've tried:
I have tried this with the Ubuntu default repo version of ffmpeg, and the static 64bit 5.0 and git-20220108-amd64 versions, all with the same result.
I have also tried with a 2-frame mp4 file as the input, with the same result.
Thoughts?
Is this a bug in ffmpeg or am I doing something wrong?
I am also open to any suggestions for creating a morph like this using other Linux-compatible software.
Thank you for any insight!
It is not documented, but it looks like
minterpolate
filter requires at least 3 input frames.We may create a longer video using 5 input frames, and keep the relevant part.
For getting the same output as applying Minterpolate filter with only two input images, we may use the following solution:
Set
test02_01.png
as the first input andtest02_02.png
as the second input.-stream_loop
(
test02_01.png
is repeated twice andtest02_02.png
is repeated 3 times).-r 30
andsetpts=100*PTS
).The input arguments are as follows:
-r 0.3 -stream_loop 1 -i test02_01.png -r 0.3 -stream_loop 2 -i test02_02.png
.concat
filter.minterpolate
filer to the concatenated output.The output of the above stage is a video with few redundant seconds at the beginning, and few redundant seconds at the end.
trim
filter for keeping the relevant part.Add
setpts=PTS-STARTPTS
at the end (as recommended when using trim filter).Suggested command:
Sample output (as animate GIF):

test02_01.png
:test02_02.png
: