视频懒加载技术详解
与图片元素类似,视频也可以实现延迟加载。视频通常通过 <video> 元素加载,而对于托管在YouTube等其他服务上的视频,则可能需要使用 <iframe>(在这种情况下,请参阅关于iframe延迟加载的文章)。
<video> 元素的延迟加载方法因存在多种不同解决方案而有所不同,具体取决于您的使用场景。
非自动播放视频场景
通常建议避免视频自动播放,以便用户能够控制视频播放。在这种情况下,最好的方法是在 <video> 元素上指定 preload 属性,以避免浏览器加载整个视频文件。
<video controls preload="none" poster="placeholder.jpg">
<source src="video.mp4" type="video/mp4">
</video>
在上面的示例中,我们将 preload 属性值设为 none,以防止浏览器预加载任何视频数据。poster 属性为 <video> 元素指定了一个占位图,在视频加载期间占据空间。
大多数浏览器中,preload 默认设置为 metadata,会使用 Content-Range 头部预加载部分视频数据。这可能导致下载的数据量超过实际需要,特别是在浏览器不支持 Content-Range 头部的情况下。即使支持,浏览器也可能无法知道元数据存储在哪些字节中,因为它们可能不在文件开头。因此,我们建议使用 preload="none" 来避免视频预加载。
您还可以使用 onmouseenter 属性(或等效的 mouseenter 事件处理程序)进行扩展,在用户将鼠标悬停在视频上时预加载元数据:
<video controls
preload="none"
poster="placeholder.jpg"
onmouseenter="this.preload='metadata'">
<source src="video.mp4" type="video/mp4">
</video>
这不仅减少了用户播放视频时的延迟,还能立即显示视频时长信息。
视频可能符合LCP候选元素的条件。由于海报图片比视频加载更快,如果视频是LCP候选元素,应使用海报图片,并通过 fetchpriority 属性设置为 "high" 进行预加载。
作为GIF动画替代方案
自动播放视频最常用于实现GIF风格的快速动画。虽然动画GIF被广泛使用,但与视频相比,特别是在文件大小方面存在一些劣势。动画GIF可能会扩展到数MB的数据,而画质相当的视频文件通常要小得多。
使用 <video> 元素替代动画GIF并不像使用 <img> 元素那么简单。动画GIF具有以下三个特征:
- 加载后自动播放
- 连续循环播放(不一定总是如此)
- 没有音轨
在 <video> 元素中实现这些特性的代码如下:
<video autoplay muted loop playsinline>
<source src="video.mp4" type="video/mp4">
</video>
autoplay、muted 和 loop 属性的功能如其名称所示。playsinline 在iOS设备上实现自动播放是必需的。这样就获得了一个跨平台工作的视频替代GIF的方案。那么如何实现延迟加载呢?
首先,根据需要修改标记:
<video autoplay muted loop playsinline poster="placeholder.jpg" class="lazy">
<source data-src="video.mp4" type="video/mp4">
</video>
我们添加了 poster 属性,该属性允许指定一个占位图,在视频延迟加载期间占据 <video> 元素的空间。与延迟加载示例类似,我们将视频URL存储在每个 <source> 元素的 data-src 属性中。
接下来,使用基于Intersection Observer的图像懒加载示例类似的JavaScript代码:
document.addEventListener("DOMContentLoaded", function() {
var lazyVideos = [].slice.call(document.querySelectorAll("video.lazy"));
if ("IntersectionObserver" in window) {
var lazyVideoObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(video) {
if (video.isIntersecting) {
for (var source in video.target.children) {
var videoSource = video.target.children[source];
if (typeof videoSource.tagName =<span class="highlight"> "string" && videoSource.tagName </span>= "SOURCE") {
videoSource.src = videoSource.dataset.src;
}
}
video.target.load();
video.target.classList.remove("lazy");
lazyVideoObserver.unobserve(video.target);
}
});
});
lazyVideos.forEach(function(lazyVideo) {
lazyVideoObserver.observe(lazyVideo);
});
}
});
延迟加载 <video> 元素时,需要遍历所有子 <source> 元素,将其 data-src 属性更改为 src 属性。然后调用元素的 load 方法触发视频加载,此时媒体将根据 autoplay 属性自动开始播放。
这种方法提供了模拟GIF动画行为的视频解决方案,同时不会产生动画GIF那样的大量数据使用,并且可以对内容进行延迟加载。
懒加载库推荐
以下库可以帮助您实现视频延迟加载:
- vanilla-lazyload 和 lozad.js 是非常轻量的选项,仅使用Intersection Observer。因此性能非常出色,但在旧版浏览器中需要使用polyfill
- yall.js 是一个使用Intersection Observer并具有事件处理程序回退的库。还可以使用
data-poster属性延迟加载视频的海报图像 - 如果需要React特定的延迟加载库,可以考虑 react-lazyload。它不使用Intersection Observer,但为React应用程序开发人员提供了熟悉的图像延迟加载方法
这些延迟加载库都有详细的文档,提供了丰富的标记模式来应对各种延迟加载场景。
正在加载评论...