使用视频(video)替换 GIF 动画

英文原文:https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/replace-animated-gifs-with-video/

不知道你是否在开发者工具看过类似于 Imgur 或 Gfycat 服务中的动画 GIF,是否发现一些 GIF 就是一个动画(video)?这是有理由的。动画 GIF 很可能是巨大的。 根据质量、帧速度和长度,GIf 大小能达到几兆字节。如果你在尝试提高网站的加载速度和帮助用户减少数据,动画 GIF 与此相互冲突。

Chrome 开发者工具显示网络加载了一张 13.7MB 的 GIF 图 1:Chrome DevTools 显示一个 13.7MB 的 GIF,这比大多数的网站都大!

高兴的是,这是加载性能的一方面,你只需付出一点工作就获取巨大的收益,却没有降低质量。在这篇文章中,你将学习以 GIF 为主的网站防止它们的宽带费用突破承受能力, 并将这些巨大的 GIF 转化为小而快的视频文件!你将学习怎样正确的在网站中嵌入这些视频,并使其看起来就像 GIF 一样。最后,我们谈论一些 GIF 和视频的解码性能。 在你了解它之前,你将能够缩减几兆字节在以 GIF 为主的网页上!

#将动画 GIF 转化为视频

有多种方法将 GIF 转化为视频,但是在改教程中我们使用 ffmpeg。你需要先安装 ffmpeg,然后在命令行中运行 ffmpeg 指令。 如果已安装,你将看到一些诊断信息。如果你看到 "command not found" 或者其它相似的错误,你需要安装它。在不同的平台安装

  1. macOS,你可以使用 Homebrew 或者自己编译
  2. Windows, 使用 Chocolatey
  3. Linux, 请检查你的首选包管理器(例如 apt-get 或者 yum)是否包含可选的包

    因为我们转化的格式中包含 WebM,你需要确定 ffmpeg 使用 libvpx 编译。

ffmpeg 安装成功后,选择一个 GIF 图片,你就可以开始了。为了该教程的目的,我选择了这个 GIF,这张图片只有 14MB。开始,让我们开始着手将一个 GIF 转化为 MPEG-4!

#将 GIF 转化为 MPEG-4

当你在页面上嵌入视频,你总是希望有一个 MPEG-4 格式版本,因为浏览器广泛支持 MPEG-4 格式。开始做,打开一个命令行窗口, 跳转到测试 GIF 所在的目录,然后尝试这个命令:

ffmpeg -i input.gif output.mp4

这是 GIF 转化 MPEG-4 最简单的语法。-i标记代表着输入(input),而且说明了输出文件。这条命令将我们的测试 GIF(14,024KB) 缩小为质量相当高的大小为 867KB 的 MPEG-4 视频,这缩减了 93.8%。还算可以,但是你可能好奇想看看更小的未来。如果好奇,就接着读下去!

ffmpeg 是超可配置的,我们可以利用这个优势通过采用称为恒定速率因子(或 CRF)的编码模式进一步微调视频输出。 当视频质量成为高优先级时 CRF 设置非常好。

ffmpeg -i input.gif -b:v 0 -crf 25 output.mp4

这条命令与之前的非常相似,仅仅有两处不同:-b:v 标记一般会限制输出比特率, 但是当我们想要使用 CRF 模式时,它必须设置为 0-crf 标记接受位于 050 之间的值。小的值代表着高质量(但更大)视频,更高的值得到更低的质量。

使用我们的测试 GIF,这条命令输出了大小为 687KB 的 MPEG-4 视频。这样大约又改善了 20%!如果你想要更小的文件,你可以设置更高的 CRF 值。 只是更高的值会输出较低质量的视频,因此总是检查转码器的输出以确定是你满意的结果!

不管怎样,这两条命令大幅度减少相比 GIF 的文件大小,相反的这将缩减网页初始加载时间并减少数据使用。虽说相比于 GIF 显示的视频质量有所下降,但缩减文件大小是明智的。

GIF 动画与以 CRF 值为 25 编码的 MPEG-4 视频相对比 图 2:GIF 动画与以 CRF 值为 25 编码的 MPEG-4 视频相对比

虽然上图不能代替全面的视觉比较,但 MPEG-4 肯定足以作为动画 GIF 替代品。还要记住,您的用户可能不会像您一样参考 GIF 来源。 始终遵守项目的媒体质量标准,但愿意在适当的情况下进行权衡。

MPEG-4 是在现代浏览器中广泛兼容,当然适合作为动画 GIF 替换,我们可以去进一步了解一些关于产生 WebM 源。请继续阅读以了解更多!

#将 GIF 转换为 WebM

直至今天 MPEG-4 依然还在发展,虽然[它在 1999 年就开始存在][mpeg-4 date],而 WebM 相比较新是在 2010 年发布的。 虽然 WebM 在浏览器上的支持没有 MPEG-4 全面,但是它的表现依然很好。因为 video 元素允许你包含多个 source 元素,你可以使用 WebM 作为首选项,作为大部分浏览器支持,当浏览器不支持时可以回退支持 MPEG-4 源。

尝试在命令行使用 ffmpeg 转化测试 GIF 为 WebM:

ffmpeg -i input.gif -c vp9 -b:v 0 -crf 41 output.webm

你将发现这与之前使用 CRF 模式转化上面的 GIF 为 MPEG-4 的命令大致相同,但有两处不同:

  1. 我们使用的 -c 标签中指定的是 vp9 WebM 格式使用的 VP8 编解码器的后继者。如果这对您失败,请替换 vp9vp8
  2. 由于 CRF 值不会在格式之间产生相同的结果,因此我们需要对其进行调整,以使我们的 WebM 输出在视觉上类似于 MPEG-4 输出。设置 -crf 的值 41 在这个例子中是用来实现与 MPEG-4 版本相当质量,同时仍输出更小的文件。

在这个例子中,611KB 的 WebM 版本比 MPEG-4 版本小了 66KB。它的视频质量也与 MPRG-4 相似。

CRF 值为 25 的 MPEG-4 编码版本与 CRF 值为 41 的 WebM 编码版本对比 图 3:CRF 值为 25 的 MPEG-4 编码版本与 CRF 值为 41 的 WebM 编码版本对比

由于 VP8 和 VP9 编解码器编码视频的不同,WebM 中的压缩伪像可能会以与 MPEG-4 不同的方式影响结果的质量。与往常一样,检查编码器输出并试用不同标志(时间允许)以找到适合你应用的最佳结果。

如果你喜欢捣鼓,可以考虑尝试两种编码,看看哪种结果你更喜欢!

现在我们知道了如何将 GIF 转化为 MPEG-4 或者 WebM,让我们学习如何使用 <video> 替换 GIF 动画元素 <img>

#使用 <video> 元素替换 GIF 动画元素 <img>

不幸的是,使用视频替换 GIF 动画不像从 <img> 元素删掉图片 URL 那样简单。使用 <video> 有一点复杂,但不是特别难。 我们将一步一步实现并说明每个方面,但如果你仅仅想看代码,请查看CodePen示例。

#保持相似的行为

GIF 动画有三个特征:

  1. 它们默认播放。
  2. 它们连续循环(通常是这样,但也可以是不连续循环的)。
  3. 它们是静默无声的。

这是使用 GIF 动画相比视频仅有的优势。在使用 GIF 的时候我们不必描述这些特征。它们的行为如同我们期望的那样。但我想要使用视频替换 GIF 时,我们需要明确告知 <video> 元素默认播放、无限循环和无声。我们可以这样书写 <video> 元素:

<video autoplay loop muted playsinline></video>

在例子中这些属性是明确的。一个 <video> 元素使用这些属性将自动播放、无限循环、无声播放并且内嵌播放(不是全屏)。总的来说,所有的行为都是在模仿 GIF 动画。

如果忠实地模拟动画 GIF 行为对您的应用程序并不重要,那么您可以通过允许用户启动播放而不是自动播放来采取更保守的方法。如果您选择此路线,请删除该 autoplay 属性,并考虑通过该 poster 属性指定占位符图像 。此外,使用 controls 属性允许用户控制播放,并添加 preload 属性以控制浏览器预加载视频内容的方式。

简单模拟 GIF 行为,还有更多更多要做的事,为了自动播放还有一些必须的属性才能工作。举例来说,就算你的视频不包含声音,为了自动播放 muted 属性也是必须设置的。在 IOS 上,必须设置 playsinline 属性自动播放才能工作。

#定义 <source>

剩下的就是定义视频源。<video> 元素必须设置一个或多个 <source> 子元素,以提供不同的视频文件给浏览器选择适合的。

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

浏览器不会猜测哪一个 <source> 是最优的,如此 source 的顺序很重要。举例来说,如果你将 MPEG-4 定义为第一位,就算浏览器支持 WebM, 浏览器也会跳过 WebM 的 source 而选择使用 MPEG-4。如果你的首选是它,请将 WebM 的 <source> 放在第一位!

现在我们知道了怎样将 GIF 转化为 视频并知晓如何使用视频替换 GIF,让我们看看这些在浏览器中的良好表现吧。

#视频和 GIF 动画的表现

虽然较小的资源是可取的,但文件大小不能代表一切。我们还需要了解媒体资源在下载后的执行情况,因为媒体资产必须在播放前进行解码。

GIF(和其他动画图像格式)不是最理想的,因为图像中的每一帧都会产生图像解码,这可能会导致抖动。这是不理智的,因为 GIF 中的每个帧都只是另一个图像。让我们看一下 Chrome 的开发者工具的“性能”面板中的内容,其中唯一的内容是 <img> 指向动画 GIF 的元素:

Chrome开发者工具的“性能”面板将浏览器活动显示为动画GIF播放 图 4:Chrome 开发者工具的“性能”面板将浏览器活动显示为动画 GIF 播放

你在上图所看的那样,当 GIF 的每个新帧被解码时,在光栅化器线程上发生图像解码。现在让我们看一下 GIF 与 MPEG-4 和 WebM 视频的总 CPU 时间对比:

格式 CPU 时间
GIF 2,668 ms
MPEG-4 1,994 ms
WebM 2,330 ms

这些数据是在 Chrome 的跟踪实用程序(记录 Chrome 跟踪 chrome://tracing)中收集的,每个格式的时间约为 6.5 秒。如你所见,GIF 占用的 CPU 时间最多,两个视频尤其是 MPEG-4 的 CPU 时间也更少。这是很赞!这意味着视频通常比 GIF 动画使用更少的 CPU 时间,除了简单地减小文件大小之外,这是一种受欢迎的性能增强。

然而,应该提到的是,一些 CPU 和 GPU 提供硬件加速的视频编码/解码(例如,Intel CPU 上的快速同步视频)。许多处理器可以处理 MPEG-4 的编码和解码,但是 Web8 编解码器(如 VP8 和 VP9 )最近才开始受益于新 CPU 上的硬件加速编码/解码。在这些测试中使用了 Kaby Lake 架构的 Intel 处理器,这意味着视频解码是硬件辅助的。

#潜在的风险

你已经足够了解使用视频比 GIF 动画的优势,但如果我没有指出一些潜在的陷阱,那将是我的失责。这些情况你需要考虑。

#嵌入 GIF 比嵌入视频简单

没有什么比在 <img> 中使用 GIF 简单的了,然后可以继续你的工作。这项简单的工作,开发者的体验是巨大的。

然而,你作为开发者的体验不是唯一重要的,用户的体验更重要。理想的一面是 Safari 中可以在 <img> 中使用视频,这是一个简单的方案用于视频替换 GIf,但不是所有的浏览器支持的。

#编码自己的视频可能需要时间

作为开发者,我们希望节省时间。然而,当涉及到与媒体质量概念一样主观的东西时,可能很难想出一个为所有场景提供最佳结果的自动化过程。

最安全的做法是分析每个视频的编码器输出,并确保结果符合要求。对于视频资源很少的项目,这可能只是一个合理的解决方案。但是对于包含许多视频的大型项目,您可能希望采用保守的编码策略,该策略强调质量而不是文件大小。好消息是,这种策略仍然可以产生很好的效果,显着提高加载性能,并减少所有用户依赖 GIF 动画的数据使用。

此外,将所有 GIF 转换为视频需要时间。你可能没有的时间。在这种情况下,你可以考虑使用基于云计算的媒体托管服务,例如 CloudinaryUploadcare,它们可以做这些工作。从 Cloudinary 的博客中查看介绍,文章解释了他们的服务如何将 GIF 转码为视频。

#节省流量模式

在 Android 中的 Chrome,当节省流量模式开启时,自动播放是禁止的。如果你是网站开发者,并且您正在努力弄清楚为什么视频不会在您的 Android 设备上自动播放,请停用节省流量模式,看看是否能解决问题。