How to put video at the top of a page without making visitors wait

MJ

Mateusz JanotaCEO & Founder

There is a category of site where the product is motion. A DJ, a venue, a production studio, a gym, a band. Show a photograph and you are describing the thing. Show three seconds of the room and you are the thing.

Which is why "put a video in the hero" keeps getting asked for, and why it keeps going wrong. The usual result is a first screen that makes every visitor wait for it, scores badly for the wait, and turns the strongest asset on the site into the reason the page feels slow. The fix is not a smaller file. It is not a file at all.

Why one file makes everybody wait

Drop a single MP4 into the hero and one encode is responsible for every visitor. That is an impossible brief:

  • Encode it for a desktop monitor and a mid-range Android on train LTE waits, then waits some more, then sees something.

  • Encode it for the phone and the footage looks thin on the screens where it had the best chance of landing.

  • Either way the browser has to buffer a meaningful chunk before playback feels safe to start, and it pulls that chunk from the top of the file, at full quality, whether or not the connection can sustain it.

That third point is the problem. With one file, the moment a visitor first sees motion was fixed at encode time by somebody who had never met their connection. Everybody is charged the same admission in seconds, and the people on the worst connections are charged it for longest.

Resolution, bitrate, duration: every knob you can turn on a single file is a trade between two groups of visitors. Adaptive streaming removes the trade instead of resolving it.

What adaptive delivery is

Instead of one file you produce a ladder: the same footage encoded several times, from a small low-bitrate rendition up to full HD. Each rendition is cut into segments of a few seconds, and a playlist file, an .m3u8 under HLS, describes what exists.

Building the ladder is an FFmpeg job, and it belongs in your build or asset pipeline rather than in a request handler: it runs once per clip, not once per visitor. The DJ portfolio we built for Seweryn Durczok encodes its own rungs at deploy time, from the same event footage the whole site is selling.

At playback time the player does something a plain <video> tag cannot: it measures real throughput as segments arrive and picks the rendition for the next one accordingly. On a weak connection the behaviour is not "buffer for six seconds", it is "drop to a lower rung and keep playing".

Three things follow:

  • Playback starts on a low rung, so the first frame is never far away. The visitor waits for one short segment, not for a file. Quality climbs afterwards, as the player learns what the connection can sustain, and nobody notices the first two seconds being softer the way they notice a hero that has not started yet.

  • It goes down as well as up. Mobile bandwidth is not merely low, it is uneven. A player that only climbs stalls the first time somebody walks into a lift, and a stall mid-hero reads worse than a slow start, because the page has already promised motion and then taken it away.

  • Only watched segments are fetched. Somebody who scrolls past after three seconds has fetched three seconds, not the head of a 1080p master. Nothing is queued in front of the frame you actually want.

The poster owns the first paint

The stream gets the first frame close but cannot get it to zero, because even a fast first segment is a network round trip away. The hero needs a poster image to hold the screen for that round trip, and that poster is almost certainly your Largest Contentful Paint element, the thing your page speed is measured on. It is not a placeholder for the video. Treat it as the first paint it is:

  • Serve it as AVIF or WebP with a JPEG fallback, sized for the viewport rather than once for the largest screen you support.

  • Do not lazy-load it. It is above the fold and it is the LCP candidate, and loading="lazy" on it is the most common way teams push out their own LCP by a second.

  • Keep the video payload lazy instead. The poster paints, the stream starts, and the handover happens when the first segment is decodable.

  • Match the poster to the first frame. If they differ visibly, the handover reads as a glitch rather than as playback beginning.

Get the ordering right and the video stops competing with your Core Web Vitals, because the measured element is an image you fully control and the stream arrives behind it rather than in front of it. The visitor gets picture, then motion, instead of nothing and then everything at once.

The poster is also the whole hero for two groups of visitors who told you in advance that they do not want the video. Both signals are cheap to read and routinely ignored:

  • prefers-reduced-motion is an accessibility request, not a preference toggle. Honour it by showing the poster and not autoplaying.

  • Save-Data, and the reduced-data preference where it is available, says the visitor is on a connection or a plan where your hero is not the priority. Fetched segments are paid for by somebody, and a visitor who has asked you not to spend their allowance has asked in as many words. Serve the poster and offer play as an explicit choice.

Safari and everything else

Safari and iOS play HLS natively. Point a <video> element at the .m3u8 and it works, with the platform's own adaptive logic. Everything else needs a JavaScript player, HLS.js being the standard choice, which uses Media Source Extensions to feed segments to the video element itself.

So: feature detect native HLS support first, use it where it exists, and load the player library only where it does not. Loading it unconditionally ships a payload to iOS users whose browser was never going to need it, and puts that payload on the critical path in front of a hero whose entire point was to start quickly.

When it is worth it

Not everywhere. A three second loop of an abstract gradient does not need a bitrate ladder, it needs to be a smaller file or an animation.

It is worth it when the footage is the argument: when a visitor deciding whether to book you is deciding on the basis of what the room looks like. Then the video is not decoration that has to justify its weight. It is the page, and the only defensible wait for a page is however long the network needs and not one second more.

Worth doing does not always mean worth building yourself. A video platform will produce and host the ladder for you, and everything above it, the poster, the deferred player, the reduced-motion path, stays your job either way. That is the route we took on the iShots Wedding site, where the showreel is the entire pitch and the encoding was never going to be the interesting part.

Have a project in mind?

Message us

Let's talk about how we can help bring your ideas to life.

Zanek

Can't keep up with changes in AI world?

Let us do the heavy lifting. Every week we distill the most important AI developments into a focused 5-minute briefing - so you stay ahead without the noise.

Find out more
Weekly AIonline