Skip to main content
added 763 characters in body
Source Link
slhck
  • 230.2k
  • 71
  • 621
  • 603

FirstWith newer ffmpeg versions, you can use the scale filter's force_original_aspect_ratio option. For example, to fit a video into 1280×720, without upscaling (see this post for more info):

ffmpeg -i input.mp4 -filter:v "scale='min(1280,iw)':min'(720,ih)':force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output.mp4

Here, the scale filter scales to 1280×720 if the input video is larger than that. If it is smaller, it will not be upscaled. The pad filter is necessary to bring the output video to 1280×720, in case its aspect ratio or size differs from the target size.


With older ffmpeg versions, there is a somewhat hacky workaround. First, define the width, height and aspect ratio of your output. This will save us some typing.

width=640; height=360
aspect=$( bc <<< "scale=3; $width / $height") # <= floating point division

Now, let's apply the super complex filter command that Jim Worrall wrote:

ffmpeg -i input.mp4 -vf "scale = min(1\,gt(iw\,$width)+gt(ih\,$height)) * (gte(a\,$aspect)*$width + \
lt(a\,$aspect)*(($height*iw)/ih)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*iw : \
min(1\,gt(iw\,$width)+gt(ih\,$height)) * (lte(a\,$aspect)*$height + \
gt(a\,$aspect)*(($width*ih)/iw)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*ih" \
output.mp4

I won't really go into explaining what this all does, but basically you can feed it any video, and it will only downscale, not upscale. If you're up for it you can dissect the filter into its individual expressions. It might be possible to shorten this, but it works like that as well.

First, define the width, height and aspect ratio of your output. This will save us some typing.

width=640; height=360
aspect=$( bc <<< "scale=3; $width / $height") # <= floating point division

Now, let's apply the super complex filter command that Jim Worrall wrote:

ffmpeg -i input.mp4 -vf "scale = min(1\,gt(iw\,$width)+gt(ih\,$height)) * (gte(a\,$aspect)*$width + \
lt(a\,$aspect)*(($height*iw)/ih)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*iw : \
min(1\,gt(iw\,$width)+gt(ih\,$height)) * (lte(a\,$aspect)*$height + \
gt(a\,$aspect)*(($width*ih)/iw)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*ih" \
output.mp4

I won't really go into explaining what this all does, but basically you can feed it any video, and it will only downscale, not upscale. If you're up for it you can dissect the filter into its individual expressions. It might be possible to shorten this, but it works like that as well.

With newer ffmpeg versions, you can use the scale filter's force_original_aspect_ratio option. For example, to fit a video into 1280×720, without upscaling (see this post for more info):

ffmpeg -i input.mp4 -filter:v "scale='min(1280,iw)':min'(720,ih)':force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output.mp4

Here, the scale filter scales to 1280×720 if the input video is larger than that. If it is smaller, it will not be upscaled. The pad filter is necessary to bring the output video to 1280×720, in case its aspect ratio or size differs from the target size.


With older ffmpeg versions, there is a somewhat hacky workaround. First, define the width, height and aspect ratio of your output. This will save us some typing.

width=640; height=360
aspect=$( bc <<< "scale=3; $width / $height") # <= floating point division

Now, let's apply the super complex filter command that Jim Worrall wrote:

ffmpeg -i input.mp4 -vf "scale = min(1\,gt(iw\,$width)+gt(ih\,$height)) * (gte(a\,$aspect)*$width + \
lt(a\,$aspect)*(($height*iw)/ih)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*iw : \
min(1\,gt(iw\,$width)+gt(ih\,$height)) * (lte(a\,$aspect)*$height + \
gt(a\,$aspect)*(($width*ih)/iw)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*ih" \
output.mp4

I won't really go into explaining what this all does, but basically you can feed it any video, and it will only downscale, not upscale. If you're up for it you can dissect the filter into its individual expressions. It might be possible to shorten this, but it works like that as well.

Source Link
slhck
  • 230.2k
  • 71
  • 621
  • 603

First, define the width, height and aspect ratio of your output. This will save us some typing.

width=640; height=360
aspect=$( bc <<< "scale=3; $width / $height") # <= floating point division

Now, let's apply the super complex filter command that Jim Worrall wrote:

ffmpeg -i input.mp4 -vf "scale = min(1\,gt(iw\,$width)+gt(ih\,$height)) * (gte(a\,$aspect)*$width + \
lt(a\,$aspect)*(($height*iw)/ih)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*iw : \
min(1\,gt(iw\,$width)+gt(ih\,$height)) * (lte(a\,$aspect)*$height + \
gt(a\,$aspect)*(($width*ih)/iw)) + not(min(1\,gt(iw\,$width)+gt(ih\,$height)))*ih" \
output.mp4

I won't really go into explaining what this all does, but basically you can feed it any video, and it will only downscale, not upscale. If you're up for it you can dissect the filter into its individual expressions. It might be possible to shorten this, but it works like that as well.