Use of “geq” as “zoompan” alternative

Watch on youtube.com
doc

https://ffmpeg.org/ffmpeg-filters.html#geq, https://ffmpeg.org/ffmpeg-filters.html#zoompan, https://ffmpeg.org/ffmpeg-filters.html#scale-1, https://ffmpeg.org/ffmpeg-filters.html#zscale-1, https://ffmpeg.org/ffmpeg-filters.html#crop

see also

(ffmpeg-utils)3. Expression Evaluation

ffmpeg’s “zoompan” can not “zoom out”

You do not want to believe, but ffmpeg’s “zoompan” can not “zoom out” contrary to its name:

#! /bin/sh
pref="`basename $0 .sh`"
dur=5
#
zoomlevel=0.5  # "zoompan" silently shuts out this as out of range.
#
ffmpeg -y -i "adult-blur-brick-wall-373918__16_9.jpg" -filter_complex "
[0:v]
scale=-1:1080,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,
loop=loop=-1:size=2,
zoompan='s=1920x1080:d=${dur}:z=${zoomlevel}',
setsar=1
[v]
" -map '[v]' -an -t ${dur} ${pref}-out.mp4

Therefore, you might think you can use “scale” (or “zscale”). That approach works if you do not intend to animate. However, since both “scale” and “zscale” can not use time stamps in expressions, they can not be used if you want to animate them.

In order to escape from this situation, you can use “geq”, although it is rather cumbersome and very heavy and slow.

Use of “geq” as “zoompan” alternative

00:01:20
#! /bin/sh
pref="`basename $0 .sh`"
#
dur=20
rat="(0.5+1.5*T/${dur})"

#
ffmpeg -y -i "adult-blur-brick-wall-373918__16_9.jpg" -filter_complex "
[0:v]
scale=-1:1080,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,
loop=loop=-1:size=2,
geq='p(X*${rat},Y*${rat})',
setsar=1
[v]
" -map '[v]' -an -t ${dur} ${pref}-out.mp4

In this example, the edge at zoom out probably is not what you want. You probably think that it is okay to cut out with “crop”, but it does not work. Strangely, “crop” rejects timestamp for “w”, and “h”, although you can use it for “x”, and “y”. Therefore, in order to do it seriously, you have only to “‘if’-festival” with “geq” expression.

00:02:25
#! /bin/sh
pref="`basename $0 .sh`"
#
dur=20
rat="(0.5+1.5*T/${dur})"

#
ffmpeg -y -i "adult-blur-brick-wall-373918__16_9.jpg" -filter_complex "
[0:v]
scale=-1:1080,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,
loop=loop=-1:size=2,
geq='
r=if(gt(X*${rat},W)+gt(Y*${rat},H),0,r(X*${rat},Y*${rat})):
g=if(gt(X*${rat},W)+gt(Y*${rat},H),0,g(X*${rat},Y*${rat})):
b=if(gt(X*${rat},W)+gt(Y*${rat},H),0,b(X*${rat},Y*${rat}))',
setsar=1
[v]
" -map '[v]' -an -t ${dur} ${pref}-out.mp4
00:02:45
#! /bin/sh
pref="`basename $0 .sh`"
#
dur=20
rat="(2.0-1.5*T/${dur})"

#
ffmpeg -y -i "adult-blur-brick-wall-373918__16_9.jpg" -filter_complex "
[0:v]
scale=-1:1080,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,
loop=loop=-1:size=2,
geq='
r=if(gt(X*${rat},W)+gt(Y*${rat},H),0,r(X*${rat},Y*${rat})):
g=if(gt(X*${rat},W)+gt(Y*${rat},H),0,g(X*${rat},Y*${rat})):
b=if(gt(X*${rat},W)+gt(Y*${rat},H),0,b(X*${rat},Y*${rat}))',
setsar=1
[v]
" -map '[v]' -an -t ${dur} ${pref}-out.mp4

However, if you do not need to keep the original image, this problem will be solved if you give a border. There are many ways to give a border, perhaps “drawbox” is probably the easiest.

00:03:20
#! /bin/sh
pref="`basename $0 .sh`"
#
dur=20
rat="(2.0-1.5*T/${dur})"

#
ffmpeg -y -i "adult-blur-brick-wall-373918__16_9.jpg" -filter_complex "
[0:v]
scale=-1:1080,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,
loop=loop=-1:size=2,
drawbox=color=black:t=5,
geq='p(X*${rat},Y*${rat})',
setsar=1
[v]
" -map '[v]' -an -t ${dur} ${pref}-out.mp4

As you can do with “zoompan”, of course you can zoom in/out with the center specified. But it’s hard because you have to think and calculate all by yourself.

00:03:55
#! /bin/sh
pref="`basename $0 .sh`"
#
dur=20
rat="(2.0-1.5*T/${dur})"

#
ffmpeg -y -i "adult-beautiful-beauty-206593.jpg" -filter_complex "
[0:v]
scale=-1:1080,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,
loop=loop=-1:size=2,format=yuv444p,
geq='p(X*${rat}+0.5*(1-${rat})*W,Y*${rat}+0.5*(1-${rat})*H)',
setsar=1
[v]
" -map '[v]' -an -t ${dur} ${pref}-out.mp4
00:04:15
#! /bin/sh
pref="`basename $0 .sh`"
#
dur=20
rat="(2.0-1.5*T/${dur})"

#
ffmpeg -y -i "adult-beautiful-beauty-206593.jpg" -filter_complex "
[0:v]
scale=-1:1080,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,
loop=loop=-1:size=2,format=yuv444p,
drawbox=color=black:t=5,
geq='p(X*${rat}+0.5*(1-${rat})*W,Y*${rat}+0.5*(1-${rat})*H)',
setsar=1
[v]
" -map '[v]' -an -t ${dur} ${pref}-out.mp4

You should now be able to do a various zooming animation. For example …

00:04:40
#! /bin/sh
pref="`basename $0 .sh`"
#
dur=5
rat="(2.0-1.5*mod(T,1)^2)"

#
ffmpeg -y -i "adult-beautiful-beauty-206593.jpg" -filter_complex "
[0:v]
scale=-1:1080,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,
loop=loop=-1:size=2,format=yuv444p,
drawbox=color=black:t=5,
geq='p(X*${rat}+0.5*(1-${rat})*W,Y*${rat}+0.5*(1-${rat})*H)',
setsar=1
[v]
" -map '[v]' -an -t ${dur} ${pref}-out.mp4
00:04:45
#! /bin/sh
pref="`basename $0 .sh`"
#
dur=20
rat="(2.0-1.5*T/${dur})"

#
ffmpeg -y -i "adult-beautiful-beauty-206593.jpg" -filter_complex "
[0:v]
scale=-1:1080,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,
loop=loop=-1:size=2,format=yuv444p,
drawbox=color=black:t=5,
geq='p(X*${rat}+(0.5+cos(T)/4)*(1-${rat})*W,Y*${rat}+(0.5+sin(T)/4)*(1-${rat})*H)',
setsar=1
[v]
" -map '[v]' -an -t ${dur} ${pref}-out.mp4
00:05:05
#! /bin/sh
pref="`basename $0 .sh`"
#
dur=20
rat="(2.0-1.5*T/${dur})"

#
ffmpeg -y -i "adult-beautiful-beauty-206593.jpg" -filter_complex "
[0:v]
scale=-1:1080,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,
loop=loop=-1:size=2,format=yuv444p,
drawbox=color=black:t=5,
geq='
p(
(tan(T)*(X-W/2)+W/2)*${rat}+0.5*(1-${rat})*W,
Y*${rat}+0.5*(1-${rat})*H
)',
setsar=1
[v]
" -map '[v]' -an -t ${dur} ${pref}-out.mp4
00:05:25
#! /bin/sh
pref="`basename $0 .sh`"
#
dur=20
rat="(2.0-1.5*T/${dur})"

#
ffmpeg -y -i "adult-beautiful-beauty-206593.jpg" -filter_complex "
[0:v]
scale=-1:1080,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,
loop=loop=-1:size=2,format=yuv444p,
drawbox=color=black:t=5,
geq='
p(
(cos(T)*(X-W/2)+sin(T)*(Y-H/2)+W/2)*${rat}+0.5*(1-${rat})*W,
(sin(T)*(X-W/2)-cos(T)*(Y-H/2)+H/2)*${rat}+0.5*(1-${rat})*H
)',
setsar=1
[v]
" -map '[v]' -an -t ${dur} ${pref}-out.mp4

Finally. Please note that any of the examples shown requires extensive processing time. Although it is possible to obtain a far more “interesting” effect than “zoompan” by the method shown indeed, if there is anything within the scope of “zoompan”, you should use that, because the processing time is 100 times or 1000 times different.

Also note that this is the simplest scaling in the world that does not “smooth zooming”. As the zoom factor increases, the roughness will become conspicuous.