0x00写在前面

有一说一,nextcloud我用了很久了,immich也早久仰大名。最近尝试了一下immich的app,感觉照片同步这块比nextcloud确实要好不少:不仅在同步上比nextcloud好用,还增加了诸如上传后几十天内自动清理相册的功能。最重要的是nextcloud的插件安装之类的非常麻烦,另外docker compose配置一直有问题导致我只能用落后的docker,更新也不方便。现在打算先将照片视频之类的迁移到immich上。

0x01利用immich-go迁移

首先创建一个api key,需要以下权限

  • asset.read
  • asset.statistics
  • asset.update
  • asset.upload
  • asset.copy
  • asset.replace
  • asset.delete
  • asset.download
  • album.create
  • album.read
  • albumAsset.create
  • server.about
  • stack.create
  • tag.asset
  • tag.create
  • user.read
  • job.create
  • job.read

接着运行以下命令(自己改参数)

1
./immich-go upload from-folder --server=http://your-ip:2283 --api-key=your-api-key /path/to/your/photos

对了,顺带一提nginx记得加一行这个,否则稍大一点的图片传不上去

1
client_max_body_size 0;

0x02更改图片识别模型

改一下docker compose的配置先,需要将容器的模型路径引出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
immich-machine-learning:
container_name: immich_machine_learning
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
# Example tag: ${IMMICH_VERSION:-release}-cuda
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
# extends: # uncomment this section for hardware acceleration - see https://docs.immich.app/features/ml-hardware-acceleration
# file: hwaccel.ml.yml
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn] for accelerated inference - use the `-wsl` version for WSL2 where applicable
volumes:
- ${MODEL_CACHE}:/cache
env_file:
- .env
restart: always
healthcheck:
disable: false

${MODEL_CACHE}这个值就在环境变量文件.env里记录了,随便什么地址都行

接着就是下载模型+更改了,我用的git clone,需要提前安装git-lfs

1
git clone https://huggingface.co/immich-app/XLM-Roberta-Large-Vit-B-16Plus
1
2
3
4
5
6
7
8
9
10
11
//模型文件夹的组织架构如下
picpo@picpo-Server:~/immich-app/ml-models$ tree -L 2
.
├── clip
│   └── XLM-Roberta-Large-Vit-B-16Plus
├── facial-recognition
│   └── antelopev2
└── ocr
└── PP-OCRv5_mobile

7 directories, 0 files

0x03中文地图支持

记录一下修改为中文地图的方法,贴一下链接和效果

https://github.com/ZingLix/immich-geodata-cn

0x04备份脚本

AI糊弄的,先留个存档

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
#!/usr/bin/env bash
set -euo pipefail

#################################
# 配置
#################################
IMMICH_DIR="/home/picpo/immich-app"
BACKUP_DIR="/home/picpo/immich_backup"
DATE="$(date +%Y%m%d_%H%M%S)"
ARCHIVE_NAME="immich_backup_${DATE}.tar.gpg"
CHUNK_SIZE="10G"

# 忽略目录
EXCLUDES=(
"geodata"
"i18n-iso-countries"
"ml-models"
)

#################################
# 日志函数
#################################
log() {
echo "[`date '+%F %T'`] $*"
}

#################################
# 退出时自动启动容器
#################################
cleanup() {
log "启动 docker compose"
cd "$IMMICH_DIR"
docker compose up -d
}
trap cleanup EXIT

#################################
# 开始
#################################

log "创建备份目录"
mkdir -p "$BACKUP_DIR"

log "生成随机密码"
PASSWORD_FILE="$BACKUP_DIR/${ARCHIVE_NAME}.password"
PASSWORD="$(openssl rand -base64 48 | tr -dc 'A-Za-z0-9' | head -c 32)"
echo "$PASSWORD" > "$PASSWORD_FILE"
chmod 600 "$PASSWORD_FILE"

log "进入 Immich 目录"
cd "$IMMICH_DIR"

log "停止 docker compose"
docker compose down

#################################
# 计算目录大小(用于进度显示)
#################################
log "计算备份大小..."
TOTAL_SIZE=$(du -sb . | awk '{print $1}')

#################################
# 构建排除参数
#################################
TAR_EXCLUDES=()
for dir in "${EXCLUDES[@]}"; do
TAR_EXCLUDES+=(--exclude="./$dir")
done

#################################
# 打包 + 进度显示 + 加密 + 数字分块
#################################

log "开始打包 + 加密 + 10G 数字分块"

tar -cf - "${TAR_EXCLUDES[@]}" . \
| pv -s "$TOTAL_SIZE" \
| gpg \
--batch \
--yes \
--pinentry-mode loopback \
--passphrase "$PASSWORD" \
--symmetric \
--cipher-algo AES256 \
| split -d -a 3 -b "$CHUNK_SIZE" - "$BACKUP_DIR/${ARCHIVE_NAME}.part-"

log "备份完成"
log "密码文件: $PASSWORD_FILE"

ls -lh "$BACKUP_DIR/${ARCHIVE_NAME}.part-"*

log "全部完成 ✅"

恢复方式

1
2
3
cat immich_backup_xxx.tar.gpg.part-* \
| gpg --batch --yes --passphrase-file backup_xxx.password --decrypt \
| tar -xpf -

0x05同步桌面设备的图片

immich比nextcloud强很多,唯一不行的是没有桌面客户端来同步电脑上的图片,但是可以利用immich-go来曲线救国

macOS上用的是launchd 配置文件每10s同步一次截图文件夹检测到文件夹变动再执行上传

1
nano ~/Library/LaunchAgents/com.picpo.immichgo.upload.plist
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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>

<key>Label</key>
<string>com.picpo.immichgo.upload</string>

<key>ProgramArguments</key>
<array>
<string>/文件夹/immich-go</string>
<string>upload</string>
<string>from-folder</string>
<string>--server=服务器地址</string>
<string>--api-key=你的APIKEY</string>
<string>--folder-as-album=FOLDER</string>
<string>--no-ui</string>
<string>/文件夹/Mac截图</string>
</array>
<![CDATA[
<!-- 每 10 秒 -->
<key>StartInterval</key>
<integer>10</integer>
]]>
<!-- 只在文件夹变化时触发 -->
<key>WatchPaths</key>
<array>
<string>/Users/picpo/Desktop/Mac截图</string>
</array>

<!-- 登录即运行 -->
<key>RunAtLoad</key>
<true/>

<!-- 日志 -->
<key>StandardOutPath</key>
<string>/tmp/immich-go.out</string>

<key>StandardErrorPath</key>
<string>/tmp/immich-go.err</string>

</dict>
</plist>

启动任务

1
launchctl load ~/Library/LaunchAgents/com.picpo.immichgo.upload.plist

windows上用的就是PowerShell+启动项了

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
$watchFolder = "你的文件夹"

$global:seen = New-Object System.Collections.Generic.HashSet[string]

$global:watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $watchFolder
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true

Register-ObjectEvent $watcher Created -Action {
try {
$path = $Event.SourceEventArgs.FullPath

if ($seen.Contains($path)) { return }

$seen.Add($path) | Out-Null
Write-Host "NEW FILE:" $path

Start-Sleep 2

Write-Host "Starting immich-go..."

Start-Process `
-FilePath "C:\文件夹\immich-go.exe" `
-ArgumentList @(
"upload","from-folder",
"--server=服务器地址",
"--api-key=你的APIKEY",
"--into-album=PC_Screenshots",
"--no-ui",
"你的文件夹"
) `
-WindowStyle Hidden `


Write-Host "immich-go started."
}
catch {
Write-Host "ERROR:" $_
}
}

while ($true) { Start-Sleep 1 }

启动文件夹创建一个immich-go-launch.vbs,内容为:

1
2
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "powershell.exe -NoProfile -ExecutionPolicy Bypass -File ""C:\Users\picpo\Documents\Workspace\immich-loop.ps1""", 0, False

0x06ShareX照片日期适配

immich唯一一点不好的就是,对于exif里没有拍摄日期的图像,会上传一个奇怪的日期(并非文件创建日)

ShareX在截图后支持使用动作来在截图后对图片进行操作,用的是exiftool这个小软件,设置的参数界面如下(顺带一提勾选隐藏窗口就能不显示弹出的终端了,代价是不会在右下角显示缩略图了,不过这不重要)

1
-overwrite_original -DateTimeOriginal<FileCreateDate -CreateDate<FileCreateDate -ModifyDate<FileCreateDate "$input"