Why Big Video Files Kill the Experience
Video is a powerful way to boost engagement, but that advantage evaporates the moment playback stutters. A video that is too large or encoded at too high a bitrate demands a network connection fast enough to keep pace with playback. When the connection can't deliver, users see long startup delays and constant stalling — a surefire way to lose a customer.
The fix is straightforward: make the file smaller without visibly degrading quality. The challenge is finding the right balance, and the tools needed to get there are free and readily available.
Real-World Video Sizes: The Data Doesn't Lie
It's surprisingly easy to end up with a disastrously large video on a website, often without realizing it until it's too late. Looking at data from the December 2020 mobile HTTP Archive, it's clear that many sites default to loading enormous video files on mobile connections. Hero background videos are a common culprit, frequently delivered at sizes that simply don't make sense for the devices and networks they're served to.
One real-world example illustrates the problem perfectly. A pumpkin farm's website featured a high-quality drone video of its fields. On a desktop connection, it played beautifully. On a phone, it was nothing but an endless loop of stalling and restarting. Inspecting the network requests to that video revealed the issue immediately.
Diagnosing the Download
Looking at the media requests in the browser's DevTools, the video was being delivered in segments via 206 (partial content) responses. The response headers painted a stark picture:
accept-ranges: bytes
access-control-allow-headers: x-test-header, Origin, X-Requested-With, Content-Type, Accept
access-control-allow-methods: GET, POST, PUT, DELETE, OPTIONS
Content-Length: 87690242
Content-Range: bytes 70025216-157715457/157715458
content-type: video/mp4
date: Fri, 22 Jan 2021 15:27:26 GMT
last-modified: Mon, 24 Jun 2019 05:13:04 GMT
server: Apache
The video file's total size was over 157 MB. It's no mystery why a mobile device on a typical cellular connection couldn't handle it. To get a full view of the encoding specs, ffprobe — part of the open-source FFmpeg package — is the ideal diagnostic tool. For videos already online, a web-based version of ffprobe can analyze a URL directly.
Probing the pumpkin farm video revealed the root causes. The processing output showed two streams in a 62-second file, which is normal. But the size and bitrate were severely problematic:
The video was encoded with a bitrate of roughly 20 MBPS. For the video to play back without interruption, the network must sustain a download rate higher than 20 MBPS. On typical mobile networks, that's a near-impossible requirement.
Matching Bitrate to Network Speed
A video's bitrate is the minimum network speed your customers will need to watch it without stalling. As a general rule, the bitrate should be about 80% of the available network throughput. This means a 20 MBPS video effectively requires a connection of about 24 MBPS to play smoothly.
Common connection profiles show why this matters:
Almost every connection type listed — including mobile 4G — has a downlink speed far below 20 MBPS. To play back smoothly on a 4G connection, the video's bitrate would need to stay below 7.2 MBPS. That's the target we need to aim for.
Bringing the Bitrate Down
The ffprobe data showed the video ran at 60 frames per second (60000/1001). Typical web video runs at 25–30 fps, so the frame rate is the first lever to pull. The second is the Constant Rate Factor (CRF), FFmpeg's primary quality/size setting. CRF values range from 0 (lossless) to 50 (maximum compression), with a default of 23. In practice, CRF values between 23 and 28 still produce visually clean videos at file sizes that are far more web-friendly.
Re-encoding the original 157 MB video to 30 fps with a CRF of 23 using a simple command:
ffmpeg -i input.mp4 -vcodec h264 -acodec aac -crf 23 -strict -2 :v fps=fps=30 output.mp4
This first pass yielded an 81.5 MB file — a 48% reduction — but it still carried a hefty 10 MBPS bitrate. Increasing the CRF to 28 dropped the file further to 35.4 MB with a bitrate of 4.5 MBPS, which is much better suited for a 4G connection. That alone represents a five-fold improvement over the source file. Further gains are possible by reducing the video's dimensions, which is an important step when preparing video for streaming delivery.
Why That Pizza Page Ate 44 MB Of Data
Imagine browsing a restaurant's site on your phone while out in Los Angeles. The videos play automatically — or rather, they download even though you never press Play. You later check WebPageTest on a mobile connection and find the damage:
44 MB of video. Digging into the waterfall reveals two separate video files, and neither even finished downloading:
| Video | Size |
|---|---|
| Video 1 downloaded | 11.8 MB (of 121 MB total) |
| Video 2 downloaded | 31.1MB (of 139 MB total) |
Why so much data when nothing was playing? The answer is in the page source:
<video id="u457537-video" class="video-js vjs-big-play-centered" controls preload="auto" width="1050" height="591" poster="assets/home_poster.jpg" data-setup='{"fluid": true}'><source src="assets/home_1.mp4" type='video/mp4'> <source src="assets/home.webm" type='video/webm'><p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p> </video>
Two common mistakes stand out:
-
preload="auto"
This overrides the browser's defaultmetadatabehavior and forces the entire video file to be fetched, whether or not the visitor ever hits Play. The default setting downloads only a few hundred kilobytes. -
File order matters
When multiple encodings exist (here, H.264 in MP4 and VP8 in WebM), the browser picks the first one it recognizes. Modern browsers universally support MP4, while WebM has about 95.4% global support — yet the heavier format was listed first, guaranteeing almost every visitor downloads it.
Cheap Fixes: Order, Preload, And Framerate
A simple trick to control which video loads — or whether any loads at all on certain screens — is to insert the appropriate <source> element with JavaScript. With just an empty <video> tag in the markup, nothing can be downloaded until the script runs, as demonstrated in this approach:
window.onload = addAutoplay();
var videoLocation = document.getElementById("hero-video");
function addAutoplay() {
if(window.innerWidth > 992){
videoLocation.setAttribute("autoplay","");
};
}
Probing those two videos with ffprobe shows the problem clearly:
| Format | Size |
|---|---|
| Mp4 | 121.2 MB |
| Webm | 11.8 MB |
The WebM file is about 90% smaller yet gets zero views, because every browser defaults to the MP4. Both are 640×360 and 140 seconds long. Re-encoding the MP4 with a good ffmpeg preset, such as CRF 28 with a halved framerate, brings it down from the original size to a far more reasonable weight. The higher-resolution footage — Full HD drone shots inside the restaurant — can be compressed from 140 MB to around 35 MB the same way. Simply flipping the order so the smaller WebM comes first saves several more MB for the vast majority of browsers that support it.
Responsive Video Through Streaming
The <video> element has no media queries, so it cannot serve differently sized files to differently sized screens. One effective workaround is HTTP Live Streaming (HLS), which adapts the delivered bitrate and resolution to the device. While this adds some JavaScript, CSS, and other assets to the page, the bandwidth savings from serving appropriately sized streams quickly outweigh that fixed overhead.
You can generate HLS streams yourself with ffmpeg — there are bash scripts for this — but you will have to define every rendition's dimensions and bitrate manually. Alternatively, dedicated video APIs such as api.video or Mux accept an upload and automatically transcode it into adaptive streams at multiple resolutions (api.video currently offers 240p, 360p, 480p, 720p, 1080p, and 4K). Smaller resolutions use proportionally lower bitrates, so phones on slower networks receive leaner data and the original video size no longer determines bandwidth usage.
For the test case of a 1080p, 60 fps video originally weighing 157 MB, recompressing to 30 fps with CRF 28 brings it down to 35.7 MB. After that, streaming it yields clear data savings per device class, as shown in the totals below (including roughly 1 MB of player assets for each stream):
| Device | Video Size (Pixels) | Video Size (MB) | Bitrate (MBPS) |
|---|---|---|---|
| Moto G4 (Portrait) | 240p | 3.1 MB | 0.35 |
| Moto G4 (Landscape) | 360p | 7.5 MB | 0.800 |
| Iphone 7/7/8 (Landscape) | 480p | 12.1 MB | 1.40 |
| Ipad (Landscape) | 720p | 21.2 MB | 2.6 |
| Ipad Pro (Landscape) | 1080p | 39.4 MB | 4.4 |
At full 1080p, the stream adds a few MB of overhead over a single compressed file. At every lower resolution though, the reduction in bytes served is substantial, with no loss in playback quality for that screen. If the network degrades mid-playback, the HLS player automatically switches to a lower quality rendition rather than stalling — a redundancy you can test with a project like StreamOrNot.
Hosting on mainstream platforms like YouTube or Vimeo can achieve a similar result, but that locks you into their player, branding, and advertising scripts inside an iframe. A self-hosted stream keeps your video brand-free, which matters for background videos on product pages and other full-bleed uses where you want zero external clutter.
Treat Video Like Any Other Asset
Nobody uploads photos straight from the camera to the web — they compress, crop, and resize them first. Video deserves the same discipline. Smaller files start faster and stall less, which users experience directly as a smoother page. Start with re-encoding your source footage at a sensible quality and framerate, pick the right preload behavior, put the smaller format first, and let streaming handle delivering just the right size of video, to the right screen, on any network.



