LibrePhotos 1.3.0:Rust/TS 实验优化回迁 Django,50k 相册搜索 1.19s→0.56s,升级后先跑 strip_thumbnail_metadata
项目地址:
1.3.0 用 OpenCLIP 这一个开源模型统一了打标和语义搜索;把 Rust、TypeScript 后端实验里验证过的性能优化回迁到 Django,搜索、API、扫描都快了、内存也省了;时间线新增 Filter 把截图和文档挡开;视频在所有浏览器都能播;修掉一批安全漏洞,其中两个是代码执行。所有实例都建议升级,多用户实例应立即升级。
升级后必做
1. 跑一次 strip_thumbnail_metadata
1.2.1 及更早版本创建的缩略图仍带着原照片的 EXIF 和 XMP,包括 GPS 位置,而公开链接会直接把这些缩略图交出去。该命令删掉这些元数据,保留像素和色彩配置,重复运行安全:
# docker compose
docker compose exec backend python manage.py strip_thumbnail_metadata
# 单容器
docker exec librephotos python manage.py strip_thumbnail_metadata
# Windows 独立版
start /wait librephotos.exe manage strip_thumbnail_metadata
2. 等 Calculate Clip Embeddings 跑完
一个 Calculate Clip Embeddings 后台任务会用 OpenCLIP 把所有照片重新嵌入并重新打标一次。它不会先删除任何东西:语义搜索覆盖已转换完成的照片,Things 相册随重新打标逐步填回。
3. Kubernetes 先读 README
deploy/k8s 里的 manifest 现在固定到 1.3.0 和 PostgreSQL 16,此前固定的是 2023w31 和 PostgreSQL 13。对已有安装套用前先读 Kubernetes README。
一个模型统管标签与语义搜索
标签、语义搜索、相似照片现在都来自 OpenCLIP ViT-B/32,由 LAION 在 DataComp-XL 上训练,MIT 许可。它取代了搜索用的 CLIP ViT-B/32 和单独的标签模型,所以一次扫描每张照片只跑一个视觉模型:打标会在同一遍里产出它的搜索嵌入。独立的 clip_embeddings 服务删掉了,站点设置里的模型选项也删掉了,因为没得可选。字幕(LFM2.5-VL)和人脸(InsightFace)不变。
回迁 Django 的性能账
Rust 和 TypeScript 后端实验比 Django 快得多,但大部分差异来自查询、应用层工作和 ML 内存,而不是语言本身。所有适用于 Django 的优化都已进入 LibrePhotos:
- 5 万张照片的相册上,文本搜索耗时约减半,1.19s 降到 0.56s;相册列表、日期列表、用户详情、站点设置、缩略图响应更快且查询更少。
- 重复检测 27 秒完成,此前要跑几个小时。
- 空闲 API 服务内存约减半,3 秒启动,重库按需加载。
- 一次带机器学习的扫描提交 2.25GB,而非实测中的 10.7GB。
时间线 Filter 与分类纠正
时间线新增 Filter 按钮,可选只看照片/视频/两者、隐藏截图、隐藏文档、只看收藏,并支持 Save as default 设为默认。Select all 只作用于时间线当前显示的内容。自动检测分类错了,可以在 lightbox 里改,badge 会显示是检测到的还是你手动设的,带 Undo;也可以在选择菜单把整批标为照片/截图/文档。侧边栏也整理了:Memories 变成时间线顶部的一条 strip,整理类页面移进 Photos 菜单,后台任务用头像周围的进度环显示。
视频按需转码与 Probe Videos
每个视频在扫描时探测一次,存下编解码器、像素格式和色彩传输信息。Web 应用据此询问浏览器能否播放该文件,只对不能播的做转换——例如 Firefox 里的 HEVC——而不是像以前那样把「Always transcode videos」当成唯一播放办法。HDR 视频瓦片上有 HDR badge,缩略图正确 tonemap;Probe Videos 任务为本次发布之前扫描的视频补齐信息。
安全修复
- 人名含换行符时,写人脸标签到文件会把选项注入 ExifTool,令已登录用户能在服务器上执行代码(GHSA-x465-w9j9-42rp)。
- 用户自己的日期与连拍检测规则里的 ExifTool 标签名可在 exif 服务里做同样的事(GHSA-cgq8-jvp9-r3j7)。
- 统一镜像和 Windows 独立版上,特制的
/media/URL 可读取 media 目录之外的文件(GHSA-cf3f-2fmg-mjj6)。 - 缩略图保留了原照片的 GPS 位置和相机信息,公开链接会泄露位置,即使关掉「Share location information」(GHSA-j84j-mc98-7wq3)。
- Nextcloud 服务器地址现在按连接真正使用的主机校验,堵住 1.2.0 所加检查的一个绕过(GHSA-xq77-cj4c-42qr)。1.2.0 里 album 和 select_all owner scope 修复的公告也已发布(GHSA-phvg-g65q-rhq3)。
修复手段:人名只以单行写文件,ExifTool 拒绝任何含换行符的值;日期与连拍规则里的 ExifTool 标签名在保存时和 exif 服务里各校验一次;direct-mode 媒体服务拒绝含 .. 或反斜杠的路径,并检查每个文件都在 media 目录内;缩略图只保留色彩配置,无 EXIF/GPS/XMP。
其他改进
- 前端锁定的用户相册:解锁前相册不能增删照片。
- 用户设置显示 web 上传存到哪里,管理员可设某用户的上传文件夹。
- 移动 App 里设的星级评分保存到服务器并写入文件。
- 前端升到 React 19、Mantine 9、zod 4、Vite 8、TypeScript 6,web 应用全面严格类型;Node.js 24;大量 Renovate 依赖更新。
- 删除用户会关掉其公开相册/照片链接与公开照片(对更早删除的用户也生效),再删第二个用户不再失败。
- Sidecar 等非媒体文件(RawTherapee
.pp3、.aae、Takeout.json)不再把扫描标记为失败;没有扫描文件夹的用户不再让后面所有人的扫描停下。 - Zip 下载流式写盘,在统一镜像、Windows 构建和原生安装上都可用;上传不再被读进内存两次。
- 后端:年份这类数字照片关键词会保留,不再破坏关键词导入。