作为NAS重度用户,我最近把谷歌开源的图片压缩工具Squoosh搬到了群晖上。这个工具最吸引我的点,就是图片压缩完全在本地完成,不用把照片传到第三方网站,压缩速度和隐私都有保障。折腾下来整体感觉非常顺手,所以这篇文章就把部署思路、两种实现方式、参数调优心得和踩过的坑一起摊开说说,给想在群晖上做图片压缩的朋友一个可以直接抄作业的参考。
1. 为什么偏偏是Squoosh:项目需求与方案思路
1.1 Squoosh到底是个什么东西
Squoosh是Chrome Labs开源的一款图片压缩工具,最初以网页版的形式出现。它最核心的技术特点,是把图片解码、编码全部通过WebAssembly在浏览器本地完成,图片数据不会上传到任何服务器。后来官方顺手推出了命令行版本(@squoosh/cli),方便批量处理图片,还可以把压缩能力集成到自动化流程里。
对于NAS用户来说,Squoosh的价值不只是“少上传图片”这么简单。群晖NAS本身就承担了相册备份、文件共享、网站托管这些工作,照片和设计素材都在本地。日常场景里,博客配图、微信素材、电商详情页、公众号封面,动辄几十上百张图要压缩,一个个拖到网页版工具里处理效率太低,又担心第三方平台泄露原图。在群晖上部署一个本地压缩服务,等于把压图这件事彻底收编到自己的网络环境里,随时打开浏览器就能用,或者写个脚本批量跑。
1.2 群晖用户为什么需要本地图片压缩
先把话说透,群晖用户平时压缩图片,最常用的无非是这几条路:在线压缩网站、Photoshop“存储为Web格式”、开源软件(如GIMP)、图床自带的压缩接口。这几条路各有各的毛病:
- 在线压缩网站(TinyPNG这类)确实方便,但免费版有文件大小上限(一般限制5MB),每天还有配额,批量压图要么排队要么付费,图片文件还要经过别人的服务器,涉及隐私的图片(合同扫描件、产品设计稿、家人照片)谁敢往上传?
- Photoshop这类软件压缩质量高,但每次都要人工操作,几百张图根本弄不过来,还得考虑电脑上有没有安装。
- 很多图床自带的接口方便,但参数的灵活性很差,你想调整压缩率、选择编码器,基本做不到。
NAS的定位就是“家里的私有云”,所有数据都在本地流转。在群晖上部署Squoosh,恰恰能把图片压缩这件事从“云端依赖”变成“本地服务”:压缩过程全部在群晖的CPU和内存里完成,不走外网,更不会把原图交到第三方手里。压缩的编码器可以选择MozJPEG、WebP、AVIF、OxiPNG这些主流方案,还可以调质量参数、缩放尺寸,用Web界面预览压缩前后的画面对比。
1.3 两种部署路线的取舍
在群晖上跑Squoosh,主流做法有两类:
- Docker容器部署:群晖DSM 7.2以上版本自带Containter Manager(以前的Docker套件),直接在镜像仓库里拉一个Squoosh镜像,创建容器就跑起来了。优点是隔离干净,不污染群晖的系统环境;缺点是第三方镜像维护水平参差不齐,发现一个好用的镜像需要试错。
- Node.js环境部署:群晖套件中心有官方Node.js套件,装上之后再用npm全局安装@sqoosh/cli,就能在SSH命令行里直接跑批量压缩。优点是走官方版本,功能最全,参数更新及时,没有第三方镜像的“盲盒”问题;缺点是要接触命令行,对纯小白来说上手门槛稍高。
我个人的建议是:如果你只是想在浏览器里像用网页版一样拖图片进去压缩,选Docker方案,访问方便;如果你要批量压几百张图,想把这些操作写进脚本和计划任务里,选Node.js方案更省心。两个方案我在下面都会详细带一遍。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 部署前的准备:环境评估与工具选型心得
2.1 群晖NAS的软硬件适配
先说硬件。Squoosh的压缩过程对CPU和内存有一定要求,尤其处理的图片尺寸大或者数量多的时候,内存占用会明显上升。实测在群晖上跑Web版Squoosh,打开页面之后,默认状态下内存占用大约在200-500MB,压缩高分辨率图片时瞬时峰值可能到1GB以上。所以低配机型(比如只有1GB内存的老款J系列)跑起来会有点喘,建议至少2GB内存起步,x86_64架构的机型(DS920+、DS423+这类)体验最好。ARM机型(比如DS223j)虽然能跑Docker里的Squoosh,但部分编码器编译版本可能不兼容,我会建议直接用Node.js方案,兼容性更好。
软件上,你需要在套件中心确认两件事:
- 群晖系统版本:DSM 7.2以上自带Containter Manager;DSM 6.x时代叫Docker套件,也能用,只是界面和权限有差异。
- 安装对应套件:如果走Docker路线,安装“容器管理器”;如果走Node.js路线,在套件中心搜索并安装Node.js(当前主流版本是v20或v22,Squoosh CLI对Node版本要求不高,v18以上都能跑)。
2.2 镜像选型到底怎么选
走Docker路线的话,镜像选型是我栽过跟头的地方。Docker Hub上搜索squoosh,能搜出好几个结果,有些镜像历史非常久远,拉下来之后页面显示不出来,或者编码器缺失。以我两次重装的经验,选Docker镜像时重点看三个维度:
- 最后更新时间:尽量选择最近一年内还在活跃维护的镜像。Squoosh的代码库迭代不算频繁,但编码器版本更新会影响压缩效果和兼容性。
- 镜像体积和层数:不要盲目选体积大的镜像,Squoosh核心代码加WebAssembly编码器其实很小,体积特别大的镜像可能是打包方式粗糙,甚至包含了无关依赖。
- 下载量和社区反馈:同名的镜像里选下载量多的,一般来说更可靠。
我不太建议从零构建镜像,因为Squoosh官方仓库的Dockerfile需要自己拉代码构建,在群晖上构建镜像要占不少临时空间,而且构建过程可能踩网络问题。直接用社区维护好的镜像,部署速度最快。
用Node.js方案就没有镜像选择的问题,官方发布在npm上的@squoosh/cli就是最权威的版本,不用折腾第三方。
2.3 端口与网络规划
Squoosh的Web服务(官方CLI模式)默认监听在8000端口,启动后会输出访问地址。Docker容器里也一样,容器内部监听8000端口,需要在创建容器时映射到群晖宿主机的一个空闲端口。我习惯映射到8088,因为群晖很多套件默认占用5000/5001,再用8000容易撞端口。
网络规划方面,如果你只在局域网内使用,只要保证群晖防火墙放行映射的端口即可。要是想在外网访问,我强烈不建议直接把端口暴露到公网。更稳妥的做法是通过群晖的QuickConnect中转,或者用DDNS配合HTTPS证书访问,同时把登录页面设置成强密码。这个话题涉及安全配置较多,我放到后面踩坑部分细说。
3. 实操全程:从拉取镜像到Web界面可用
3.1 方案A:Docker容器部署步骤
下面用DSM 7.2的Container Manager演示。
- 打开Container Manager,进入“注册表”页面,搜索
sqooosh(注意拼写,容易手滑多打一个o),从搜索结果里挑一个更新时间最近、下载量较高的镜像点“下载”。 - 等待镜像拉取完成,进入“映像”页面,选中刚拉取的镜像,点击“运行”。
- 容器名称随意,比如
sqoosh-web。重点配置两处:- 端口设置:容器端口
8000,本地端口8088,协议选择TCP。 - 存储空间:如果你希望压缩后的图片能直接保存到群晖的共享文件夹,可以添加一个存储映射,把容器的
/app/output(具体路径最好看镜像的说明,这里以常见路径为例)映射到本地的/volume1/compress这类共享文件夹。
- 端口设置:容器端口
- 环境变量一般不用配置,Squoosh的Web版本不太依赖环境变量。如果是第三方镜像,可以先参考镜像文档页的环境变量说明。
- 点击“应用”创建容器。创建完成之后,在容器列表里找到它,点“详情”,切到“日志”选项卡,正常情况下会看到类似这样的输出:
bash复制Starting server at http://0.0.0.0:8000
- 浏览器访问
http://群晖的局域网IP:8088,就能看到Squoosh的Web界面了。
需要注意,如果容器日志里提示监听端口不对,很可能镜像内部用的不是8000,这时候可以进入容器详情页,在“终端机”选项卡里执行env | grep PORT或者查看启动命令,确认后调整映射关系。
3.2 方案B:Node.js命令行版,适合批量脚本
如果嫌Docker镜像维护水平参差不齐,那就直接用官方Node.js方案。这套方案我目前主力使用,因为批量压缩、写脚本、挂在群晖的计划任务里都很方便。
- 套件中心安装Node.js,安装时选择最新稳定版。
- 通过SSH连上群晖(需要先在控制面板开启SSH功能),用管理员账号登录后执行安装CLI:
bash复制sudo npm install -g @squoosh/cli
如果提示权限不足,就检查一下npm的全局目录是不是系统目录,群晖的套件Node.js会把npm全局目录设置到/usr/local/bin,普通用户很容易碰权限边界,所以强烈建议用sudo执行安装。
安装完成后验证一下:
bash复制squoosh-cli --help
看到类似“Squoosh CLI”的帮助信息就说明装好了。
- 用官方CLI压缩单张图片的基础命令长这样:
bash复制squoosh-cli --mozjpeg auto --resize 1920:1920 input.jpg -d ./output
这条命令的意思是用MozJPEG编码器,质量设为auto,把图片缩放到最长边1920像素(保持宽高比),输入input.jpg,输出到./output目录。-d如果没指定,默认就输出到当前目录下与输入同名的文件前面(具体可以看帮助文档)。
- 批量压图用一个简单的shell循环就能搞定。比如把当前目录下所有jpg压成WebP,同时控制最大边1920像素:
bash复制for img in *.jpg; do
squoosh-cli --webp auto --resize 1920:1920 "$img" -d ./webp_output
done
这套方案一个额外好处是,压缩过程完全无头运行,你可以在群晖的任务计划里创建一个定时任务,定期去扫描指定文件夹里的新图片,自动压缩输出到另一个备份目录。这个玩法后面我细说。
3.3 外网访问的安全提醒
部署好之后,如果你只是内网用,那基本就完事了。如果确实想外网访问,不少人的第一反应是“把端口映射到路由器上”,我极其不建议这么做。群晖的登录页面是默认的,私密文件如果在公网裸奔,扫描工具分分钟就能扫到你的服务端口。
我的建议是分两步:先用群晖的证书给服务加上HTTPS(群晖控制面板里有免费的Let's Encrypt证书申请),再把访问入口限制在DDNS域名加复杂路径后面。如果你不想折腾这些,用QuickConnect穿透放行特定端口也可以,它自带身份认证,安全性比直开端口高不少。总之,任何映射到公网的服务,都需要配置强密码、开启登录限制、定期查看访问日志。
3.4 实际压缩体验记录
部署好之后,我拿自己博客里的素材做了几组实测。为了公平起见,用同一张4032×3024像素、原大小4.8MB的照片,分别用MozJPEG、WebP、AVIF三种编码器处理,质量参数均设为75左右,输出尺寸限制为1920像素宽。结果如下:
| 编码器 | 输出格式 | 输出文件大小 | 压缩率 | 视觉观感 |
|---|---|---|---|---|
| MozJPEG | JPEG | 420KB | 91.2% | 与原图几乎无差别,放大后有轻微噪点 |
| WebP | WebP | 310KB | 93.5% | 边缘细节略锐利,无明显伪影 |
| AVIF | AVIF | 180KB | 96.2% | 纹理部分有轻微涂抹感,一般场景无感知 |
单独看AVIF的压缩率确实很香,但AVIF编码耗时明显偏高,单张大图大约需要4-6秒,而MozJPEG只用了不到1秒。所以假如你的照片要发到微信或者论坛,对兼容性有要求的,首选WebP或MozJPEG;如果只是自己存档备份,AVIF的压缩率很值得考虑。
4. 核心功能深度解析:参数与编码器怎么选
4.1 Squoosh支持的编码器对比
Squoosh不是只支持一种压缩格式,它在同一个界面上集成了多个编码器,每个编码器对应不同的应用场景:
| 编码器 | 输出格式 | 适用场景 | 优点 | 不足 |
|---|---|---|---|---|
| MozJPEG | JPEG | 博客图片、社交平台、兼容性要求高的场景 | 压缩率高,画质损失小;所有程序都能打开 | 不支持透明背景 |
| WebP | WebP | Web页面、公众号图片 | 压缩率比JPEG高出30%左右,支持透明;现代浏览器大多支持 | 个别老设备和旧版系统不支持 |
| AVIF | AVIF | 高质量压缩、个人存档 | 压缩率再次大幅提升,支持HDR | 编码慢,兼容性目前仍不及WebP |
| OxiPNG | PNG | 截图、图标、带透明背景的图片 | 无损或接近无损压缩 | 对有损压缩场景没有意义,体积仍然偏大 |
| 自定义(BrowserPNG等) | 多种 | 发烧友研究 | 灵活度高 | 配置复杂,不适合日常用 |
实际选择标准可以简化成一句话:需要兼容性就MozJPEG或WebP,需要极限压缩率就AVIF,需要透明背景就WebP,需要无损的图标和截图就OxiPNG。
4.2 关键参数怎么看怎么调
Squoosh的参数其实不复杂,重点就三个:
- 质量(Quality):范围一般是0-100。数值越高画质越好,体积越大。以MozJPEG为例,75是博客配图的甜点值,90以上适合保留细节的原图输出,50以下会出现可见的色块和边缘振铃。
- 缩放(Resize):如果不做缩放,大图压缩后体积依然可观。绝大多数应用场景(尤其是在屏幕上展示的图片)把最长边限制到1920像素就已经足够满足4K显示器的需求;如果只是公众号配图,1200像素以内就够了。缩放之后体积能再下降一个量级。
- 编码器特定参数:比如WebP的无损模式(Lossless)开关,AVIF的
Effort参数(代表编码耗时,值越大压缩越精细但耗时越长)。日常用默认值就好,不用过于深入。
我的建议是,把Squoosh当作一个“压图流水线”:先设置输出尺寸上限,再选编码器,最后根据抽样查看视觉结果微调质量。
4.3 批量与脚本化的进阶玩法
前面提到Node.js CLI方案支持脚本化,这里给一个我实际使用的群晖计划任务脚本示例。目标是将/volume1/photo/原图路径下的图片自动压缩到/volume1/photo/压缩图:
bash复制SOURCE="/volume1/photo/原图"
DEST="/volume1/photo/压缩图"
mkdir -p "$DEST"
find "$SOURCE" -type f \( -iname "*.jpg" -o -iname "*.png" \) -mmin +5 | while read f; do
echo "压缩中:$f"
squoosh-cli --webp auto --resize 1920:1920 "$f" -d "$DEST"
done
注意两个细节:一是通过find和-mmin +5过滤,避免程序正在写入的图片还没有完成就被拿去压缩;二是输出目录不要放在源目录内部,防止压缩结果再次被find捕获形成死循环。
把这段脚本填进群晖“控制面板-任务计划-新增-计划的任务-用户自定义脚本”,执行间隔可以设成每天凌晨3点。这样NAS就会自动处理当天新增的图片,手机相册的照片备份进来后,早上起来压缩图就都准备好了。
5. 踩坑实录:我遇到的三个经典问题与排查
5.1 容器无法启动:端口被占用
第一次用Docker方式部署时,容器状态一直显示“退出”,查看日志发现报错:
bash复制Error: listen EADDRINUSE: address already in use :::8000
原因很简单,容器里的进程检测到8000端口被占用,启动失败。我当时把本地端口映射改成了8088,却忽略了容器内部的8000端口可能被同一个镜像重复启动的旧容器占用。解决方法是先在容器列表里把之前的异常容器删掉,再把映射关系改成9000:8000这类不常用的端口组合,重新启动就正常了。
经验是,不要一上来就依赖默认端口,不管Web版还是CLI版,都显式指定一个自定义端口,避免冲突。端口冲突在群晖这种日常跑着好多套件的系统里特别常见。
5.2 压缩大图时内存爆掉
有次我压一张8000×6000像素的全景图,Web界面直接卡死,SSH里看群晖的内存几乎被打满了,负载曲线一下子飙高。后来定位到原因是Squoosh的WebAssembly编解码需要把整个图像数据加载进内存,图片尺寸过大时,内存会直接翻倍甚至更高。
解决方案是:先用--resize参数把图片缩放到2048以内再做压缩。对于已经上传到Web界面的大图,也可以先把图片缩小到合理尺寸再拖进去。低配NAS上如果同时跑着下载、相册缩略图这些服务,建议并发压缩时限制线程数,或者错开时间跑任务。
5.3 文件无法写入
用容器版Squoosh时,我想把压缩结果直接写到/volume1/compress目录,结果容器一直提示权限不足。原因是容器内的进程用户是随镜像打包的(通常是nobody或者非root用户),对群晖的共享文件夹默认没有写权限。
最简单粗暴的办法是在文件管理器里把compress文件夹的权限设置为“所有人可读写”,但内网环境下这个做法可控性还行,如果要求严格的话,更规范的做法是用UID/GID映射:创建容器时在“高级设置-环境”里添加PUID和PGID,值取你群晖管理员账户的UID/GID(可以通过SSH执行id命令查到),这样容器内的进程就有了对应宿主机用户的写权限。
5.4 群晖DSM 6和7的差异
我的第二台群晖还在跑DSM 6.2,套件中心里没有Container Manager,只有老的Docker套件。两者操作逻辑差别不大,但老版本Docker套件的镜像源在拉取时偶尔会遇到网络超时,多试几次基本能成功。Node.js方案在DSM 6和7上都能跑,套件中心里都有Node.js安装包,所以如果你还在用旧系统,优先推荐Node.js方案,省心。
6. 一点个人体会和后续扩展
把Squoosh挪到群晖上这件事,本质上是把“图片压缩”从一个依赖外部网站的动作,变成了私有网络里的基础设施。我用这套方案之后,最直观的感受是处理图片不再有“上传到别人服务器”的心理负担,批量压缩也不用跟在线网站的免费额度较劲了,几百张照片丢进去跑一圈,输出目录里躺着整整齐齐的压缩文件,总体上非常踏实。
如果你已经部署好Docker版或Node.js版,后续还有几个可以玩的方向:一是结合群晖的Synology Photos相册,写个计划任务定期压缩“恢复”目录里的原图存档;二是给压缩工具套上一个简单的权限层(比如反向代理加口令),让家人也能通过网页访问;三是把压缩结果直接归档到另一个备份目录,实现“原图留存、预览走压缩图”的双份策略。每一步都不复杂,但能让NAS这台设备真正嵌入到你的创作流程里。
