Dev.to WebDev 🛠 Dev 👁 0 📖 4 min read

H.265 isn't what makes screen recordings small

If you ship a small product, you send screen recordings all the time: a demo for a client, a walkthrough, a bug repro. The file a recorder hands you can be far bigger than four minutes of slides should be, and a common r

If you ship a small product, you send screen recordings all the time: a demo for a client, a walkthrough, a bug repro. The file a recorder hands you can be far bigger than four minutes of slides should be, and a common reflex is to export it again as H.265, the newer codec most export dialogs now list. On the test clip below, that switch was worth 3%. What decided the size was how the encoder spends bits on frames that don't change, and how often it forces a keyframe.

The numbers come from one synthetic clip, not a real session. It imitates a 4-minute lecture-style recording, built from screenshots of a hand-written page: page turns, a cursor, typing, a notes panel that scrolls. It is 1920×1080, 30 fps, 360.0 MB, generated at a constant 12 Mbps, which is an assumed rate, since Apple's and Microsoft's support pages don't state a default bitrate for their recorders. Nothing moves for about 78% of it, and with no audio and no sensor noise it compresses more easily than a real capture would. Every setting got a single encode, run on an Apple M4 Mac using ffmpeg (x264, x265), the HandBrake CLI and macOS's avconvert. Text quality is SSIM on a crop of 15 px English text against the lossless master; the original file itself scores 0.971.

H.265 saved 3% at the same text quality

The baseline is x264 at CRF 23, preset medium: 5,222,157 bytes, text SSIM 0.970. Keeping CRF 23 and switching to x265 gave 6,058,499 bytes, 16% bigger. CRF values don't mean the same thing in the two encoders, so the fair comparison is x265 at CRF 28, where text SSIM landed at 0.969, level with the baseline. That file was 5,058,634 bytes, 3.1% smaller. HandBrake's stock presets pointed the same way: Fast 1080p30 (H.264) gave 6.01 MB, H.265 MKV 1080p30 gave 6.23 MB.

The two encodes, as settings to reproduce rather than captured output:

ffmpeg -i input.mp4 -c:v libx264 -preset medium -crf 23 -an h264.mp4
ffmpeg -i input.mp4 -c:v libx265 -crf 28 -an h265.mp4

A guess at why, and it is only a guess: in the x264 output, 29 keyframes held 79.4% of the bytes, around 140 KB each, while a frame where nothing moved cost a median of 77 bytes. There is almost nothing in the in-between frames for a smarter codec to squeeze, and the keyframes are still pictures of sharp text. On two CC-licensed camera clips from Wikimedia Commons, 59% to 78% of the bytes sat in P frames instead, which is where HEVC would be expected to earn its reputation. x265 was not run on those clips.

Rate control mattered far more than the codec

macOS's avconvert makes the point from the other side. Its HEVC 1080p preset encodes at a fixed rate of roughly 2.0 Mbps and produced 60.5 MB with the same text SSIM as the source, more than ten times plain H.264 at CRF 23. Its same-size H.264 presets didn't shrink the file at all. A constant-bitrate encoder spends the same budget on a frozen slide as on typing, and dropping that habit, not changing codec, is what took 360 MB down to 5.2 MB. Not every recording is bloated, though: the Mac's hardware H.264 encoder, given a 12 Mbps target in variable-bitrate mode, used about 0.79 Mbps on the same material.

Then the keyframe interval

With rate control sorted, the next lever on a mostly static recording is how often a full keyframe gets written. At CRF 23, spacing them 10 seconds apart instead of 2 removed about three quarters of the bytes (−75.6%), while a camera clip given the same change shrank by only 5.0%. Small text didn't get softer as the interval grew. The cost lands on seeking, since a player has to decode forward from the last keyframe, so for a demo that a client mostly watches straight through a longer interval is the cheaper trade, and for anything people scrub through it's worth checking before going much past 10 seconds.

What I'd do with the next demo video

Quality-based rate control first (CRF in ffmpeg, RF in HandBrake), then a keyframe interval around 10 seconds, and 1080p kept, since 720p saved 30.4% but took notes-panel text SSIM from 0.998 to 0.880. H.264 stays the default, and H.265 only when the client's player handles it and there's a reason besides size; HEVC playback wasn't tested here. If you'd rather not touch a command line, ImgIng's video compressor https://imging.ai/ runs in a desktop browser on the local file and handles batches and H.265. Its default H.264 output for this clip was 20.2 MB at text SSIM 0.969, roughly three times HandBrake's file at the same text quality, and the test runs saw no upload requests from it, which matters when a demo shows features that aren't public yet.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.