解码AVIF:用猫和imgproxy进行深入研究

493 阅读16分钟

作者。 Polina Gurtovaya,Evil Martians的前端开发员和Andy Barnov,Evil Martians的作家。Le Wagon的老师

AVIF,一种由行业巨头支持的儿童图像格式,随着Firefox的全面加入,终于获得了广泛的浏览器支持。我们在这里调查WebP的后继者是否兑现了其消灭JPEG和PNG的承诺,以及如何利用imgproxy--在网络上转换图像的尖端火星人工具,尽早跳上AVIF的转换列车。请注意,这段文字是为爱猫人士准备的!

随着Firefox 92准备发货,我们终于可以期待AVIF不再是一个噱头,而是获得更广泛的浏览器支持。还有证据表明,Webkit(支持Safari的引擎)也支持AVIF解码。感觉AVIF的采用将在未来几年内飞速发展。

因此,我们觉得现在是深入研究现代图像压缩格式的合适时机,并向你展示如何轻松地在飞行中创建轻质的AVIF版本的图像--而不需要使用命令行图像转换工具或考虑如何存储变体的繁琐任务。

请抓紧时间,因为我们将从一些历史开始,深入了解现代编解码器的工作原理,所以这不是一个快速阅读的过程。这也是对imgproxy的一个很好的介绍,我们的免费开源工具用于即时转换图像。

从图像到框架

现在,网上的图片仍然被_前互联网_时代创造的格式所统治。网络上40%的图片是好的老式JPEG文件。

1992年,当JPEG被创造出来的时候,早期的数码相机只能存储少量的照片,早期的网络通过电话线交换数据,用数字方式发送图像需要几分钟,而YouTube是15年后的事情。

在那个时候,只有小说家可以想象通过卫星和无线电波观看8K视频流到口袋里的设备,这样你就可以在离地面3万英尺高的地方喝番茄汁时查看猫的视频了。

JPEG完成了将图像打包成比原始位图更小的东西所需的所有工作,并且做得很好,所以没有人感到有压力去想出一些根本性的新东西。直到_动态_图像也觉得有必要进行数字化。

如果你有一张500像素宽、350像素高的猫的静态图片,你可以很容易地计算出产生的位图文件的大小。

(500 × 350) × 8 bits per sample × 3 samples = 512Kb!

通过52k调制解调器发送它将需要大约73秒。如果你以某种方式用JPEG压缩你的猫的照片,你将只得到约15Kb,这是34倍的减少。使用WebP或AVIF等现代格式将允许你使其更小,但差别不会很大。毫不奇怪,JPEG仍然在互联网上占主导地位。它的压缩效果足够好。

从下面的表格可以看出,互联网在采用新的图像格式方面相当缓慢。

AVIF还没有压制住JPEG的脖子

然而,随着视频在网络上的风靡,行业巨头们不得不想出一种方法来有效地_流传移动图像_。

大多数现代图像格式(WebP、AVIF和一种叫做HEIF的东西)在本质上都是基于视频格式。如果我们能够压缩1000个帧,我们显然可以压缩一个单一的帧,这将是你的猫咪备忘录。

让我们看看这个粗略绘制的时间线。我们可以看到,在某些时间点上,视频格式催生了图像格式。

AVIF是AV1的一个孩子,它将视频关键帧放入称为HEIF(高效图像文件格式)的容器中,并称其为图像。顺便说一下,你的iPhone照片也是存储在HEIF容器中。

但是,我们为什么要关心任何新的花哨的格式?为什么它们比老式的JPEG更好?让我们在学习视频压缩的速成课程时来弄清楚这个问题。

视频压缩101

当我们在YouTube上观看视频时,我们观察到的是一串从原始视频流解码的静态图片。这个视频流是由一个叫做视频编解码器的特殊程序压缩的。编解码器是enCOder-DECoder的缩写。

将每一个视频帧作为独立的 "图片 "来压缩是非常低效的,就像过去的GIF文件一样。相反,视频编解码器利用了任何视频的两个重要属性:空间_定位_和_时间定位_。

空间定位意味着相邻的像素不是独立的,而是以某种方式连接在一起。时间定位意味着两个相邻的帧最有可能是相似的。

我们可以将我们的_比特流_分成一连串的帧。然后我们可以选择一些 "特殊 "的帧,称其为_关键帧_并将其编码为独立的图片。然后,其余的帧可以从关键帧中衍生出来。这个过程被称为帧间压缩

我们不是为关键帧中的每个区块存储像素,而是在不同的_关键帧_中只存储参考区块以及_运动矢量_。运动向量显示了参考帧的不同部分是如何移动以到达当前帧的。

由于每个关键帧都被_编码_为一个独立的图片,所以它可以被独立_解码_。对每个独立关键帧的编码被称为帧内压缩

为了对关键帧进行编码,我们应该将图片分成若干层,每层对应于_像素视觉属性_的一个特定方面,描述为YCbCr或YUV

Y代表_luma_(亮度方面),Cb/Cr代表_chroma_(颜色方面)。选择这种分割方式是因为人眼对亮度变化比色度变化更敏感。这对大多数哺乳动物来说也是如此。

这意味着我们可以减少色度通道的细节,_降低_其分辨率而不影响_人类感知_的质量。

通常情况下,有三个数字被用来指定降采样。

  • 第一个总是4,不要问我为什么🤷♀️。
  • 第二个是色度通道的水平采样。
  • 第三个是0,这意味着2:1的垂直子采样,或者等于第二个,意味着没有垂直子采样。

4:2:0 是最流行的情况。每一个色度有四个luma样本

下采样完成后,我们可以对luma和chroma层分别进行编码。

要做到这一点,我们首先将图像分割成矩形块,然后按块进行编码。块的大小和结构取决于编码器。老式的JPEG使用8×8的正方形块,而AVIF则创建了一个块的层次结构,从128×128(对于卢马)的超级块开始,可以进一步分割成4像素大小的小块。

现在,空间_定位_开始起作用了。这意味着,我们不对每个块进行单独编码。相反,我们试图从它的邻居那里_预测_一个新块。我们预测的方式被称为_预测模式_。

通常情况下,编码器从顶部和左侧的相邻像素计算块中的预测值。为了对它的工作原理有一个基本的了解,我们来考虑一些预测模式的例子。使用的预测模式的数量因编解码器而异。

直流预测模式--用所有相邻像素的平均值填充块。这是大多数编解码器中最常见的模式。

方向预测--用基于特定方向的相邻像素值来填充区块。不同的编解码器,方向的数量也不同。AVIF有56种方向性模式,而H.264只有两种。以下是最简单的模式,图示。

有一些特定的预测模式只在AVIF中使用。

色度来自卢马--这个名字不言自明:你从相应的卢马像素计算出色度像素。

调色板-它是AVIF的 "GIF模式"。编码器从块中提取调色板,并将每个样本编码为调色板中的一个索引,见下文。

平滑和PAETH预测模式组-预测的样本值是由相邻块的相应顶部和左侧像素计算出来的,并考虑到与块的边缘的距离。

归内部预测-样本值是由块中的前一个样本递归预测的。

最后但并非最不重要的是--块内复制。你可能已经猜到了,在这种模式下,编码器只是引用以前编码的像素。

预测模式是视频游戏书中的技巧;静态设计的JPEG没有足够的智能来做这种数学运算。

在我们预测了一切之后,是时候应用一种叫做离散余弦变换的东西了。当我们对区块应用DCT时,我们把它的表示方法从像素值(如亮度和颜色)改为_特征值_。请在下面的图片上自己看。

在这一点上,我们只是改变了我们存储信息的方式。下一步将是调整系数,直到我们得到尽可能多的相似值。相似意味着它可以被_运行长度编码_,从而形成一个看起来像12W1B12W3B24W1B14W 的字符串,其中B代表黑色,W代表白色。

为了调整系数,我们使用称为_量化_的过程:我们采取一个预先定义的数字矩阵,并将每个区块除以该矩阵中的值。我们可以为不同的图片区域使用不同的矩阵,实现动态质量:你不需要为墙壁提供那么多细节,也不需要为猫的皮毛提供那么多细节。

得到的一组数字可以用一些很酷的无损算法进一步压缩,这只是另一堆枯燥的数学和统计学,你可能在高中时错过了(或没有)。

只有一个问题:由于我们做的每件事都是按块进行的,所以得到的猫可能会变成比它更长方形。但不要担心;我们仍然可以用一些过滤器来平滑事情。

Unfiltered and filtered blocks

上面未经过滤的图块与下面经过过滤的图块的对比

JPEG根本不使用滤波器,而AV1编码器使用3个阶段的流水线(其中一些阶段是可选的)来获得最佳质量。

首先,解锁滤波器平滑了块的边界。下一个滤波器(称为CDEF)分析块,并试图去除振铃伪影,避免模糊尖锐边缘。然后,可以使用称为恢复的过程来恢复在前面压缩步骤中丢失的一些信息。

如果这些过滤器之一出现在AV1比特流中,它将被应用于解码循环中的帧。

AV1规范描述了两个更酷的技巧。

第一个被称为 "超级分辨率",它允许降低一个帧的尺度,对其进行编码,然后在解码时提高尺度。

第二个技巧旨在对抗压缩的主要敌人--随机性。这个想法很简单:许多视频都含有电影颗粒,这给我们的画面增加了随机噪音。AV1将颗粒去除,并对结果进行压缩。然后,解码器将_合成的类似于_电影颗粒的东西加回来,以达到相同的外观和感觉。

综上所述,我们已经描述了在视频压缩过程中发生的六个阶段。

  1. 将一个关键帧分割成块。
  2. 预测相互之间的块。
  3. 应用变换。
  4. 量化。
  5. 过滤。
  6. 无损压缩。

现代图像格式之间唯一真正的区别是在这些步骤的细节上。

这些阶段的进步推动了现代媒体格式的发展,正如你在下表中看到的那样。

正如你所看到的,AVIF/AV1包装了大多数功能,在科学竞争中获胜,同时也是免版税的。该格式由开放媒体联盟开发,该联盟由亚马逊、ARM、思科、Facebook、谷歌、IBM、英特尔、微软、Mozilla、Netflix、Nvidia、三星电子、腾讯、苹果等管理。

所有这些公司都是以盈利为目的,但他们也想确保你使用最好的编解码器,这样你就可以消费更多的内容,使用更少的带宽。因此,AV1和AVIF都是免费的;如果你决定围绕图像压缩建立业务,你不必支付版权费。

这都是主观的

酷酷的,AVIF在理论上要比JPEG好得多。但证据在哪里呢?我们如何比较这两种格式呢?事实证明,这是个超级困难的任务。

AVIF和JPEG是标准。这些标准是用不同的真实编解码器以不同的方式实现的。而实施很重要。为了使事情变得更加困难,回顾一下,视频编解码器是_一组工具_,你可以关闭其中的一些(例如,过滤器)。

这意味着你不能比较格式--你只能比较特定的实现方式,并尝试匹配一组命令行参数。

你选择压缩的资产的类型也很重要。例如,AV1有一套内置工具来实现对 "屏幕内容 "更好的压缩,如块内复制。AV1可以在压缩文本方面做得更好,但JPEG可能在压缩猫方面做得更好!因此,我们需要选择合适的数据格式。所以我们需要选择一个合适的数据集进行压缩。

现在是最有趣的部分:我们如何比较两个压缩的图像?让我们试试吧!

你能看出上面的区别吗?我当然不能。是的,在这种特殊情况下,AVIF要小一些,但是,根据图像的不同,这种差异可能小得可以忽略不计。AVIF真正闪光的地方是在低质量设置下的压缩,当我们需要对尺寸进行优化时,这往往是网络的情况。如果我们把图像大小限制在20Kb左右,会发生什么?

JPEG完全崩溃成了块状,而AVIF仍在躲避,使用更少的空间,给我们的图像_在感觉上_与未压缩的原始图像没有太大的区别。这就是AV1过滤器的威力!

我们甚至可以用一些硬性数字从_感知质量_的角度来比较图像。最好的衡量标准叫做SSIM(代表结构相似度),一般会把几个指标结合起来(不同类型的SSIM加上PSNR)。

另一种方法是使用基于ML的技术。我们可以用一个神经网络来模拟观众的感知!

我可以踢它吗?(是的,你可以,用imgproxy!)

精心选择的图片格式可以大大改善你的网站性能。这在最近变得非常重要:因为谷歌的一个新指标叫核心网络生命力,影响你的网页的搜索排名。

在许多情况下,手动处理每张图片是超级低效的。通常,你需要优化来自用户或第三方集成的第三方图片。有许多解决方案可以帮助你以最佳格式提供图片。

然而,我们推荐imgproxy。它是一个性能极强、易于使用、安全的_自我托管_服务器,用于即时处理图片。

要快速试用imgproxy,你只需要在你的机器上安装Docker。如果你喜欢它(我们打赌你会喜欢)--请查看官方网站,了解部署选项(支持Heroku!)和更高性能的imgproxy Pro

imgproxy运行中

所有的转换参数都在URL中进行了编码

要用imgproxy创建AVIF图像,你只需要运行一个服务器的实例,并构建正确的URL,其中包含源图像的链接和你想使用的编码选项。

关于可用选项的更多信息,请查看imgproxy文档。另外,确保你在生产中使用签名,以保护你的imgproxy端点免受不需要的请求。

然而,为了快速了解这些可能性,这里有一个简单的DIY例子,用imgproxy创建AVIF图像。打开你的终端,启动Docker Desktop,让我们在飞行中把一些东西转换成AVIF。

docker pull darthsim/imgproxy:latest
docker run -p 8080:8080 -it darthsim/imgproxy

现在imgproxy已经在localhost:8080 ,并且100%准备好优化你的猫。有了这个,你所需要的就是为imgproxy构建一个适当的请求,把源图像的链接和编码选项放在URL中。基本的格式是这样的。

http(s)://%imgproxy-host/%signature/%processing_options/plain/%source_url@%extension

现在启动你的浏览器(我们推荐Chrome浏览器,因为当你读到这篇文章时,默认的AVIF支持可能还没有在Firefox或Safari中出现),并将以下URL粘贴到地址栏。在引擎盖下,imgproxy使用最快的AVIF编码器:rav1e。请注意,转换是_在请求_时完成的;你不需要以任何方式事先处理你的图片

# note we use /insecure/ to tell imgproxy we are not using any cryptographic signing for this simple home demo
http://localhost:8080/insecure/resize:fill:300:400:0/gravity:sm/quality:60/plain/https://www.nasa.gov/sites/default/files/thumbnails/image/pia22228.jpg@avif

就这样吧!你现在可以看到你刚刚创建的AVIF图片在野外,而不需要手动压缩任何东西。

除了rav1e,一个支持imgproxy的编码器,还有其他值得一提的工具。

  • SVT-AV1-一个实验性的AV1/AVIF的编码器和解码器。
  • libaoum--Chromium中使用的AV1编解码器。
  • dav1d-Firefox中使用的AV1解码器。
  • 当然还有ffmpeg--一把瑞士军刀,可以编码一切。

一些CDN供应商也在他们那边实施AVIF转换。请看Cloudflare的这个帖子

现在,你完全有能力节省所有的带宽,并向你的用户提供那些精美的压缩图像了


根据Can I Use数据库,超过67%的网络用户今天已经准备好收获AVIF图像的好处。毫无疑问,在几乎一致的行业支持下(以及大量资金的投入),我们可以期待该格式在未来十年成为事实上的标准。如果你想在你的网络应用中成为AVIF的早期采用者,你可以使用imgproxyURLs和srcset HTML属性的组合,在越来越多的浏览器采用该编解码器时,逐步增强你的标记。

如果你需要招募火星人的工程师和设计师来帮助你的数字产品,无论它们是否围绕图像压缩而构建,请随时与我们联系。