Motion and video

Video for the web: weight, speed and the decision that comes first

Video is the heaviest thing you can put on a page, so the first decision is not compression but whether this page needs video at all. If it does, there are four real levers: encoding it properly, matching the resolution to the display size, using a poster instead of preloading the file, and hosting the file somewhere other than the server that serves your HTML.

  • Lesson 7 of 10
  • Intermediate
  • Free, no signup

The four levers that take video off the load path

The Lighthouse performance score runs 0 to 100, and its green band starts at 90.

0 100
90+the lower edge of Lighthouse green
  • Encode properlyNo attribute on the tag compensates for a badly encoded file.
  • Resolution to fit the frameA 1080-pixel file in a frame that is 360 pixels wide on a phone is bytes thrown away.
  • Poster instead of preloadThe poster is itself an LCP candidate, so it has to be compressed.
  • Host away from the HTMLA long video on shared hosting is where the decision breaks.

The Lighthouse score is a lab measurement and holds no user behaviour. A page whose video is never clicked scores well and says nothing about the experience of the person who clicks.

Last checked: Facts and tool names in this lesson are re-checked against their sources on this date.

Does this page need video at all?

Our position: most business pages should not autoplay video, and many of them should not carry video at all.

That comes from an agency that makes and sells video, which is exactly what makes it worth trusting. A page with a background video has pulled megabytes and put the visitor's processor to work decoding frames before they have read a single word. If that video says something the text and the image cannot, the cost is right. If it is atmosphere, it is not.

Three questions, in this order, settle it. First, what does this video show that a still and two sentences do not; if the answer is movement, like a demo or a process, video is correct. Second, does the visitor want it or do we want it; someone who came to see prices does not want the company introduction film. Third, what is lost if it never plays; if the answer is nothing, the video is decoration.

On this site, those three questions took us to a place where the theme does not contain a single video tag and every figure is drawn with HTML and CSS. We sell video, and our own video lives somewhere else, not in the load path of the pages that sell.

A webpage frame sinking under a heavy glass video block beside a small green poster frame

What does this video show that a still image and two sentences do not?

Answer: movement

Video is the right call

  • A product demo or a step-by-step process
  • Something that changes and a photo cannot hold
  • A testimonial, where tone is part of the message
  • Give it a poster, set preload to none, play on click
Answer: atmosphere

Take the video out

  • A hero background video nobody watches
  • The company film on the pricing page
  • A short looping animation: use a silent looping video instead
  • Any video where nothing is lost if it never plays

Where exactly does video hit page speed?

In two places, and only one of them is the one everybody thinks of.

The first is weight, and it is familiar: the bytes being downloaded compete for the same bandwidth as the rest of the page, and on mobile over an average connection the video wins that competition because it is bigger. The second is less known and matters more: the video itself can be the page's LCP element. The web.dev documentation lists the video element as an LCP candidate, and for it whichever comes first is used: the poster image load time or the first frame presentation time.

Which means that if the biggest thing above the fold is a video, the metric Google measures as page experience is tied to it. The threshold web.dev gives for a good LCP is 2.5 seconds or less, at the 75th percentile of loads, and anything over 4 seconds counts as poor.

The practical consequence is two lines long. If the video does not autoplay, always give it a poster, because then an optimised image sits on the LCP path instead of a video download. And if that poster is the largest element on the page, web.dev suggests raising its priority with fetchpriority="high".

One trap shows up constantly: a poor poster, or a poster that is itself several hundred kilobytes. A poster is an ordinary image and it obeys the same optimisation rules; if you do not compress it, all you have done is move the problem.

Which video tag settings actually matter?

Four of them, and the biggest effect belongs to the one that gets set least often: preload.

preload valueWhat the browser doesWhere it is right
noneNone of the video is preloadedA video the user has to click
metadataOnly file information such as length is fetchedThe default MDN advises
autoThe whole file may be downloaded even if never playedAlmost nowhere on a sales page

The web.dev video chapter says preload="none" outright for playback the user initiates. That single attribute takes the heaviest download on the page out of the load path.

The poster is the second. MDN says that without a poster nothing is displayed until the first frame is available, and then that first frame is shown as the poster; so with no poster you either have an empty rectangle or you are forced to fetch the file earlier.

Autoplay is the third and is more a decision than a setting. web.dev writes that autoplay should only be used when necessary and as the result of an anticipated need for the user. MDN also notes that modern browsers block autoplay for video with an unmuted audio track, so an autoplaying video with sound will in practice not play at all.

And GIF replacement is the fourth, the one place where autoplay is almost always right. If you want a short looping animation, use a silent video with autoplay, muted and loop instead of a GIF. For exactly this case web.dev suggests stripping the audio stream entirely with ffmpeg's -an flag, because removing the audio stream reduces the file size.

One point that does not make the checklists: these four settings do nothing for a badly encoded file. Bring the resolution down to what is actually displayed; sending a 1080-pixel file into a frame that is 360 pixels wide on a phone is not something any of these attributes compensates for.

Where should the file live: your server or a platform?

Both choices are valid and they are for two different situations; what separates them is control against load.

When you serve the file yourself, everything is yours: no one else's player, no extra script, no logo and no suggested next video, and no visitor data going anywhere else. The cost is equally clear: bandwidth and traffic come out of the same server that serves your HTML, and a long video on shared hosting is where this decision breaks.

When you use a platform, they carry the load and you get adaptive streaming and multiple quality renditions for free. In exchange a third origin joins the page with its own script, the look of the player is not yours, and whatever happens inside that player follows that service's rules.

The rule we use is simple: anything shorter than about ten seconds that is decorative or demonstrative goes as our own file with muted autoplay; anything long, that someone sits down to watch, goes to a platform behind a poster image and lazy loading, so the player script only arrives after a click.

And one technical trap that hits both: putting video inside a page that is itself page-cached. The video file does not come from the HTML cache and has its own path, so the speed score a tool gives you may not reflect the video at all. So after every change, open the page once with throttled network in your browser's developer tools and watch what is actually downloaded.

Your own file or a platform: control against load

The file on your own server

  • No third-party script and no third origin joins the page
  • The player look and what happens at the end are yours
  • Bandwidth comes out of the same server that serves the HTML
  • Right for short, silent, looping clips

Hosted on a platform

  • Adaptive streaming and quality renditions, with no extra work
  • The bandwidth load comes off your server
  • Push the player script back with lazy loading
  • Right for long video someone sits down to watch

Neither is better than the other; the length of the video and the capacity of the host decide, not taste.

What does a score of 90 mean, and what does it not say?

The Lighthouse performance score runs from 0 to 100, and Chrome's own documentation puts the bands like this: 0 to 49 is poor, 50 to 89 needs improvement, and 90 to 100 is good. The number we target is the lower edge of the green band, which is 90.

Now for what the score does not say, which matters more than the score. Lighthouse is a lab test: one run, on a simulated device, over a simulated network. Your real users are on different phones and different networks, and that shows up in field data, not in this number.

For video the gap is wider than usual, because user behaviour is part of the equation. A page whose video is preload="none" scores beautifully in the lab, because nobody clicks. The real experience of the person who does click is not in that score at all.

So read the score as an alarm, not a target. Under 90, something on the load path needs looking at. Over 90 only means the load path is clean; how long the video takes to start after a click is something you measure separately. If you want to see where all of this sits inside a speed project, site speed optimisation explains the process.

The fast path, with AI

The fast path here is not asking a model how to make video lighter. It is running ffprobe first to get the real inventory of the page's video files, then handing that inventory to the model together with the page's budget so it returns one concrete decision and one ready command per file. What separates this from asking directly is that the model stops guessing: the numbers are in front of it.

  1. Take an inventory. For each video file on the page, read the resolution, duration, bitrate and size with ffprobe in one line. That table usually makes half the decision on its own.
  2. Measure the real display width. In the browser developer tools, look at the width of the video box on mobile and on desktop. That number sets the target resolution, not whatever the source file happened to be.
  3. Hand the table and the budget to a model with the recipe below. The output is one row per file: keep or drop, target resolution, and whether the audio is needed at all.
  4. Run the encode commands, pull the poster out of the output file itself, and write the tag with the right poster and preload. Then open the page with a throttled network and see what actually downloads.

Copy-ready recipe

# All four commands were run and their output checked on this server with ffmpeg 6.1.1.

# 1. Inventory: resolution, duration, bitrate and size of each file
for f in *.mp4 *.mov; do
  echo "== $f"
  ffprobe -v error -show_entries stream=width,height,codec_name \
    -show_entries format=duration,bit_rate,size -of default=nw=1 "$f"
done

# 2. The web version. The number after scale is the target height; -2 lets
#    the width be computed and kept even. A higher crf means a smaller
#    file and lower quality.
ffmpeg -i source.mov -vf "scale=-2:720" -c:v libx264 -crf 26 -preset slow \
  -profile:v high -pix_fmt yuv420p -c:a aac -b:a 128k \
  -movflags +faststart web.mp4

# 3. GIF replacement: silent and lighter
ffmpeg -i source.mov -an -vf "scale=-2:720" -c:v libx264 -crf 28 \
  -preset slow -pix_fmt yuv420p -movflags +faststart loop.mp4

# 4. The poster, taken from the output file and not from the source
ffmpeg -ss 2 -i web.mp4 -frames:v 1 -q:v 3 poster.jpg

# 5. The decision prompt, for a strong model

Role: web performance engineer. The table below is the video inventory of a page.
Goal of the page: {e.g. a sales landing page, LCP under 2.5 seconds}
Real width of the video box: {e.g. 360px on mobile, 720px on desktop}
What each video does: {one line per file}

ffprobe table:
{paste the output of step 1 here}

Give one row per file with these columns:
1. File name
2. Keep / remove / replace with a still image, and why in one sentence
3. Target resolution, based on the real box width and not on the source file
4. Is the audio needed? If not, write -an
5. Is autoplay allowed? Only if it is silent, looping and short
6. The preload value, and whether a poster is required

Rules:
- Never write a size or bitrate that is not in the table, and guess no numbers.
- Do not promise savings as a percentage. If you give a number, say which
  row of the table it came from.
- If a file does not fit the goal of the page at all, put remove in column
  two and do not go looking for a setting.
- At the end, list the files putting the most bytes on the load path, in order.

Before you trust the output: Two things you have to look at yourself. First, quality: a crf number is a setting and not a guarantee, and on footage with heavy grain or gradients the same number gives a worse result. View the output at full size on the page it will actually appear on, not in a small preview. Second, audio: the -an flag removes the sound completely and is not reversible; if it later turns out that clip needs voiceover, you go back to the source. And as always, check any saving the model quoted against your own measurement, because the only number that counts is the one that came out of your actual file.

AI in this kind of work

In video optimization, AI does nothing exotic, and that is the good news. What it actually does is translate: from tool output into a decision, and from a decision into a command. The compression itself is done by ffmpeg, which is free and deterministic, and no model replaces it. Our position: bring a model in for the decision step and not for the execution step, because the right tool for execution already exists.

Tools that actually help

  • Gemini Economical for the first pass over ffprobe output and a speed report, because that work is mechanical and reviewable: sorting the table and finding the heaviest files. Iran is not on Google's supported-country list; the payment layer is on this site's buying-AI page.
  • Claude Better for the decision step, where the answer is that a file should not be on the page at all. It is less inclined to offer a setting when the correct answer is removal. Iran is not on Anthropic's supported-country list.
  • ffmpeg Not AI, and in this list on purpose: it does the thing everyone is looking for, free, local and with no upload. A model only writes its command line. The web.dev documentation points straight at this tool for stripping the audio stream.

Where it backfires

The main risk on this topic is the numbers models state with total confidence about size reduction. "This setting cuts the size by around forty percent" is a sentence that looks like an answer and came from no measurement of your file; the real reduction depends on the content of that video, and a detailed scene and a static scene give wildly different results from one setting. That is why the recipe above explicitly forbids writing any number that is not in the table. The second risk is ffmpeg command lines a model composes that quietly do the wrong thing: a flag that has no effect in that position, a filter that does not match the chosen codec, or a flag that re-encodes when the intent was to copy. These do not error; they just produce something that looks correct. Always check the output file's size and dimensions with ffprobe. And a third risk goes back to privacy: uploading client footage to an online compression service is the same decision described in the editing lesson and it still applies here, while ffmpeg needs no upload at all.

Sources: web.dev: video performance Chrome for Developers: Lighthouse performance scoring Anthropic: is my data used for model training

Where this advice stops

This lesson is about short video on ordinary pages: a demo, a promo, a testimonial, a looping animation. If your business is long-form video, video courses or paid content, that is a different problem with different answers: adaptive streaming, multi-bitrate packaging and access control, none of which this page covers. One more honest limit: nothing here saves a video nobody wants to watch. An optimised file that no one plays is still the wrong decision, just a lighter one.

From our own work

One setting that almost no serious guide bothers with makes the biggest difference to how fast playback starts: -movflags +faststart. An MP4 is built from blocks and the moov block is the file's map; if it sits at the end, the browser has to fetch most of the file before it knows how to play it. On this server, with ffmpeg 6.1.1, we produced two outputs and read the block order: without the flag it came out ftyp, free, mdat, moov, and with it ftyp, moov, free, mdat. The map moved from the end of the file to the front. This is something you can test on your own file in thirty seconds, and it is where you find out that a video slow to start after a click is not necessarily a heavy one.

Real follow-up questions

For the web, is MP4 or WebM better?

If you are producing only one file, MP4 with H.264 is the one that plays in the most places without trouble. If you want it lighter without losing compatibility, you can put two sources inside one video tag and let the browser take the first it recognises. The difference between them lives in codec detail, and the video formats and codecs lesson is where that sits.

Is a background video in the hero section a problem?

The problem is that it puts the heaviest thing on the page exactly where LCP is measured, and usually gives no information in return. If you still need it, at least make it silent, short and looping, strip the audio stream, and give it an optimised poster so the page is not empty if it never plays. But the honest answer in most cases is that a good image does the same job at a fraction of the cost.

How do you lazy load a video?

For your own file, preload="none" does most of the work: the browser fetches nothing of the video until someone starts playback. For a video on a platform, the issue is not the file but the player script; the usual approach is to place a poster image instead of embedding the player directly, and load the player only after a click on that image.