SnapTools
Media

Video compression explained: codecs, CRF and why files are huge

5 min read · updated 2026-07-21

Uncompressed video is absurdly large. A single frame of 1080p in 8-bit colour is 1920 × 1080 × 3 bytes ≈ 6.2 MB; at 30 frames per second that is about 187 MB per second, or 11 GB per minute. The fact that a minute of decent-looking 1080p can instead fit in 10–20 MB — a compression ratio of several hundred to one — is down to some genuinely clever engineering, and understanding a little of it explains almost every practical question about video files.

What H.264 actually does

H.264 (also called AVC), still the most widely compatible codec, attacks the problem on two fronts.

Within a frame, it works like a smarter JPEG: blocks of pixels are predicted from their already-decoded neighbours, and only the prediction error is transformed, quantised and stored.

Between frames is where the big wins live. Consecutive video frames are usually almost identical — the camera holds still, most of the scene doesn't move. So instead of storing each frame, the encoder stores how to build this frame out of previous ones. It divides the frame into blocks, searches nearby frames for where each block came from (motion estimation), and records just a motion vector plus the small residual difference. A talking-head shot where only a face moves costs almost nothing per frame.

This creates three frame types:

  • I-frames (keyframes) — complete, self-contained images. Expensive, but decodable on their own.
  • P-frames — predicted from earlier frames.
  • B-frames — predicted from earlier and later frames; cheapest of all.

Typically there is one keyframe every few seconds, with dozens of P- and B-frames between. This is why you can only jump cleanly to certain points in a video: playback must start from a keyframe and decode forward. It is also why static-camera footage compresses vastly better than confetti, rain or handheld shake — motion the encoder cannot predict must be paid for in bits.

Newer codecs — H.265/HEVC, VP9, AV1 — are refinements of the same architecture with larger blocks, cleverer prediction and better entropy coding. Each generation buys roughly 30–50% smaller files at equal quality, at the price of slower encoding and patchier device support.

CRF vs bitrate: two ways to say "how good"

Encoders need to know how much to compress, and there are two philosophies:

Bitrate targeting ("make this 5 Mbps") fixes the file size but lets quality float: simple scenes get more quality than they need, complex scenes get starved and fall apart into blocking. Use it only when the size genuinely is the constraint — live streaming, or hitting an upload cap.

CRF (Constant Rate Factor) fixes quality and lets file size float. You pick a number — for x264, the scale runs 0 (lossless) to 51 (dreadful), with 18–28 the useful range and 23 the default — and the encoder spends whatever bits each scene needs to hold that perceptual quality. Lower is better quality; each step of ±6 roughly doubles or halves the file size. CRF 18 is generally regarded as visually transparent for most content; CRF 28 is noticeably compressed but fine for casual sharing.

For any file you are compressing offline, CRF is the right tool: you get consistent quality and the smallest file that achieves it.

The lever people forget: resolution

Quality sliders get all the attention, but pixel count is the bigger dial. Going from 1080p to 720p removes 56% of the pixels; to 480p removes 79%. Fewer pixels means less to encode at every quality level, and on a phone screen — where much shared video is watched — the difference between 1080p and 720p is often invisible. If a file must shrink a lot, dropping resolution one step usually looks better than keeping the resolution and strangling it with a high CRF, because under-fed high-resolution video develops ugly block artefacts while properly-encoded lower-resolution video just looks slightly soft.

Container vs codec: why "it's an MP4" answers nothing

An MP4 is not a format of video — it is a container, a filing box holding one or more streams: a video stream (H.264, H.265, AV1…), audio streams (AAC, Opus…), subtitles, chapter markers. MKV, MOV and WebM are other boxes for the same kinds of contents. This is why one MP4 plays everywhere and another stutters: the box is the same, the codec inside differs. It is also why "converting" MKV to MP4 can be instantaneous — if the streams inside are already compatible, they can be remuxed: copied into the new container bit-for-bit, no re-encoding, no quality loss, done in seconds.

Why GIFs are enormous

A GIF of a video clip is routinely 10–20× the size of an equivalent MP4, and worse-looking. The GIF format dates from 1987 and has none of the machinery above: no inter-frame motion prediction worth the name, no DCT, a hard limit of 256 colours per frame, and lossless LZW compression that was designed for simple graphics. A 5-second clip that costs 500 KB as H.264 can easily exceed 10 MB as a GIF. Every modern platform knows this — most "GIFs" you see on social media are actually silent looping MP4s. Make a real GIF only when you need one (some chat tools, some CMSs, email), keep it short, small and under ~15 fps, and use MP4 everywhere else.

Trimming: the free lunch

Cutting a clip out of a longer video does not have to mean re-encoding it. A stream-copy trim simply copies the compressed frames between two points into a new file: instant, and zero quality loss. The catch follows from keyframes: the cut can only start cleanly at a keyframe, so your start point may shift by up to a few seconds, or the first moments may show garbled frames until the next keyframe arrives. Frame-accurate cutting requires re-encoding at least the section before the first keyframe (or the whole clip), trading a little quality and time for precision. Know which one your tool is doing, and you will know why the trim was instant — or why it wasn't.

The short version

Modern codecs work by not storing what hasn't changed. Compress with CRF rather than a bitrate, drop resolution before you drop quality, remember the container is just a box, trim without re-encoding when keyframe precision is good enough — and never ship a GIF where an MP4 would do.