网站因图片导致的加载缓慢是一个常见问题,解决这一问题的有效方法之一是使用现代压缩技术来减少图片文件的大小,其中最新的选择是 AVIF 图片格式。本文将介绍 libavif 编码库,并提供使用该库高效编码 AVIF 图片的教程。

在深入了解 libavif 之前,我们先来看看现代浏览器对 AVIF 图片格式的支持情况。作为最新、最先进的图片格式,AVIF 是否已被广泛支持呢?以下是 Can I use 网站的查询结果:

根据查询结果,自 2024 年 1 月起,AVIF 格式已在最新设备和主流浏览器版本上得到支持。因此,AVIF 已成为新的图片格式主流,完全可以放心使用。

1. 安装 libavif

编译的方法请参照官方 README,我这里以 debian 12 为例,主要讲以 apt 的方式进行安装。目前在 debian 12 的默认软件源中,libavif 版本是发布于 2022 年 10 月的 0.11.1-1,而官方最新的 release 版本已经是 1.1.1 。所以这里选择从 debian 测试版软件源进行安装,以下是步骤:

编辑 /etc/apt/sources.list 文件,添加 debian 测试版软件源:

# Debian Testing
deb http://deb.debian.org/debian testing main contrib non-free
# Debian Unstable
deb http://deb.debian.org/debian unstable main contrib non-free

新建 /etc/apt/preferences.d/99pinning 文件,设置 stable 稳定版软件源的优先级为最高:

Package: *
Pin: release a=stable
Pin-Priority: 900

Package: *
Pin: release a=testing
Pin-Priority: 750

Package: *
Pin: release a=unstable
Pin-Priority: 650

更新软件包列表:

sudo apt update

从测试版软件源安装 libavif:

sudo apt install -t testing libavif-bin

成功后输入 avifenc -V 验证安装:

Version: 1.1.0 (dav1d [dec]:1.4.3, libgav1 [dec]:0.18.0, aom [enc/dec]:v3.6.0, rav1e [enc]:0.7.1 (UNKNOWN), svt [enc]:v2.1.0)
libyuv : available (1891)

2. 编码参数

输入 avifenc --help 可以查看编码的命令行参数,使用默认参数进行编码仅需要设置输入文件和输出文件,例如:

avifenc panda.jpg panda.avif

我自己整理优化后使用的参数如下,量化级别设置为 29

avifenc -s 3 -j all -c aom --ignore-exif --ignore-xmp --ignore-icc --min 0 --max 63 --minalpha 0 --maxalpha 63 -a aq-mode=2 -a cq-level=29 -a end-usage=q -a tune=ssim panda.jpg panda.avif

如果是无损压缩,使用以下:

avifenc -s 3 -j all -l -c aom panda.jpg panda.avif

速率控制模式使用了 q 量化值模式,在 x264 中应该叫 crf 。其中最重要的参数 cq-level 量化级别是如何确定为 29 的呢,以下细说。

首先,我确定要达成的目标是网站图片编码成 avif 格式后,体积尽可能减小的情况下,画质在肉眼观察中不产生明显的区别。为了达成这个目标,我找了不同风格的图片分组进行编码。每个图片长度或者宽度限制在 512px,cq-level 设定值从 26 一直到 36:

  • 知名测试样图 Lenna,该图片很好的包含了平坦区域、阴影和纹理等细节
  • 衣着鲜艳的黑人,包含虚化的背景
  • 自然风景瀑布
  • 卡通
  • 类 excel ,包含简单的文字和图形

经过每组多个图片之间的对比,得出结论 cq-level 设定值在 30 左右,图片细节开始出现肉眼可感知的变化,最终确定 cq-level=29 。然后我把 cq-level=30 这张图片和知名图片压缩服务 shortpixel 编码后的 avif 图片放在一起对比(压缩等级为 Lossy)。呈现效果上的差别还是很细微的,可以说 shortpixel 编码的图片比较接近 cq-level=32 。

完结。