Optimizing videos for the web: our ffmpeg pipeline
How to optimize videos for the web without killing load time. Container vs. codec (H.264, VP9, AV1), concrete ffmpeg commands with CRF and faststart, lazy loading, poster, autoplay, accessibility, and self-hosting vs. YouTube. 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
- Separate container and codec: MP4 and WebM are wrappers, H.264, VP9, and AV1 the actual compressor. For the web both matter.
- H.264 (libx264) is the safe default: it runs on 99 percent of all devices. VP9 and AV1 save 35 to 60 percent file size but need an H.264 fallback.
- Compressing means turning three dials: CRF (quality), preset (encoding speed), codec (efficiency). CRF 23 with preset medium is the starting point for the web.
- Without -movflags +faststart your video only starts once it is fully loaded. This single flag decides perceived load time.
- A background video is a design element, not content: muted, playsinline, poster, lazy loading, and no audio. That way motion runs without wrecking Core Web Vitals.
Why is web video different from just compressing a video?
Shrinking a video for sending and optimizing a video for the web are two different jobs. For sending, only file size matters. On the web, what matters is how fast the video starts playing, whether it runs on every device, and whether it wrecks your load time and with it your Core Web Vitals. A 200 MB hero video slows your page down no matter how beautiful it is.
So it is not just about compression but about three things at once: the right format and codec, a clean compression with the right values, and a delivery that loads progressively instead of all at once. We walk through exactly these three layers here, with concrete ffmpeg commands from our real pipeline. At INSYNC we put a lot of motion and video into the web, so this is not theory but the way we do it every day.
Which video format and codec for the web?
First, keep the terms clean, because they get confused constantly. A container (MP4, WebM) is the wrapper: it holds picture, audio, subtitles, and metadata together. A codec (H.264, VP9, AV1) is the method that compresses the picture. An MP4 is therefore not automatically H.264, and WebM not automatically VP9, even if those are the usual pairings.
Four codecs matter for the web. The choice is a trade-off between compression efficiency, encoding speed, and playback compatibility. Rule of thumb: H.264 as the universal base, VP9 or AV1 as the economical variant with an H.264 fallback.
MP4 with H.264 (the safe default)
H.264, also called AVC, is the de facto standard for web video. Around 84 to 86 percent of the video industry uses it, and it runs on over 99 percent of all browsers and devices, including hardware decoding. The encoder is libx264. H.264 delivers very good quality at small file size and is always the base when everyone should really be able to see the video. If you can only ship one format, ship this one.
H.265/HEVC
H.265 (HEVC, encoder libx265) compresses around 35 to 45 percent smaller than H.264 at equal quality. The catch: it is license-encumbered, encoding takes 3 to 5 times as long, and browser support is split. Safari and the Apple world play it natively, Chrome and Firefox long did not reliably. For the open web HEVC is therefore rarely the first choice, but strong in a pure Apple environment.
WebM with VP9
VP9 (encoder libvpx-vp9) is Google’s license-free answer to H.265: also around 35 to 45 percent smaller than H.264, but without license fees. Chrome, Firefox, and Edge support it well, Safari only partially. It usually sits in the WebM container with Opus as the audio codec. For web-first projects where Chrome and Firefox dominate, VP9 is the obvious economical variant alongside H.264.
AV1 (the best compression)
AV1 (encoder libaom-av1 or the much faster libsvtav1) is the license-free codec from the Alliance for Open Media and compresses around 50 to 60 percent smaller than H.264. In 2026 AV1 is production-ready for delivery: Chrome, Firefox, Edge, and Safari from version 17 support it, and hardware decode covers around 80 percent of streaming devices. Over 75 percent of YouTube playback now runs on AV1. The catch remains encoding: with libaom it is extremely slow (20 to 50 times H.264), with SVT-AV1 practical (3 to 8 times). Older devices still need an H.264 fallback. Combining AV1 and HEVC covers over 99 percent of sessions.
Codec comparison for the web (2026)
| Codec | File size vs. H.264 | Compatibility | Use case |
|---|---|---|---|
| H.264 (libx264) | Baseline (100%) | ~99% of all devices | Universal base, fallback |
| H.265/HEVC (libx265) | 35-45% smaller | Safari/Apple native, else split | Apple environment, licensed |
| VP9 (libvpx-vp9) | 35-45% smaller | Chrome/Firefox/Edge, license-free | Web-first economical variant |
| AV1 (libsvtav1) | 50-60% smaller | All modern browsers, Safari 17+ | Best compression, with fallback |
How do you compress a video correctly with ffmpeg?
ffmpeg is the tool that lets you control format, codec, and compression precisely, without cloud, without upload, without licensed software. If you prefer working graphically, HandBrake does essentially the same. Compressing comes down to three dials: CRF for quality, preset for encoding speed, and the codec for efficiency. Whoever understands these three copes with almost any requirement.
CRF instead of fixed bitrate
CRF (Constant Rate Factor) is the most important setting. Instead of a fixed bitrate you set a target quality, and the encoder distributes bits where they are needed: more for complex scenes, less for calm ones. A lower CRF means better quality and a larger file. For H.264 the scale runs from 0 (lossless) to 51. The sweet spot for the web is CRF 18 to 28, CRF 23 is the solid default. For H.265 and AV1 the scale is shifted: CRF 28 in H.265 corresponds to about CRF 23 in H.264.
You only need a fixed bitrate when you must hit a hard file size. Then you use two-pass encoding: in the first run ffmpeg analyzes the video, in the second it encodes with optimal bit distribution. For the web, CRF is almost always the better choice.
Resolution, framerate, and preset
For most websites Full HD (1920x1080) is enough. 4K looks premium on large screens but multiplies file size, often without a visible gain. For videos embedded smaller, 720p or less will do. Never upscale, it only burns bandwidth. When downscaling, the Lanczos filter delivers the best quality.
Leave the framerate at 24 to 30 fps in most cases, more rarely pays off. The preset controls how much compute ffmpeg puts into optimizing: medium is the default and sweet spot, slow saves only a few percent for much longer encoding time. Rough bitrate orientation for H.264: 1080p around 4 to 8 Mbit/s, 720p around 2 to 4 Mbit/s. For H.265 and AV1 about half.
The concrete ffmpeg commands
Here are the commands we actually use. The first is the standard for the web: H.264, CRF 23, faststart for progressive loading.
Standard web video (H.264, universal): ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -vf "scale=1920:-2:flags=lanczos" -c:a aac -b:a 128k -movflags +faststart output.mp4
Economical variant VP9 (WebM, license-free): ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -row-mt 1 -c:a libopus -b:a 128k output.webm
Best compression AV1 (modern devices, ship with an H.264 fallback): ffmpeg -i input.mp4 -c:v libsvtav1 -crf 30 -preset 6 -c:a libopus -b:a 128k output.mp4
Silent background video without audio (hero, autoplay): ffmpeg -i input.mp4 -an -c:v libx264 -crf 24 -preset medium -vf "scale=1920:-2:flags=lanczos" -movflags +faststart hero.mp4
Extract a poster frame as a still image: ffmpeg -i input.mp4 -ss 00:00:01 -frames:v 1 -q:v 2 poster.jpg
The -movflags +faststart moves the metadata to the start of the file. Without this flag the video only starts playing once the entire file is loaded. It is not optional for the web.
How do you deliver video without killing load time?
The best encoding is useless if the video is embedded wrong. Four levers decide whether your video slows the page down or loads invisibly fast. They cost almost no effort and act directly on your Core Web Vitals.
Lazy loading and the preload attribute
A video far down the page does not need to load immediately. Set preload="none" or preload="metadata" so the browser does not pull the whole file upfront. Videos that only become visible on scroll you load lazily via IntersectionObserver. That way the video does not block the initial page render, and your Largest Contentful Paint stays fast.
Autoplay, muted, and playsinline
If a background video should play automatically, it must be muted. Browsers block autoplay with sound by default. The combination is autoplay muted playsinline loop. playsinline prevents iOS from forcing the video into fullscreen. And since the video runs silent anyway, you best encode it without an audio track at all (-an drops the audio entirely). A hero video is a design element, not a media player.
Poster frame as an instant still
The poster attribute shows a still image immediately while the video loads in the background. Without a poster the user sees an empty area, which worsens perceived loading and creates a layout-shift risk. Extract the poster frame directly from the video (see the ffmpeg command above) and serve it as an optimized JPG or WebP. On weak connections the poster is often all the user sees in the first seconds.
Adaptive streaming and CDN
A single video file never works equally well for everyone: on a weak network a 1080p file will not load, on a fast connection an over-compressed image annoys. Adaptive streaming via HLS or MPEG-DASH automatically delivers the right quality tier depending on connection and screen. For short hero loops that is overkill, for longer content videos it pays off. Either way: deliver video over a CDN, not directly from your own server. That spreads the load, shortens the path to the user, and keeps your origin server free.
Should you self-host or use YouTube and Vimeo?
The decision depends on purpose. Self-hosted video gives you full control over appearance, load behavior, and privacy: no foreign branding, no cookie banners, no external tracking calls, clean integration into the design. The price is effort: you handle encoding, multiple versions, and delivery yourself. For hero loops, short silent design videos, and anything that should belong seamlessly to the brand, self-hosting is almost always right.
YouTube and Vimeo pay off for long content videos, tutorials, or reach on the platform itself. They handle adaptive streaming and global delivery but bring foreign branding, recommendations to competitors, and in the GDPR world consent obligations. A middle ground is specialized, GDPR-compliant hosting services that automate encoding without cookie banners. For a premium B2B site where every detail should be right, we usually choose self-hosting with a clean pipeline of our own.
Does web video need to be accessible?
Yes, and since the Barrierefreiheitsstärkungsgesetz (BFSG, the German accessibility act) this is mandatory rather than optional for many companies from 2025. In practice that means three things. First: subtitles do not belong burned into the video but as a separate track (such as WebVTT) that can be toggled on and off. Second: where sound carries information, you need a transcript or audio description. Third: the player itself must be keyboard-operable and must not autoplay with sound.
For silent background loops the effort is small because they carry no information. But as soon as a video conveys content, plan subtitles and a transcript from the start, not as an afterthought. More on this in our guide to accessible websites.
What does this do for your website?
Properly optimized web video is the difference between a page that impresses with motion and one that chokes on it. A cleanly encoded, faststart-capable, lazily loaded hero video with a poster feels instant even though megabytes are flowing in the background. The same video, uncompressed and embedded blocking, ruins your Largest Contentful Paint and sends users away before they have seen anything at all.
This is exactly where we work at INSYNC: we build B2B websites with a lot of motion and video without performance suffering. Encoding pipeline, delivery, and design are created together, not one after the other. That way you get the visual impression of a high-end site and still load times that keep your Core Web Vitals green.
Frequently asked questions
In most cases MP4 with the H.264 codec. It runs on over 99 percent of all browsers and devices and offers a very good ratio of quality to file size. To save file size, add VP9 (WebM) or AV1 and ship H.264 as a fallback.
Most precisely with ffmpeg. A good standard command is: ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k -movflags +faststart output.mp4. CRF 23 controls quality, preset medium the speed, and faststart ensures progressive loading. Graphically the same works with HandBrake.
For most sites Full HD (1080p) is enough, for smaller embedded videos often 720p. As rough orientation: short hero loops ideally under 10 MB, longer clips under 50 MB in the version loaded first. More important than the raw MB figure is how fast the video starts playing.
CRF (Constant Rate Factor) is a quality-based setting: you set a target quality and the encoder distributes the bitrate variably where it is needed. A lower CRF means better quality and a larger file. For the web, CRF 23 for H.264 is the solid default, the range 18 to 28 the sweet spot.
For hero loops and short design videos that should belong seamlessly to the brand, self-hosting is almost always better: full control, no foreign branding, no cookie banner. YouTube or Vimeo pay off for long content videos and reach but bring foreign branding and GDPR consent.
Common reasons: missing -movflags +faststart (the video only starts after fully loading), no lazy loading (the whole file loads immediately), no poster attribute, and delivery directly from your own server instead of a CDN. A single oversized version without adaptive delivery also slows things down especially on mobile.
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.







