FFmpeg has got a very powerful scale filter, which can be used to accomplish various tasks. Some of them are listed here. More can be found in the official documentation.
Warning:
- When using
-filter_complex
/-lavfi
, the default scaling flags are not applied, so the default algorithm is notbicubic
, butbilinear
. To achieve the same results for complex filter chains, you have to explicitly set the scaling algorithm via theflags=bicubic
option. That was fixed in 9f14396a5103ec80893db801035ece5d14c0d3c5. - In some cases, FFmpeg will set the Sample Aspect Ratio to compensate for the ratio change. You have to manually set the SAR value to 1:1 to make the players display it in the way you want. For example:
ffmpeg -i input.mp4 -vf scale=320:240,setsar=1:1 output.mp4
The above example is highly misleading becausesetsar=1:1
is equivalent tosetsar=r=1:max=1
. In this special case it accidentally gives the correct result SAR=1:1, but for examplesetsar=2:3
would give the wrong result SAR=2:1. The correct syntax for SAR=2:3 issetsar=2/3
, orsetsar=1
for the above example.
- When going from BGR (not RGB) to yuv420p the conversion is broken (off-by-one). Use -vf scale=flags=accurate_rnd to fix that.
- yuvjxxxp pixel formats are deprecated. Yet for x265 the workaround was implemented, but not for jpeg2000 and AV1. For those -vf scale=out_range=pc should be used.
- Conversion from YCbCr limited to RGB 16 bit is broken, use zscale instead of swscale
- Limited range RGB is not supported at all.
- Dither can be turned off using -vf scale=sws_dither=none
- One should always remember that YCbCr 4:4:4 8 bit is not enough to preserve RGB 8 bit, YCbCr 4:4:4 10 bit is required.
- The default for matrix in untagged input and output is always limited BT.601
In all the examples, the starting image (input.jpg) will be this one (535×346 pixels):
Simple Rescaling
If you need to simply resize your video to a specific size (e.g 320×240), you can use the scale filter in its most basic form:
ffmpeg -i input.avi -vf scale=320:240 output.avi
Same works for images too:
ffmpeg -i input.jpg -vf scale=320:240 output_320x240.png
The resulting image will look like this:
As you can see, the aspect ratio is not the same as in the original image, so the image appears stretched.
Keeping the Aspect Ratio
If we'd like to keep the aspect ratio, we need to specify only one component, either width or height, and set the other component to -1. For example, this command line:
ffmpeg -i input.jpg -vf scale=320:-1 output_320.png
will set the width of the output image to 320 pixels and will calculate the height of the output image according to the aspect ratio of the input image. The resulting image will have a dimension of 320×207 pixels.
Some codecs require the size of width and height to be a multiple of n. You can achieve this by setting the width or height to -n:
ffmpeg -i input.jpg -vf scale=320:-2 output_320.png
The output will now be 320×206 pixels.
Using Variables
There are also some useful variables which can be used instead of numbers, to specify width and height of the output image.
For example, if you want to stretch the image in such a way to only double the width of the input image, you can use something like this (iw
= input width, ih
= input height):
ffmpeg -i input.jpg -vf scale=iw*2:ih input_double_width.png
The output image will look like this:
If you want to half the size of the picture, just multiply by .5 or divide by 2:
ffmpeg -i input.jpg -vf "scale=iw*.5:ih*.5" input_half_size.png ffmpeg -i input.jpg -vf "scale=iw/2:ih/2" input_half_size.png
Avoiding Upscaling
Sometimes you want to scale an image, but avoid upscaling it if its dimensions are too low. This can be done using min
expressions:
ffmpeg -i input.jpg -vf "scale='min(320,iw)':'min(240,ih)'" input_not_upscaled.png
The output width will be evaluated to be the minimum of 320 and the input width. If you have an imput image that is only 240 pixels wide, the result of the min
function will be 240 – this will be your target value.
Fitting into a Rectangle / Statically-sized Player
Sometimes you need to scale the input image so that it fits into a specified rectangle, e.g. when consolidating material from different sources.
You can achieve this with the force_original_aspect_ratio
option. It has two possible values:
decrease
: The output video dimensions will automatically be decreased if needed.increase
: The output video dimensions will automatically be increased if needed.
This allows you to force the image to fit into a 320×240 box, downscaling it with the correct aspect ratio:
ffmpeg -i input.jpg -vf scale=w=320:h=240:force_original_aspect_ratio=decrease output_320.png
This produces our 320×207 image that we had seen before.
You may have additional constraints such as adding black bars (pillar- and letterboxing) to fill up the remaining space when scaling to a certain rectangle. You can additionally add a black border using the pad
filter:
ffmpeg -i input.jpg -vf "scale=320:240:force_original_aspect_ratio=decrease,pad=320:240:(ow-iw)/2:(oh-ih)/2" output_320_padding.png
More examples can be found in this Super User answer.
scale2ref
If you need to scale one video to match another without pre-defining the dimensions, see the scale2ref filter.
Two videos are provided for input and output. The 1st input is scaled and the 2nd input is unchanged, but used for reference. For example, to put 2 videos side-by-side and have the 2nd video scale to match the first:
ffmpeg -i vid1.mp4 -i vid2.mp4 -filter_complex "[1:v][0:v]scale2ref=oh*mdar:h=in_h:[v1][v0];[v0][v1]hstack[vo]" -map "[vo]" ./output-video.mp4
Specifying scaling algorithm
You can specify which algorithm is used for resizing with the -sws_flags
option. For example, to use bilinear instead of the default bicubic scaling:
ffmpeg -i test.tif -vf scale=504:376 -sws_flags bilinear out.bmp
List of scaling algorithms with their defaults, if any:
fast_bilinear
bilinear
bicubic
experimental
neighbor
area
bicublin, Bicubic scaling algorithm for the luma component, bilinear for chroma components.
gauss
sinc
lanczos, The default width (alpha) is 3 and can be changed by setting param0.
spline
See the scaler documentation for more info.
Setting param0 for lanczos is done via
-vf scale=1920x1080:flags=lanczos:param0=3
To set multiple flags you can combine them with a +
sign. For example:
-sws_flags lanczos+full_chroma_inp
You can also specify the options directly in the scale
filter, for example:
-vf scale=1920x1080:flags=lanczos
Chroma sample location
FFmpeg does not see the chroma sample location on either limited or full range file, so you should specify it by hand when going to .rgb (or upsampled from 4:2:0 to 4:4:4 .yuv):
ffmpeg -i cosmos.mkv -vf 'scale=in_h_chr_pos=0:in_v_chr_pos=128' -pix_fmt rgb24 qnfvarejwnfe3.rgb //for left ffmpeg -i cosmos.mkv -vf 'scale=in_h_chr_pos=0:in_v_chr_pos=0' -pix_fmt rgb24 qnfvarejwnfe3.rgb //for top-left
To create BT.2020-NCL matrix with top-left chroma this can be used (if the source image is not using bt.2020 primaries the color managment must be done first on linear data, also correct transfer must be tagged, either SDR or HDR one, again this requires color managment):
-vf scale=out_color_matrix=bt2020nc:out_h_chr_pos=0:out_v_chr_pos=0
To change chroma sample location in VUI in HEVC to 0 (left) with -c copy this can be used (2 would be top-left, -1 will remove any sample location from VUI, all 0, 1, 2, 3, 4, 5 sample locations are possible):
ffmpeg -i file.mp4 -c copy -bsf:v hevc_metadata=chroma_sample_loc_type=0 file1.mp4
Attachments (5)
- input.jpg (53.8 KB ) - added by 10 years ago.
- output_320x240.png (169.5 KB ) - added by 10 years ago.
- output_320.png (147.9 KB ) - added by 10 years ago.
- input_double_width.png (577.6 KB ) - added by 10 years ago.
- output_320x240_boxed.png (167.5 KB ) - added by 10 years ago.
Download all attachments as: .zip