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.
- When using
-lavfi, the default scaling flags are not applied, so the default algorithm is not
bilinear. To achieve the same results for complex filter chains, you have to explicitly set the scaling algorithm via the
flags=bicubicoption. 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.mp4The above example is highly misleading because
setsar=1:1is equivalent to
setsar=r=1:max=1. In this special case it accidentally gives the correct result SAR=1:1, but for example
setsar=2:3would give the wrong result SAR=2:1. The correct syntax for SAR=2:3 is
setsar=1for 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):
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.
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
Sometimes you want to scale an image, but avoid upscaling it if its dimensions are too low. This can be done using
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
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.
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:
bicublin, Bicubic scaling algorithm for the luma component, bilinear for chroma components.
lanczos, The default width (alpha) is 3 and can be changed by setting param0.
See the scaler documentation for more info.
Setting param0 for lanczos is done via
To set multiple flags you can combine them with a
+ sign. For example:
You can also specify the options directly in the
scale filter, for example:
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):
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
- 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