Video performance

In the previous module, you learned some performance techniques related to images, which are a widely used resource type on the web that can consume significant bandwidth if care is not taken to optimize them and take the user's viewport into consideration.

However, images aren't the only media type commonly seen on the web. Videos are another popular media type often used on web pages. Before looking at some of the possible optimizations, it's important to first understand how the <video> element works.

When working with media files, the file you recognize on your operating system (.mp4, .webm, and others) is called a container. A container contains one or more streams. In most cases, this would be the video and audio stream.

You can compress each stream using a codec. For example, a video.webm could be a WebM container containing a video stream compressed using VP9, and an audio stream compressed using Vorbis.

Understanding the difference between containers and codecs is helpful, because it helps you to compress your media files using significantly less bandwidth, which leads to lower overall page load times, as well as potentially improving a page's Largest Contentful Paint (LCP), which is a user-centric metric and one of the three Core Web Vitals.

One way to compress video files involves using FFmpeg:

ffmpeg -i input.mov output.webm

The preceding command—though as basic as it gets when using FFmpeg—takes the input.mov file and outputs an output.webm file using the default FFmpeg options. The preceding command outputs a smaller video file that works in all modern browsers. Tweaking the video or audio options FFmpeg offers could help you to reduce a video's file size even further. For example, if you are using a <video> element to replace a GIF, you should remove the audio track:

ffmpeg -i input.mov -an output.webm

If you want to tweak things a bit further, FFmpeg offers the -crf flag when compressing videos without using variable bitrate encoding. -crf stands for Constant Rate Factor. This is a setting that adjusts the level of compression, and does so by accepting an integer within a given range.

Codecs such as H.264 and VP9 support the -crf flag, but its use depends on which codec you're using. For more info, read about constant rate factor for encoding videos in H.264, as well as constant quality when encoding videos in VP9.

Multiple formats

When working with video files, specifying multiple formats works as a fallback for browsers that don't support all modern formats.

<video>
  <source src="video.webm" type="video/webm">
  <source src="video.mp4" type="video/mp4">
</video>

Since all modern browsers support the H.264 codec, MP4 can be used as the fallback for legacy browsers. The WebM version can use the newer AV1 codec, which is not yet as widely supported, or the earlier VP9 codec, which is better supported than AV1, but typically doesn't compress as well as AV1.

The poster attribute

A video's poster image is added using the poster attribute on the <video> element, which hints to users what the video contents may be before playback is initiated:

<video poster="poster.jpg">
  <source src="video.webm" type="video/webm">
  <source src="video.mp4" type="video/mp4">
</video>

Autoplay

According to the HTTP Archive, 20% of videos across the web include the autoplay attribute. autoplay is used when a video must be played immediately—such as when used as a video background or as a replacement for animated GIFs.

Animated GIFs can be very large, especially if they have many frames with intricate details. It's not uncommon for animated GIFs to consume several megabytes of data, which can be a significant drain on bandwidth better spent for more critical resources. You should generally avoid animated image formats, as <video> equivalents are much more efficient for this type of media.

If autoplaying video is a requirement for your website, you can use the autoplay attribute directly on the <video> element:

<!-- This will automatically play a video, but
     it will loop continuously and be muted: -->
<video autoplay muted loop playsinline>
  <source src="video.webm" type="video/webm">
  <source src="video.mp4" type="video/mp4">
</video>

By combining the poster attribute with the Intersection Observer API you can configure your page to only download videos once they are within the viewport. The poster image could be a low-quality image placeholder, such as the first frame of the video. Once the video appears in the viewport, the browser begins downloading the video. This could improve load times for content within the initial viewport. On the downside, when using a poster image for autoplay, your users receive an image that is shown only briefly until the video has loaded and begins playing.

User-initiated playback

Generally, the browser begins downloading a video file as soon as the HTML parser discovers the <video> element. If you have <video> elements where the user initiates playback, you probably don't want the video to begin downloading until the user has interacted with it.

You can affect what is downloaded for video resources by using the <video> element's preload attribute:

  • Setting preload="none" informs the browser that none of the video's contents should preloaded.
  • Setting preload="metadata" only fetches video metadata, such as the video's duration and possibly other cursory information.

Setting preload="none" is likely the most desirable case if you're loading videos that users need to initiate playback for.

You can improve the user experience in this case by adding a poster image. This gives the user some context on what the video is about. Additionally, if the poster image is your LCP element, you can increase the poster image's priority using the <link rel="preload"> hint along with fetchpriority="high":

<link rel="preload" as="image" href="poster.jpg" fetchpriority="high">

Embeds

Given all the complexity in optimizing and serving video content efficiently, it makes sense to want to offload the problem to dedicated video services such as YouTube or Vimeo. Such services optimize the delivery of videos for you, but embedding a video from a third party service can have its own sort of effect on performance, as the embedded video players can often serve a lot of extra resources, such as JavaScript.

Given this reality, third-party video embeds can significantly impact page performance. According to the HTTP Archive, YouTube embeds block the main thread for more than 1.7 seconds for the median website. Blocking the main thread for long periods of time is a serious user experience problem that can impact a page's Interaction to Next Paint (INP). However, you can strike a compromise by not loading the embed immediately during the initial page load, and instead create a placeholder for the embed that is replaced by the actual video embed when the user interacts with it.

Video demos

Test your knowledge

The order of <source> elements inside of a parent <video> element does not determine which video resource is ultimately downloaded.

True.
False.

The <video> element's poster attribute is considered an LCP candidate.

False.
True.

Up next: Optimize web fonts

Next up in our coverage of optimizing specific resource types is fonts. Optimizing your website's fonts is something that is often overlooked, but can have a significant impact on your website's overall load speed, and metrics such as LCP and Cumulative Layout Shift (CLS).