[FFmpeg-user] smarter scaling filter

Jim Worrall coniophora at gmail.com
Wed Dec 7 23:24:08 CET 2011

I've been trying to find or write a script/filtergraph that will take a
target frame size and automatically scale down the input video (maintaining
aspect ratio) if needed to fit the frame, and leave it the same if it is
already the size or smaller than the frame.  I'm in a bit over my head and
hoping for some pointers.

I'm starting with a very clever set of calculations that Francesco Turco
posted here 12 June 2011. One side of each plus sign will always evaluate
to 0 (escapes removed for clarity; his target frame size was 720x576):
-vf scale = '
gte(iw/ih,720/576)*720 + lt(iw/ih,720/576)*((576*iw)/ih) :
lte(iw/ih,720/576)*576 + gt(iw/ih,720/576)*((720*ih)/iw) '

He thought it was too long, but still seems a great approach.  The problem
for me is it will upscale too, which seems undesirable if the device
doesn't require an exact size.  So I'm trying to add some logic to keep the
input scale if both iw and ih are the size of or smaller than the frame.
While I'm at it, I'm hoping to use some variables from the script for the
frame size.

The bash script asks for the target device (just iPhone 3 or iPhone4 now)
and sets device-specific values for the maximum frame width ($FW) and
height ($FH) and the corresponding aspect ratio ($FA).  The filter also
seems to need some stored variables within ffmpeg, but I've only found one
example of their real use on the web and couldn't make much sense out of
it.  I can't figure how st(var,expr) is supposed to be incorporated into
the filter, since it can't seem to go before it.  And there's a
while(cond,expr) I don't know where to put either.

Here's an idea what I'm trying to do, and I think it is a long way from
working.  The st(0,expr) that I put in the beginning (not knowing where it
goes) stores 0 if both dimensions fit in the target frame.  I'm not sure if
I can use a script variable inside a filter, hope so.  Anyway, the while
statement is supposed to convert var 0 to 1 if it is not 0.  The rest is
just an add-on to Francesco's filter that should specify the input
dimensions if var 0 is 0.
-vf = "st(0,gt(iw,$FW)+gt(ih,$FH)) ;
  while(ld(0),st(0,1) ;
  scale= ld(0) * ( gte(a,$FA)*$FW + lt(a,$FA)*(($FH*iw)/ih) ) +
eq(0,ld(0))*iw :
             ld(0) * ( lte(a,$FA)*$FH + gt(a,$FA)*(($FW*ih)/iw) ) +
eq(0,ld(0))*ih "

In case it matters, I'm a user/hobbyist.  Any tips will be appreciated.

More information about the ffmpeg-user mailing list