Optimizing videos for the web: our ffmpeg pipeline
How to compress videos for the web without killing load time. Codecs, concrete ffmpeg commands, lazy loading, and autoplay attributes from our real pipeline.

A 40 MB hero video looks great in the editor and makes your site unusable on mobile. The usual online tools do shrink the file, but they know nothing about your website: nothing about the right codec, nothing about autoplay, nothing about load time on mobile connections.
This article shows how we actually optimize videos for the web. It is the same ffmpeg pipeline we use to get video-heavy high-end sites like FRAMEN to green PageSpeed scores. Codec choice, concrete commands, delivery. No marketing, just the flags we really use.
Key takeaways
- The best codec for the web is H.264 (MP4) as a compatible baseline, plus WebM/VP9 or AV1 as a smaller alternative for modern browsers.
- Compressing works cleanest with ffmpeg via CRF instead of fixed bitrate: -crf 23 for H.264, -crf 30 for VP9. Lower means better quality and a bigger file.
- A web video should rarely exceed 1080p and 30 fps. Lowering resolution and frame rate saves more than any codec trick.
- Without a poster frame, lazy loading, and the attributes muted, autoplay, playsinline, autoplay fails on iOS and the first frame arrives too late.
- That is how we get FRAMEN with heavy hero videos to green Core Web Vitals: small files, an instant poster, late loading, delivery over a CDN.
Why web video is different from just compressing a video
Optimizing a video for the web is not the same as compressing it. Compressing makes the file smaller. Optimizing means building it so a browser starts it fast, plays it smoothly, and does not eat mobile data.
The online tools in the search results (clideo, freeconvert, video-verkleinern.online) only solve the first part. They do not know your page. They do not know that iOS blocks an autoplay video without the muted attribute, that a missing poster frame ruins your Largest Contentful Paint, or that a video without the right container structure loads fully before it even starts.
So web video optimization has three layers: choose the right codec, compress cleanly, then deliver it so load time does not suffer. These are exactly the three layers we walk through.
Which video format and codec for the web?
For the web, two things matter: the container format (the file extension like MP4 or WebM) and the codec inside it (H.264, H.265, VP9, AV1). The codec determines compression and compatibility, the format is just the wrapper. Here are the four that are practically relevant.
MP4 with H.264
MP4 with H.264 (also called AVC) is the safe baseline. It runs in every browser, on every device, for over a decade. Its compression is not the most efficient, but its compatibility is perfect. H.264 belongs in every web video delivery as a fallback so every visitor actually sees something.
H.265/HEVC
H.265, also HEVC, compresses around 40 to 50% smaller than H.264 at the same quality. The catch: license costs and patchy browser support. Safari plays it, Chrome and Firefox did not do so reliably for a long time. For the open web, HEVC is therefore not a good standard. We only use it in closed environments, not on public sites.
WebM with VP9
WebM with VP9 is Google’s license-free standard and compresses about 30 to 50% more efficiently than H.264. Chrome, Firefox, and Edge support it fully, Safari now too. In practice we deliver VP9 as the modern variant and H.264 as the fallback. The browser automatically takes the smaller file it understands.
AV1
AV1 is currently the most efficient open codec and beats VP9 by another 30% or so. The price is encoding time: encoding AV1 takes many times longer than H.264. For a short hero loop that is encoded once and delivered thousands of times, it is worth it. For large volumes of video, less so. Browser support is broad in 2026 but not everywhere yet, so H.264 stays the fallback.
Web codecs compared
| Codec | Efficiency | Support | Use |
|---|---|---|---|
| H.264 (MP4) | Baseline | Everywhere | Mandatory fallback |
| H.265/HEVC | +40–50% | Patchy | Closed only |
| VP9 (WebM) | +30–50% | Broad | Modern variant |
| AV1 | +50–60% | Growing | Short hero loops |
Compressing videos with ffmpeg (our pipeline)
ffmpeg is the tool we process every web video with. It is a command-line tool, free, and gives you full control over every parameter. Unlike an online tool, you do not guess what happens, you set exactly the flags you need. The following building blocks are the ones we use in real projects.
Bitrate or CRF
For web video you almost always use CRF (Constant Rate Factor) instead of a fixed bitrate. CRF keeps quality constant and lets file size vary with the motion in the frame. That is exactly right when quality is the goal and the file should be as small as possible.
The value -crf 23 is the default for H.264. Lower (around 18) means better quality and a bigger file, higher (around 28) means more compression and more visible artifacts. For VP9 the comparable range is -crf 30 to 34. Start at 23, go up until you see the quality drop, then step back one.
Resolution and frame rate
The biggest lever is not the codec but the size of the image. A web video rarely needs more than 1080p (1920 pixels wide), often 720p is enough. Scale down with the flag -vf scale=1920:-2 (the -2 keeps the aspect ratio and ensures even pixel dimensions). For an atmospheric background loop, 24 or 30 fps is plenty, no reason for 60 fps. Set that with -r 30. Resolution and frame rate together often save more than any codec change.
Two-pass encoding
When you need a fixed target file size, say for a load-time budget, you use two-pass instead of CRF. ffmpeg analyzes the video in the first run and distributes the bitrate optimally across the scenes in the second. At a fixed bitrate, this gives the best quality. For most hero loops, CRF is enough, but for long videos with a hard size limit, two-pass is the cleaner tool.
Extracting a poster frame
The poster frame is the still image the browser shows immediately before the video loads. It is the real trick for good Core Web Vitals: the image is there in milliseconds, the video follows in the background. Without a poster, the user stares at an empty area, and your Largest Contentful Paint waits for the whole video.
With ffmpeg you pull the frame straight from the video, for example at second one, and deliver it as a lean WebP or JPEG. A poster of a few kilobytes replaces megabytes of perceived waiting.
The concrete ffmpeg commands
Here are the commands we actually use. First H.264 as the fallback with CRF 23, scaled to 1080p and 30 fps, with -movflags +faststart so the browser can start immediately instead of waiting for the whole file:
ffmpeg -i input.mov -c:v libx264 -crf 23 -preset slow -vf scale=1920:-2 -r 30 -movflags +faststart -c:a aac -b:a 128k output.mp4
Then the same source as WebM/VP9 for modern browsers:
ffmpeg -i input.mov -c:v libvpx-vp9 -crf 30 -b:v 0 -vf scale=1920:-2 -r 30 -c:a libopus output.webm
And the poster frame at second one:
ffmpeg -i input.mov -ss 00:00:01 -frames:v 1 poster.webp
The flag -preset slow on H.264 controls how much compute time ffmpeg spends on compression. Slower means a smaller file at the same quality. With -b:v 0 for VP9, the codec works purely quality-based via the CRF value. These three commands are the base of our pipeline.
Delivering without killing load time
A small video is half the battle. The other half is how you embed it in the page. A perfectly compressed video that the browser loads immediately and completely can still make your page slow. Four things decide it.
Lazy loading
Videos that are not in the first screen should only load when the user scrolls near them. Via an Intersection Observer you load the source only once the video is about to become visible. That way no video further down blocks the initial page render. For the hero video at the top you do not use lazy loading, you use the poster frame as an instant still instead.
Autoplay, muted, and playsinline
An autoplay background video needs three attributes, otherwise it will not play, especially on iOS. It must be muted (browsers block autoplay with sound), carry autoplay, and playsinline so iOS plays it inline instead of jumping into the fullscreen player. Add loop for repetition and preload="none" or "metadata" so the whole file is not pulled immediately. In practice: <video autoplay muted loop playsinline preload="none" poster="poster.webp">.
Poster as an instant still
The poster attribute in the <video> tag shows your extracted still until the video is ready. That is why a video hero can get a good Largest Contentful Paint at all: the browser renders the light poster in milliseconds while the heavy video loads in the background. Without a poster, the measurement waits for the video and your LCP score tips into the red.
Delivery over a CDN
A video file should not come from your origin server but from a CDN that caches the file near the user and supports byte-range requests. That way the browser loads only the parts of the video it currently needs, instead of the whole file at once. Together with +faststart in the MP4, the video starts almost instantly, no matter how big it is overall.
What this does for your website
The point behind all this effort is not smaller files in themselves but Core Web Vitals, and with them a ranking and a user experience that hold. A heavy hero video without optimization destroys the Largest Contentful Paint and makes mobile users bounce before they see anything. That exact same pipeline of small codec, poster frame, late loading, and CDN is why a video-heavy site like FRAMEN keeps green PageSpeed scores.
How Core Web Vitals are measured exactly and which thresholds matter is in our article Understanding Core Web Vitals. If you want to see what this video pipeline looks like in a real enterprise project, read the making-of the FRAMEN website.
Frequently asked questions
Cleanest with ffmpeg via CRF. Scale to 1080p or 720p, set 30 fps, encode H.264 with -crf 23 as the fallback plus WebM/VP9 with -crf 30 as the smaller variant. Extract a poster frame and deliver everything over a CDN. That gives small files without visible quality loss.
H.264 (MP4) as the compatible baseline because it runs everywhere, plus WebM/VP9 or AV1 as the modern, smaller variant. The browser automatically picks the most efficient file it understands. HEVC/H.265 is not recommended for the open web due to licensing and patchy browser support.
For most web videos CRF is better because it keeps quality constant and lets file size vary with the motion in the frame. You only use a fixed bitrate or two-pass encoding when you need a hard target file size, for example due to a fixed load-time budget.
Because iOS only allows autoplay when the video is muted and inline-playable. It needs the attributes muted, autoplay, and playsinline. If one is missing, the browser blocks automatic playback or jumps into the fullscreen player.
As small as possible, as a guideline under a few megabytes for a short loop. Set resolution to 1080p or below, frame rate to 24 to 30 fps, shorten the loop, and use CRF. More important than a fixed MB limit is that a poster frame appears instantly and the video loads in the background.
For serious web performance, yes. Online tools shrink the file but give you no control over codec, CRF, faststart, poster frame, or the dual format of MP4 and WebM. ffmpeg is free, scriptable, and delivers reproducible results, which is why we run every web video pipeline with it.
More Articles
Let's talk about your project.
20-minute call, no sales pressure. You describe what you have in mind, we tell you if and how we can help.







