文章

一键压缩avif图像

使用FFmpeg批量压缩avif或webp图像

一键压缩avif图像

背景介绍

传统的 JPEG 和 PNG 格式在现代网页开发中已经不再是唯一选择。Google 推出的 WebP 格式和新兴的 AVIF 格式都能在保持高质量的同时大幅减小文件体积。WebP 通常比 JPEG 小 25-35%,而 AVIF 则可以再减少 20-30% 的体积。

功能简介

这套工具包含四个主要功能:

  1. img2webp - 将单张图片转换为 WebP 格式
  2. img2avif - 将单张图片转换为 AVIF 格式
  3. batch_img2webp - 批量转换目录中的所有图片为 WebP
  4. batch_img2avif - 批量转换目录中的所有图片为 AVIF

质量参数说明

  • WebP:质量范围 0-100(数值越大质量越高,默认85)
  • AVIF:质量范围 0-63(数值越小质量越高,默认25)
  • 硬件加速优化:针对 M4 Mac 设备进行了特别优化
  • 尺寸对比:转换完成后显示文件大小变化

使用方法

1. 安装依赖

首先确保系统已安装 FFmpeg:

1
2
# 使用 Homebrew 安装(macOS)
brew install ffmpeg

2. 配置终端函数

将提供的代码直接复制到终端中执行,即可在当前会话中使用这些函数。 如为永久可用,可将代码添加到你的 shell 配置文件中(如 ~/.zshrc~/.bashrc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# 将图片转换为 WebP 格式
# 用法: img2webp <输入文件> [质量] [输出文件]
# 质量范围: 0-100 (默认: 85)
img2webp() {
    if [[ $# -eq 0 ]]; then
        echo "用法: img2webp <输入文件> [质量] [输出文件]"
        echo "示例: img2webp photo.jpg 90 photo.webp"
        echo "      img2webp photo.jpg 90"
        echo "      img2webp photo.jpg"
        return 1
    fi

    local input="$1"
    local quality="${2:-85}"
    local output="${3:-${input:r}.webp}"

    if [[ ! -f "$input" ]]; then
        echo "错误: 输入文件 '$input' 不存在"
        return 1
    fi

    # 针对 M4 Mac 使用硬件加速
    ffmpeg -i "$input" \
        -c:v libwebp \
        -quality "$quality" \
        -preset picture \
        -threads 0 \
        "$output" -y -loglevel error
    
    if [[ $? -eq 0 ]]; then
        local input_size=$(du -h "$input" | cut -f1)
        local output_size=$(du -h "$output" | cut -f1)
        echo "✓ $output ($input_size -> $output_size)"
    else
        echo "✗ 转换失败: $input"
        return 1
    fi
}

# 将图片转换为 AVIF 格式
# 用法: img2avif <输入文件> [质量] [输出文件]
# 质量范围: 0-63 (数字越小质量越高,默认: 25)
img2avif() {
    if [[ $# -eq 0 ]]; then
        echo "用法: img2avif <输入文件> [质量] [输出文件]"
        echo "示例: img2avif photo.jpg 20 photo.avif"
        echo "      img2avif photo.jpg 20"
        echo "      img2avif photo.jpg"
        echo ""
        echo "注意: AVIF 质量参数 0-63,数字越小质量越高"
        return 1
    fi

    local input="$1"
    local quality="${2:-25}"
    local output="${3:-${input:r}.avif}"

    if [[ ! -f "$input" ]]; then
        echo "错误: 输入文件 '$input' 不存在"
        return 1
    fi

    # 检测是否有透明通道
    local has_alpha=$(ffprobe -v error -select_streams v:0 -show_entries stream=pix_fmt -of default=noprint_wrappers=1:nokey=1 "$input" | grep -c "a$")
    
    # 针对 M4 Mac 优化的 AVIF 转换
    if [[ $has_alpha -gt 0 ]]; then
        # 带透明通道
        ffmpeg -i "$input" \
            -c:v libaom-av1 \
            -crf "$quality" \
            -cpu-used 4 \
            -row-mt 1 \
            -threads 0 \
            -pix_fmt yuva420p \
            "$output" -y -loglevel error
    else
        # 不带透明通道
        ffmpeg -i "$input" \
            -c:v libaom-av1 \
            -crf "$quality" \
            -cpu-used 4 \
            -row-mt 1 \
            -threads 0 \
            -pix_fmt yuv420p \
            "$output" -y -loglevel error
    fi
    
    if [[ $? -eq 0 ]]; then
        local input_size=$(du -h "$input" | cut -f1)
        local output_size=$(du -h "$output" | cut -f1)
        echo "✓ $output ($input_size -> $output_size)"
    else
        echo "✗ 转换失败: $input"
        return 1
    fi
}

# 批量转换目录下的所有图片为 WebP
# 用法: batch_img2webp [目录] [质量]
batch_img2webp() {
    local dir="${1:-.}"
    local quality="${2:-85}"
    
    for file in "$dir"/*.{jpg,jpeg,png,JPG,JPEG,PNG}(N); do
        if [[ -f "$file" ]]; then
            img2webp "$file" "$quality"
        fi
    done
}

# 批量转换目录下的所有图片为 AVIF
# 用法: batch_img2avif [目录] [质量]
batch_img2avif() {
    local dir="${1:-.}"
    local quality="${2:-25}"
    
    for file in "$dir"/*.{jpg,jpeg,png,JPG,JPEG,PNG}(N); do
        if [[ -f "$file" ]]; then
            img2avif "$file" "$quality"
        fi
    done
}

3. 基本使用示例

转换单张图片为 WebP:

1
2
3
img2webp photo.jpg           # 使用默认质量(85)
img2webp photo.jpg 90       # 指定质量为90
img2webp photo.jpg 90 output.webp  # 指定输出文件名

转换单张图片为 AVIF:

1
2
3
img2avif photo.png          # 使用默认质量(25)
img2avif photo.png 20       # 指定质量为20
img2avif photo.png 20 output.avif  # 指定输出文件名

批量转换目录中的所有图片:

1
2
batch_img2webp ~/blog/images   # 转换目录中所有图片为WebP
batch_img2avif ~/blog/images 50 # 指定质量并转换为AVIF

快捷指令

为了进一步简化操作流程,我还创建了一个Mac快捷指令,可以在移动设备上快速处理图片:

这个快捷指令可以与终端工具配合使用,提供更加完整的图片优化工作流。

本文由作者按照 CC BY 4.0 进行授权