涯丨角

通过HTML5 Video来优化动态GIF

原文链接: www.smashingmagazine.com

摘要- 网页中的动态GIF图片是非常受欢迎的,因为它们相比静态图片更生动,相比网页视频更简单。但是GIF图片通常具有较大的体积,就导致网页加载速度变慢,内存使用增加。通过使用HTML video,可以使浏览器中的GIF图片在减少98%体积的情况下,仍然具有相对较高的质量。

我们注意到这篇文章是Google Web Fundamentals上杰里米·瓦格纳 (Jeremy Wagner)的一篇文章的复写版本,原文可点击这里查看。

我对杰里米表达深深的歉意,由于我并未第一时间辨认出这是复制他的工作。审核确认一直都是我和整个团队非常重视的工作。对于这次的事件,我非常抱歉。

— 瑞秋 安德鲁 (Rachel Andrew), 代表编辑团队

动态GIF图片有很多优势:它们很容易制作并且所有浏览器都支持。但是GIF格式的设计初衷并不是为了存储动画,而是为了将多张图片压缩到单个文件中。为此用了一种无损的压缩算法 (LZW 压缩算法),来使GIF图片可以在短时间内下载,即使在较慢的连接状态下 ,也是如此。

后来,GIF文件允许内部存储的一系列的图片可以随时间展示,这才有了动画功能。当时GIF动画默认只会播放一次,在最后一帧图片展示完之后,就会停止。网景浏览器2.0 首次给动态GIF增加了循环播放的能力,这极大地促进了GIF动画的崛起。

GIF作为动画存储格式,有很大的限制。动画中的每一帧严格限制有256种颜色,多年以来,压缩技术的发展已经促进了动画和视频文件的压缩和使用。但GIF格式不同于这些传统的视频格式,不能利用这些新技术的优势,导致其几秒的内容就需要很大的空间储存,因为里面有很多重复的内容被储存。

即使你试图用一些GIF工具,像Gifsicle,来降低图片质量和动画长度,你也很难把GIF文件控制到合适的尺寸。这就是为什么像Giphy,Imgur和the likes这些有很多GIF图片的网站,不会去用GIF格式,而是把它们转换成HTML5 video呈现出来的原因。正如Pinterest的工程师团队发现的那样, 把动态GIF图片转换成video,可以减少加载时间,重放更加平滑,带给用户更好的体验。

因此,我们来看一下这些能够让我们把HTML5 video代替动态GIF的技术。我们会学到如何把GIF转换成视频文件,并且把这些视频文件合适地嵌入到网页中,让其表现出和GIF同样的效果。最后,我们会考虑一些用这项方案所可能带来的缺点。

动态GIF转换成Video

第一步是把GIF文件转换成一种视频格式。在主流浏览器中,大约有94%的浏览器都支持MP4格式的视频,所以MP4可以是一个很安全的默认视频格式选项。

Support table on caniuse.com showing browser support for the MP4 video format

  • 94%的浏览器支持MP4格式 (详情)

另外WebM格式也是一个可选项,WebM格式与MP4格式相比,具有更小的文件尺寸和更高的视频质量。然而,浏览器还没有广泛地支持这种格式,所以你不能把所有MP4文件都替换成WebM格式文件。

Support table on caniuse.com showing browser support for the WebM video format

  • IE和Safari不支持WebM (详情)

因为 <video> 标签支持多种 <source> 文件,所以我们可以把WebM视频放到浏览器中,对于不支持此格式的浏览器可以回退到MP4格式。

现在我们去把GIF转换成MP4和WebM。有一些在线的工具可以帮助我们,但是这些工具大部分都是基于ffmpeg 的,所以我们跳过这些工具,直接使用 ffmpegffmpeg 是一个免费开源的处理视频和音频文件的命令行工具。它也可以用来把动态GIF转换成视频格式。

为了确定你的机器上是否有 ffmpeg ,你需要打开终端,运行 ffmpeg 命令。这会打印出一些相关信息,如果没有,需要安装。在Windows,macOS和Linux上的安装说明可点击这里。因为我们需要转换成 WebM,所以你需要确保用 ffmpeg 打包你安装的任何东西都需要用 libvpx编译。

为了更好地执行文章的中命令,你需要准备一个超过28MB的GIF文件,或者可以用这一张。下一部分我们开始介绍如何把GIF转换成MP4。

GIF 转换成 MP4

打开终端,进入你测试GIF文件所在目录,运行下面命令,把GIF文件转换成MP4文件:

ffmpeg -i animated.gif video.mp4

运行命令后,根据你要转换的GIF文件大小,需要等待数秒,之后会在当前目录生成一个vedio.mp4的文件。命令中的 -i 表示要后面指定输入文件路径,接着要指定输出文件的路径 (本例子中vedio.mp4就是输出文件)。对一个28MB的GIF文件可以转换成一个只有536KB大小的MP4文件,在保持动画质量的前提下,有98% 压缩量。

我们可以做的还有更多。 ffmpeg 有很多选项可以让我们进一步地调节输出文件。 一种方法是用码率控制方法如CRF (Constant Rate Factor),来进一步减少输出文件大小。你需要运行如下命令:

ffmpeg -i animated.gif -b:v 0 -crf 25 video.mp4

正如你看到的,上面的命令比之前的命令多了一些新的参数。-b:v 通常是用来限制输出比特率,当用CRF模式时,它必须设置为0。-crf 用来控制输出视频的质量,可接受0 - 51之间的数值,这个值越小,则视频质量越高,文件尺寸越大。

运行上面的命令,压缩后的视频文件大小只有386KB,并且视频质量和之前的并无明显区别。如果你想进一步减少文件大小,你可以增大crf的值。需要记住,crf值越大,视频质量会越差。

GIF转换成WebM

你可以将GIF文件转换成WebM文件,运行如下命令:

ffmpeg -i animated.gif -c vp9 -b:v 0 -crf 41 video.webm

这个命令和前面介绍的转换成MP4文件的命令几乎一样,仅有的区别是有一个新参数 -c ,这个参数通常来指定进行转换的编码解码器。上面命令用 vp9 编码解码器,它是继承 vp8 编码解码器。

另外,这个命令中crf的值为41,因为不同的视频格式相同的crf值也是代表不同的视频质量。这个命令产生的WebM文件只有16KB,远小于MP4格式的文件,但是视频质量并没有明显差别。

现在我们知道如何把GIF文件转换成视频文件,接下来我们看如何在浏览器中用HTML5的 <video> 标签来模仿GIF图片的动画效果。

浏览器中用Video替换GIF

在网页中,把一个视频表现得像GIF并不是简单得把视频文件放到 <img> 标签中,但是解决方法也不复杂。动态GIF的主要特征如下:

  • 自动播放

  • 连续循环播放

  • 无声播放

既然知道了GIF文件的这些特性,那么我们可以改变视频文件的某些属性来具备这些特征。下面就展示了如何将视频文件表现出GIF的特征:

<video autoplay loop muted playsinline src="video.mp4"></video>

浏览器中的这行代码就表示这个视频是自动播放,循环播放,无声播放并且不展示任何视频控制组件。这就使网页中的视频表现出和GIF无异,同时表现出更好的性能。

你可以为视频指定更多的源,通过在 <video> 中用 &lt;source&gt; ,如下所示:

<video autoplay loop muted playsinline>
    <source src="video.webm" type="video/webm">
    <source src="video.mp4" type="video/mp4">
</video>

这些代码告诉浏览器从指定的源中去选择视频文件。在上面的例子中,如果浏览器支持WebM格式的视频,那么页面将会下载并播放,但是如果不支持,MP4格式视频会被下载并播放。

为了兼容较老的不支持HTML5 video的浏览器, 可以添加如下内容来显示原始GIF图片。

<video autoplay loop muted playsinline>
    <source src="video.webm" type="video/webm">
    <source src="video.mp4" type="video/mp4">

    Your browser does not support HTML5 video.       
    <a href="/animated.gif">Click here to view original GIF</a>
</video>

或者把GIF文件添加到 <img> 标签中:

<video autoplay loop muted playsinline>
    <source src="video.webm" type="video/webm">
    <source src="video.mp4" type="video/mp4">
    <img src="animated.gif">
</video>

现在我们已经测试了如何在浏览器中用HTML5 video模拟GIF图片,接下来我们会考虑一些这种办法可能会存在的问题。

潜在的问题

在采用HTML5 video替换GIF方案之前,我们需要考虑会产生的一些问题。很明显,GIF以方便地直接放到页面中并且不会有兼容性问题。但是对于视频文件,你需要首先对其进行编码操作,并且很难对这一流程实现自动化操作,而且视频文件存在兼容问题。

手动转换GIF并检查输出结果,可以确保输出文件在质量和大小之间保持平衡。但是对于一个大型项目,这样的步骤不具备很强的操作性。对于这样的事情,最好通过类似于 Cloudinary 这样的服务来帮助你。

另外一个问题是,不同于图片,视频文件在浏览器中并不会预加载。因为一个视频可能非常长,浏览器通常会跳过视频解析,直到主线程准备来解析视频文件内容。这就导致视频文件会有几百毫秒的延迟加载。

另外,还有一些自动播放的问题,尤其是在手机端。在安卓的 ChromeiOS Safari 浏览器中,即使视频文件不包含任何音频内容, muted 属性也是必须设置的。并且如果自动播放没被允许,在视频展示的位置,用户只会看到一片空白。举个例子,在安卓的Chrome浏览器中Data Saver模式下,即使你所有属性都设置正确,自动播放的视频也不能正常显示。

为了应对所有的场景,应该设置 poster 属性来给视频展示区域设置一个占位图,以至于在视频因为某些原因不能正确播放的情况下,仍然有有效的内容信息。在视频自动播放不被允许的情况下,需要考虑用 controls attribute 来让用户可以点击回放。

总结

通过用HTML5 video来替换GIF动画,我们让网页中的动画表现出和GIF类似的效果,同时没有损失动画的质量和性能。替换GIF是值得考虑的一件事,特别对于那些有大量GIF图片的网站。

这里列举了一些已经这样做的网站:

花费一些时间把你网站上的GIF文件转换成视频文件,可以使网页加载速度大大提升。如果你的网站没有太复杂,你只需要花费很短的时间就可以完成这些操作。