# AV1 vs HEVC vs H.264 at the same file size

Canonical: https://rendobar.com/blog/av1-vmaf-matched-size/
Author: Abdelrahman Essawy
Published: 2026-08-20
Updated: 2026-09-26

---

## Key takeaways

- To compare codecs, fix the file size and measure the quality. A shared CRF number compares settings, because each encoder has its own scale.
- At a starvation budget for 720p, the ordering was AV1, then HEVC, then H.264, with a gap of about 20 VMAF points between the ends.
- One budget is one point on the rate-quality curve. The gap between codecs is widest at low bitrates and narrows as the budget grows.
- codec auto chose H.264, the lowest scorer here, because it optimises for playback compatibility. Ask for AV1 explicitly when your players support it.

Held to the same 150 KB budget on a 5-second 720p clip, about 245 kbps, AV1
scored VMAF 84.8, HEVC 76.2 and H.264 64.3. That is one point on the
rate-quality curve, at a starvation budget where codec differences are widest,
so it settles the ordering and not the size of the gap at everyday bitrates.
The price of the AV1 result is encode time, covered below.

_Every case asked for a 150 KB ceiling. The job searched candidate encodes and scored each with VMAF, so size is the constant and quality is the measurement._

## How this was measured

Each row is one `compress.target` job asking for `maxBytes: 153600` (150 KB)
with a named codec. The job encodes with libx264, libx265 or SVT-AV1
(`libsvtav1`) at its default `effort: balanced`, searches the quality level
until the file fits, and scores every candidate against the source with
libvmaf's `vmaf_v0.6.1neg` model. The searches took five or six probe encodes
per codec. FFmpeg and encoder versions were not recorded. The shared clip and
setup are on [how we benchmark](/blog/how-we-benchmark/).

My earlier [AV1 vs VP9 vs HEVC vs H.264](/blog/av1-vp9-hevc-h264-measured/)
post ran each codec at its own conventional CRF, and said in its own caveats
that this compares settings, not codecs. CRF 23 does not mean the same thing to
x264 and to an AV1 encoder, and there is no conversion table between them.
Fixing the size and measuring the quality removes that problem.

## Same size, different quality

The three files landed within 5% of each other in size. The quality scores did
not come close. **At this budget AV1 held about 20 more VMAF points than H.264
in the same bytes**, with HEVC in between.

The regime matters. 150 KB over 5 seconds is a starvation budget for 720p, and
low bitrates are where newer codecs pull furthest ahead. At higher budgets all
three climb toward the top of the scale and the gap narrows. This sweep
measured one budget, so I would not quote the 20 points as the general
advantage of AV1, only the ordering.

VMAF is a model of human perception trained on viewer scores, not the
perception itself. It is known to be lenient on some kinds of blur and harsh on
some kinds of grain. A 20-point gap is far outside the range where those
effects would reverse an ordering. A 2-point gap would not be.

Codec labs publish matched comparisons like this for their own content, and
you can run the same search on yours:

const rb = createClient({ apiKey: process.env.RENDOBAR_API_KEY });

const job = await rb.jobs.run({
  type: "compress.target",
  inputs: { source: "https://cdn.rendobar.com/assets/examples/sample.mp4" },
  // Fix the bytes, name the codec, read the quality back.
  params: { target: { maxBytes: 153600 }, codec: "av1", for: "web" },
});

const d = job.output.data;
console.log(d.codec, d.achievedScore, job.output.file.size);`}
  curl={`curl -X POST https://api.rendobar.com/jobs \
  -H "Authorization: Bearer $RENDOBAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "compress.target",
    "inputs": { "source": "https://cdn.rendobar.com/assets/examples/sample.mp4" },
    "params": { "target": { "maxBytes": 153600 }, "codec": "av1", "for": "web" }
  }'`}
/>

Change `codec` to `h264` or `hevc` for the other two rows.

## codec auto picked the lowest scorer

`codec: auto` chose H.264, the lowest-scoring codec in the table.

Auto is not broken. It optimises for compatibility, and H.264 plays on
practically every device in use while AV1 decoding is still missing on a lot of
older hardware. For a general-purpose default that is the right call, for the
same reason [yuv420p is the right default](/blog/yuv420p-chroma-subsampling-cost/).

It does mean auto is not the setting to use if you care about quality per byte.
If your players support AV1, ask for AV1.

## What AV1 costs you

Encode time is not in this table. AV1 is slower to encode than H.264, and
[SVT-AV1 presets compared](/blog/svt-av1-presets-measured/) puts numbers on
that. The same source also has a size floor: asked for 100 KB or 50 KB, the
H.264 search returned the same 111.5 KB file.
[When compressing a video would make it bigger](/blog/compressor-that-refuses/)
covers how the job reports a floor like that instead of hiding it.

This is one of the comparisons behind the
[video codec comparison](/blog/video-codec-comparison/). For a library that is
encoded once and served many times, I would encode it in AV1 wherever the
players allow and keep H.264 as the fallback rendition. For content that is
transcoded constantly and watched rarely, the extra encode time is harder to
justify.
