批量转换图片为 WebP 格式的几种实用方案

WebP 是 Google 推出的一种现代图片格式,在同等画质下体积比 JPEG 小 25%-35%,比 PNG 小得更多。对于博客网站和前端项目来说,全量切到 WebP 能显著减少页面加载时间。


为什么要用 WebP

在介绍方案之前,先简单说说为什么值得花时间做这件事:

对比项 PNG JPEG WebP
无损压缩 支持 不支持 支持,比 PNG 小 26%
有损压缩 基准 比 JPEG 小 25-35%
透明度 支持 不支持 支持
动图 支持(替代 GIF)

根据 Google 的官方数据,WebP 无损图片比 PNG 体积小 26%,有损图片比同等 SSIM 质量的 JPEG 小 25-35%。对于流量来自移动端的场景,省下来的每一 KB 都在加快首屏速度。

浏览器兼容性方面,主流现代浏览器(Chrome、Firefox、Edge、Safari 14+)都已原生支持 WebP。如果你需要兼容老旧浏览器,可以用 <picture> 标签做降级兜底:

1
2
3
4
<picture>
<source srcset="image.webp" type="image/webp">
<img src="image.png" alt="fallback">
</picture>

这行代码不会增加太多维护成本,但对用户体验的提升是实打实的。


方案一:使用 cwebp(Google 官方工具)

cwebp 是 Google 提供的 WebP 编码器,也是性能最好、控制最细的方案。

安装

macOS:

1
brew install webp

Ubuntu/Debian:

1
sudo apt install webp

Windows(用 Scoop):

1
scoop install webp

单文件转换

1
cwebp -q 80 input.png -o output.webp

-q 80 是质量参数(0-100),80 通常是在画质和体积之间比较好的平衡点。

批量转换

用一行 find 配合 xargs 就能处理整个目录:

1
2
3
# 将当前目录下所有 PNG/JPEG 转换为 WebP
find . -type f \( -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" \) \
-exec sh -c 'cwebp -q 80 "$1" -o "${1%.*}.webp"' _ {} \;

这个命令会遍历当前目录及其子目录下的所有图片,为每张图片生成一个同名的 .webp 文件。

如果你只想处理单层目录,用 for 循环更直观:

1
2
3
for img in *.png *.jpg *.jpeg; do
cwebp -q 80 "$img" -o "${img%.*}.webp"
done

保留目录结构批量转换

如果你想把源文件放在 images/,输出到 webp_output/ 并保持相同的目录结构:

1
2
3
4
5
find images/ -type f \( -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" \) | while read -r file; do
output="webp_output/${file#images/}"
mkdir -p "$(dirname "$output")"
cwebp -q 80 "$file" -o "${output%.*}.webp"
done

方案二:使用 ImageMagick

如果你已经在用 ImageMagick 处理图片,它内置的 WebP 支持足够应对大多数场景,值得优先考虑。

安装

macOS:

1
brew install imagemagick

Ubuntu/Debian:

1
sudo apt install imagemagick

批量转换

1
mogrify -path ./webp_output -format webp -quality 80 *.png *.jpg

mogrify 是 ImageMagick 的批量处理命令,-path 指定输出目录(会自动创建),-format 指定输出格式。

如果需要递归处理子目录,配合 find

1
2
find . -type f \( -name "*.png" -o -name "*.jpg" \) -exec \
sh -c 'convert "$1" -quality 80 "${1%.*}.webp"' _ {} \;

ImageMagick 的优势在于你可以在转换的同时做其他处理——调整尺寸、裁剪、加水印:

1
mogrify -path ./webp_output -resize 1920x1080 -quality 80 -format webp *.jpg

方案三:使用 Squoosh CLI(Google 出品,Web 版命令行)

Squoosh 是 Google Chrome Labs 推出的图片压缩工具,它的 CLI 版本适合 Node.js 生态的开发者。

安装

1
npm install -g @squoosh/cli

批量转换

1
squoosh-cli --webp '{"quality":80}' *.png *.jpg --output-dir ./webp_output

Squoosh 的好处是编码器参数通过 JSON 传递,非常灵活。它还支持 AVIF、JPEG XL 等新一代格式,未来迁移很方便。


方案四:用 Node.js + Sharp 写脚本

如果你的项目已经用 Node.js,用 sharp 库写一个批量转换脚本是最灵活的方式——可以精确控制输出路径、添加日志处理、与 CI/CD 流程集成。

安装依赖

1
npm install sharp glob

批量转换脚本

创建一个 convert-to-webp.mjs 文件:

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
import sharp from 'sharp';
import { glob } from 'glob';
import path from 'path';
import fs from 'fs';

const QUALITY = 80;
const INPUT_DIR = './images';
const OUTPUT_DIR = './webp_output';

// 获取所有图片文件
const files = await glob('**/*.{png,jpg,jpeg}', { cwd: INPUT_DIR });

for (const file of files) {
const inputPath = path.join(INPUT_DIR, file);
const outputPath = path.join(OUTPUT_DIR, file.replace(/\.(png|jpe?g)$/i, '.webp'));

// 确保输出目录存在
fs.mkdirSync(path.dirname(outputPath), { recursive: true });

await sharp(inputPath)
.webp({ quality: QUALITY })
.toFile(outputPath);

const inputSize = (fs.statSync(inputPath).size / 1024).toFixed(1);
const outputSize = (fs.statSync(outputPath).size / 1024).toFixed(1);
console.log(`✓ ${file} ${inputSize}KB → ${outputSize}KB`);
}

console.log(`\n转换完成!共处理 ${files.length} 个文件`);

运行:

1
node convert-to-webp.mjs

脚本会输出类似下面的日志:

1
2
3
4
5
✓ hero.png  120.5KB → 32.1KB
✓ screenshot.jpg 340.2KB → 68.4KB
✓ icon.png 8.5KB → 4.2KB

转换完成!共处理 3 个文件

如果你想把这个流程加到 GitHub Actions 里也很容易,就是在构建前跑一遍脚本的事。


方案五:macOS 用户的神器——sips + ImageMagick

macOS 自带 sips(Scriptable Image Processing System),可以配合 cwebp 做迂回转换。如果你不想装太多东西,这个组合够用:

1
2
3
4
5
6
# 批量将 PNG 转为 WebP(需 brew install webp)
for f in *.png; do
sips -s format jpeg "$f" --out "${f%.*}.jpg" && \
cwebp -q 80 "${f%.*}.jpg" -o "${f%.*}.webp" && \
rm "${f%.*}.jpg"
done

sips 能转换大部分常见格式,但原生不支持输出 WebP,所以这里用了一个迂回策略:先用 sips 转成 JPEG,再用 cwebp 编码成 WebP。


避坑指南

1. 处理后的文件比原文件大?

WebP 对照片类图片压缩效果最好,但对某些简单图形、截图、扁平色块的 PNG,WebP 无损模式的文件体积可能反而比原文件大。遇到这种情况,可以尝试有损模式或者保持原格式。

2. 不要删除原始文件

建议转换完成后统一清理,而不是转换时直接覆盖。万一对质量不满意,还能用原图重新压。

3. 质量参数选择建议

场景 推荐质量
产品图、照片 -q 80 ~ -q 85
图标、UI 元素 -q 90 ~ -q 95(或无损)
缩略图、背景图 -q 60 ~ -q 70
存档、无损需求 -lossless

4. 文件命名冲突

如果源文件有 photo.jpgphoto.png,转换后都会变成 photo.webp,两个文件会互相覆盖。建议转换前检查一下文件名:

1
2
find . -type f \( -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" \) \
-exec basename {} \; | sed 's/\.[^.]*$//' | sort | uniq -d

有重复就单独处理,或者给输出文件加上后缀区分。


总结

五个方案各有侧重,选哪个取决于你的具体场景:

方案 适合人群 特点
cwebp 命令行用户 最快、最可控
ImageMagick 已有该工具链 可同时做其他处理
Squoosh CLI Node 开发者 参数灵活,格式友好
Sharp 脚本 前端项目 可集成 CI/CD
sips + cwebp macOS 用户 零安装(brew 即可)

无论用哪种方式,WebP 迁移都是一次性的工作,带来的加载速度提升却是长久的。如果你还在用原始图片格式往外丢,花半小时做一次全量迁移吧,值得。

如果你有更好的方案或踩过什么坑,欢迎留言补充。