# FFmpeg lanczos vs bicubic scaling

Canonical: https://rendobar.com/blog/ffmpeg-scaling-flags-measured/
Author: Abdelrahman Essawy
Published: 2026-08-20
Updated: 2026-08-20

---

## Key takeaways

- Encode time across five scaling algorithms varied by 17 ms, from 636 to 653, which is under 3%. The flag costs nothing.
- Output size varied by 66%: neighbor produced 394 KB where bilinear produced 237 KB, on the identical downscale.
- Nearest-neighbor is the expensive choice. Its hard pixel edges are high-frequency detail that the encoder then has to spend bytes on.
- Smaller is not better here. Bilinear was smallest because it is blurriest, and blur compresses well. Lanczos, bicubic and spline cluster at 265 to 273 KB, which is the useful range.
- FFmpeg's default is bicubic and it is a sensible default. The flag is worth setting explicitly anyway, because the default has changed before.

`scale=854:-2` uses a default scaling algorithm you probably never chose. The
question is whether choosing costs anything.

Short version. It does not. Across five algorithms, encode time varied by **under
3%** while output size varied by **66%**. The scaler flag is one of the few
genuinely free decisions in an FFmpeg command.

## The time column is a flat line

**636 ms** to **653 ms** across nearest-neighbor, bilinear, bicubic, lanczos and
spline. A 17 ms spread, which is inside the run-to-run noise on a clip this
short.

That makes sense once you see where the work is. Scaling is a per-pixel filter
pass; encoding is a search problem. The encoder dominates so completely that the
difference between a 2-tap and an 8-tap resampling kernel disappears into it.

So there is no reason to pick a cheap scaler for speed. That was maybe true on
2005 hardware for realtime work. It is not true here.

## Nearest-neighbor is the expensive one

**394 KB** against bicubic's **265 KB**, for the same output resolution. 49%
more bytes from a flag.

The mechanism is worth understanding because it generalises. Nearest-neighbor
picks one source pixel per output pixel and copies it, which produces hard,
stair-stepped edges. Hard edges are high-frequency content, and high-frequency
content is exactly what a DCT-based codec spends bits describing. So the cheap
scaler hands the encoder a harder problem and you pay for it downstream.

**Any filter that adds sharp artificial detail costs you encoder bytes.** That is
the same reason heavy sharpening inflates file size, and it is why the size
column here is not a quality ranking.

## Smaller is not better

Bilinear produced the **smallest** file at **237 KB**, and it is not the best
choice.

Bilinear averages two taps, which is a soft, slightly blurry resample. Blur is
low-frequency, low-frequency compresses well, and so the blurriest option wins on
bytes while looking worst. If you optimise this table for size you will pick the
wrong algorithm.

The useful cluster is the middle: **bicubic 265 KB, spline 269 KB, lanczos 273
KB**, within 3% of each other. Those three are all reasonable, and the 8 KB
between them is not worth thinking about.

## What to actually set

For a downscale, **lanczos** is the conventional choice and is what our own GIF
recipe uses, because it holds edge detail well. **bicubic** is FFmpeg's default
and is fine. **spline** is between them.

Use nearest-neighbor only when you want the stair-stepping: pixel art, or
upscaling a QR code or a barcode where interpolation would destroy the thing you
are scaling.

And set the flag explicitly. `scale=854:-2:flags=lanczos` costs nothing to write
and does not depend on the default staying what it is today.

## Where this stops

One 720p to 480p downscale, libx264 CRF 23 preset medium, audio stripped. The
size ordering is a property of what each kernel does to detail, so it should
travel, but the magnitudes will move with content: footage that is already soft
gives nearest-neighbor less to stair-step and narrows the gap.

Upscaling is a different question with a different answer, and this sweep does
not test it.

The scaler flag is one of seven settings measured on this same source. The rest are in [FFmpeg encoding settings compared](/blog/ffmpeg-encoding-settings/).
