# FFmpeg Scale Filter: Every Option You Actually Need

`scale=1280:720` works. It is also, in a lot of real situations, wrong — it will happily stretch a 4:3 source into widescreen, produce odd dimensions that some encoders reject, and resample with an algorithm that is not the best fit for your content.

This guide covers the parts of the `scale` filter that matter in practice: automatic dimension calculation, expressions, aspect-ratio handling, algorithm selection, and the hardware-accelerated variants that are much faster on modern machines.

---

### The Basic Form

```bash
ffmpeg -i input.mp4 -vf scale=1280:720 output.mp4
```

`-vf` is shorthand for `-filter:v`. Everything after `scale=` is a colon-separated argument list, first width then height.

That command re-encodes the video, which is unavoidable — you cannot change frame dimensions without re-encoding, since the dimensions are baked into the compressed bitstream. Because you are re-encoding anyway, it is worth passing quality settings rather than accepting the defaults:

```bash
ffmpeg -i input.mp4 -vf scale=1280:720 -c:v libx264 -crf 20 -preset slow -c:a copy output.mp4
```

`-c:a copy` passes the audio through untouched, which saves time and avoids a pointless generation of audio loss.

---

### -1 and -2: Automatic Dimensions

Hardcoding both dimensions means you have to know the source aspect ratio. You usually do not, especially in a batch. FFmpeg can compute one from the other.

```bash
# Height 1080, width computed to preserve aspect ratio
ffmpeg -i input.mp4 -vf "scale=-2:1080" output.mp4

# Width 1280, height computed
ffmpeg -i input.mp4 -vf "scale=1280:-2" output.mp4
```

**Use `-2`, not `-1`.** Both preserve the aspect ratio; the difference is rounding.

- `-1` gives the exact computed value, which is frequently odd.
- `-2` rounds to the nearest even number.

H.264, HEVC and most other codecs use 4:2:0 chroma subsampling, which requires even dimensions. Feed libx264 a width of 853 and it will fail with `width not divisible by 2`. The one-pixel difference `-2` introduces is invisible; the error `-1` produces is not.

There is also `-n` for any positive n, which rounds to the nearest multiple of n. `scale=-4:720` guarantees divisibility by 4, occasionally required by specific hardware encoders.

---

### Expressions: iw, ih and Arithmetic

The scale filter accepts expressions, not just numbers. The two variables you will use constantly:

- `iw` — input width
- `ih` — input height

```bash
# Half size
ffmpeg -i input.mp4 -vf "scale=iw/2:ih/2" output.mp4

# 75% of original
ffmpeg -i input.mp4 -vf "scale=iw*0.75:ih*0.75" output.mp4

# Double (upscaling — see the caveat below)
ffmpeg -i input.mp4 -vf "scale=iw*2:ih*2" output.mp4
```

Fractional scaling can produce odd dimensions, so wrap it:

```bash
ffmpeg -i input.mp4 -vf "scale=trunc(iw*0.75/2)*2:trunc(ih*0.75/2)*2" output.mp4
```

That looks worse than it is: divide by 2, truncate to an integer, multiply back by 2. The result is always even.

**Conditional scaling** is where expressions earn their keep. This downscales anything wider than 1920 and leaves smaller files alone:

```bash
ffmpeg -i input.mp4 -vf "scale='min(1920,iw)':-2" output.mp4
```

Without the `min()`, a 720p source would be upscaled to 1920 — bigger file, no additional detail, worse than doing nothing. This is the single most useful expression in the filter and it belongs in most batch scripts.

---

### force_original_aspect_ratio

For fitting video into a fixed box without distortion, this option is cleaner than manual expressions.

```bash
# Fit inside 1920x1080 — never exceeds either dimension
ffmpeg -i input.mp4 -vf "scale=1920:1080:force_original_aspect_ratio=decrease" output.mp4

# Cover 1920x1080 — fills the box, may overflow one dimension
ffmpeg -i input.mp4 -vf "scale=1920:1080:force_original_aspect_ratio=increase" output.mp4
```

`decrease` is the letterbox-friendly behaviour: the output fits entirely within the target and one dimension will usually come up short. `increase` is the crop-friendly behaviour: the output covers the target and overflows.

Combine `decrease` with `pad` to get exact output dimensions with black bars rather than a stretched picture:

```bash
ffmpeg -i input.mp4 -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2" output.mp4
```

The `pad` arguments are target width, target height, then x and y offsets. `(ow-iw)/2` and `(oh-ih)/2` centre the video in the padded frame. This is the standard recipe for delivering mixed-aspect footage to a platform that demands one fixed size.

Note the comma: `scale` and `pad` are two filters chained in a single filtergraph, applied left to right.

---

### Choosing the Scaling Algorithm

FFmpeg's default is bicubic. It is a fine default and often not the best choice.

```bash
ffmpeg -i input.mp4 -vf "scale=1280:-2:flags=lanczos" output.mp4
```

| Algorithm | Best for | Character |
| --- | --- | --- |
| `bicubic` | General purpose (default) | Balanced sharpness and speed |
| `lanczos` | Downscaling video and photos | Sharpest perceived detail; slight ringing on hard edges |
| `bilinear` | Speed-critical work | Fast, noticeably soft |
| `neighbor` | Pixel art, crisp UI screen recordings | No interpolation at all; preserves hard pixel edges |
| `spline` | Upscaling | Smooth, low artefacts |
| `area` | Large downscale ratios | Averages source pixels; good anti-aliasing |

The practical takeaways: use **lanczos** when downscaling real-world footage — it is the most common upgrade over the default and costs very little. Use **neighbor** for screen recordings of text or UI, where interpolation turns crisp pixels into mush. Use **area** when shrinking dramatically, such as generating thumbnails, where lanczos ringing becomes visible.

---

### Hardware-Accelerated Scaling

On modern machines, scaling on the GPU or media engine is substantially faster, particularly when the decode and encode are already happening there — it avoids round-tripping frames through system memory.

**macOS (VideoToolbox):**

```bash
ffmpeg -hwaccel videotoolbox -i input.mp4 -vf "scale_vt=1280:-2" -c:v h264_videotoolbox output.mp4
```

**NVIDIA:**

```bash
ffmpeg -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -vf "scale_cuda=1280:-2" -c:v h264_nvenc output.mp4
```

**Intel Quick Sync:**

```bash
ffmpeg -hwaccel qsv -i input.mp4 -vf "scale_qsv=w=1280:h=-1" -c:v h264_qsv output.mp4
```

Two caveats. The hardware scalers expose fewer options — you generally do not get algorithm selection. And mixing hardware and software filters in one chain forces frames back and forth between GPU and system memory, which can be slower than staying in software the whole way. Keep the chain entirely on one side where you can.

Quality trade-offs of hardware versus software processing are covered in [hardware vs software video encoding](/content/blog/hardware-vs-software-video-encoding/index.html).

---

### -s vs -vf scale

You will see both in older documentation.

```bash
ffmpeg -i input.mp4 -s 1280x720 output.mp4       # legacy shorthand
ffmpeg -i input.mp4 -vf scale=1280:720 output.mp4 # filter
```

`-s` sets fixed output dimensions and will stretch the image if the aspect ratio does not match. It offers no expressions, no automatic dimension calculation and no algorithm selection. It also conflicts with a filtergraph that already scales.

Use `-vf scale`. There is no situation where `-s` is better.

---

### A Note on Upscaling

The scale filter will upscale as readily as it downscales, but it cannot invent detail that was never captured. Scaling 720p to 4K produces a 4K file that looks like soft 720p, at several times the bitrate. The only things that genuinely gain from upscaling are compatibility with a pipeline that demands a specific resolution, and delivery targets that penalise low resolutions.

If you must upscale, `spline` or `lanczos` tend to look best, and it is worth being honest that neither is doing anything a good display's own scaler would not.

---

### Frequently Asked Questions

#### Why does my FFmpeg scale command fail with "width not divisible by 2"?

You used `-1` and the computed dimension came out odd. Switch to `-2`, which rounds to an even number.

#### How do I scale a video to a specific file size?

Scaling changes dimensions, not file size directly. To target a size you need to control bitrate — either by calculating a target bitrate from the duration, or by adjusting CRF. See [FFmpeg compress video](/content/blog/ffmpeg-compress-video/index.html).

#### Can I scale without re-encoding?

No. Frame dimensions are part of the encoded bitstream, so changing them requires decoding and re-encoding. Only operations that leave the video stream untouched — remuxing to a different container, trimming on keyframes — can avoid re-encoding.

#### How do I scale multiple videos at once?

A shell loop works: `for f in *.mp4; do ffmpeg -i "$f" -vf "scale=-2:720" "out_$f"; done`. For anything more involved, a GUI batch tool will be less error-prone.

#### Does scaling down improve quality?

It cannot add quality, but downscaling does hide compression artefacts and noise by averaging them away, so a downscaled version of a poor source often looks cleaner than the original at full size. It also reduces the bitrate needed for a given perceived quality.
