immich
将本地图像和视频上传到 Immich 服务器,支持批量上传、管理 Album 和公开链接。网络资源下载由 video-downloader 负责;当用户提到"上传到 Immich"、"上传图片"、"备份照片"、"上传视频"、"下载视频并上传 Immich"时使用此技能。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
将本地图像和视频上传到 Immich 服务器,支持批量上传、管理 Album 和公开链接。网络资源下载由 video-downloader 负责;当用户提到"上传到 Immich"、"上传图片"、"备份照片"、"上传视频"、"下载视频并上传 Immich"时使用此技能。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
AI 图片生成与编辑。使用统一 CLI 调用 OpenAI Images、Google Gemini 原生图片 API、火山方舟 Seedream,支持多参考图、mask、批量生成、透明背景后处理,以及 Seedream 5.0 Pro 点选/框选式连续交互编辑。当用户提到生成图片、画图、封面图、配图、AI 生图、改图、修图、参考图编辑、Gemini 生图、Seedream 或交互编辑时使用。
媒体处理工具集(基于 ffmpeg)。当用户需要视频转码、格式转换、压缩到指定大小、调整分辨率/帧率、添加 Logo 或图片水印、设置水印位置/尺寸/透明度、追加片头片尾、音频处理、视频裁剪/剪辑、合并/拼接、修复 m3u 下载损坏视频(faststart/moov atom)时使用。支持品牌视频一体化生成、目标 MB 两遍编码、H.264/H.265/AV1/VP9 批量转码、无损裁剪与合并、mp4 moov 前置修复。
为 Sorb 的 Seedance 2.0 视频生成分析图片或参考视频,编写和优化中文视频提示词、图生视频方案、运镜设计、分镜板、首帧建议、长视频分段方案与剪辑节奏。用户明确提到 Seedance 2.0、图生视频、参考视频复刻、运镜、分镜、首尾帧、视频延长或长视频规划时使用;不要为普通图片生成或与 Seedance 无关的视频任务触发。
下载视频工具。处理抖音短链、抖音作品页、微信视频号 SPH 分享链接,以及 yt-dlp 支持的网站视频下载。 触发场景: - 用户发来视频链接并要求”下载这个视频” - 用户要求下载抖音视频、图文、封面、音乐、JSON、评论 - 用户要求下载 YouTube、Bilibili、X、TikTok 等 yt-dlp 支持站点的视频 - 用户要求下载 weixin.qq.com/sph/ 格式的微信视频号分享链接 - 用户提到”yt-dlp””douyin-downloader””视频下载””抖音短链” - 用户要求获取抖音热搜榜或搜索抖音作品 - 用户要求刷新抖音 Cookie - 用户要求刷新微信视频号或腾讯元宝 Cookie
从静态图片中提取前景元素并分离 UI 组件,支持棋盘格背景去除、绿幕/蓝幕/白幕/黑幕关键色抠图、透视校正。当用户说"提取 UI 元素"、"分离组件"、"去除背景"、"棋盘格背景"、"绿幕抠图"、"checkerboard 抠图"、"抠图"时使用。
从视频中提取帧生成 spritesheet 和独立透明 PNG。当用户说"制作 spritesheet"、"视频转精灵图"、"提取动画帧"、"sprite sheet"、"循环动画"时使用。
| name | immich |
| version | 26.29.38 |
| description | 将本地图像和视频上传到 Immich 服务器,支持批量上传、管理 Album 和公开链接。网络资源下载由 video-downloader 负责;当用户提到"上传到 Immich"、"上传图片"、"备份照片"、"上传视频"、"下载视频并上传 Immich"时使用此技能。 |
| argument-hint | [file-path] [--album album-name] |
| allowed-tools | Bash(uv run *), Read, Glob, Edit |
将图像和视频上传到 Immich 服务器。
{SKILL_DIR} = 本 skill 所在目录{SCRIPTS_DIR} = {SKILL_DIR}/scripts/在当前工作目录、skill 目录、Git 项目根目录或 ~/.agents/agent_config.toml 中配置。查找优先级依次为:当前工作目录、skill 目录、Git 项目根目录、全局配置。
添加:
[immich]
base_url = "https://your-immich-server.com"
api_key = "your-api-key"
default_album = "My Photos" # 可选
public_album_url = "https://your-immich-server.com/s/shared-album-key" # 可选
asset_time_source = "upload" # 可选,upload(默认)或 source
运行方式(重要): 必须从 agent_config.toml 所在目录运行,且需要用
--project 指定 scripts 目录,再通过 python -c 调用 CLI:
# 从全局配置目录运行(推荐)
cd ~/.agents && uv run --project {SCRIPTS_DIR} python -c "from immich.cli import main; main()" upload /path/to/photo.jpg
# 指定 album
cd ~/.agents && uv run --project {SCRIPTS_DIR} python -c "from immich.cli import main; main()" upload /path/to/video.mp4 --album "Vacation"
# 单文件上传并保留网络来源的完整原始描述
cd ~/.agents && uv run --project {SCRIPTS_DIR} python -c "from immich.cli import main; main()" upload /path/to/video.mp4 --description "原标题 #话题1 #话题2"
# 本次上传改用媒体拍摄/创建时间
cd ~/.agents && uv run --project {SCRIPTS_DIR} python -c "from immich.cli import main; main()" upload /path/to/photo.jpg --asset-time source
# 批量上传
cd ~/.agents && uv run --project {SCRIPTS_DIR} python -c "from immich.cli import main; main()" upload /path/to/img1.jpg /path/to/img2.png --album "Trip"
uv run immich upload ...(文档中的简写形式)不工作——该包没有注册
console_scripts 入口点。使用上面的 python -c 调用方式。
如果 Python 脚本上传失败(如遇到时区缺失的 400 错误,见陷阱 #2), 可以用 curl 作为 fallback,之后再调用 API 加入相册:
UPLOAD_AT=$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)
curl -s -X POST "${BASE_URL}/api/assets" \
-H "x-api-key: ${API_KEY}" \
-F "assetData=@/path/to/video.mp4;type=video/mp4" \
-F "deviceAssetId=hermes-$(date +%s)" \
-F "deviceId=hermes-agent" \
-F "fileCreatedAt=${UPLOAD_AT}" \
-F "fileModifiedAt=${UPLOAD_AT}"
视频可能包含旧的 creation_time,Immich 后台提取元数据后会覆盖上述时间;
curl fallback 必须等
GET /api/assets/{id} 返回 hasMetadata=true,再执行:
curl -s -X PATCH "${BASE_URL}/api/assets/${ASSET_ID}" \
-H "x-api-key: ${API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"dateTimeOriginal\": \"${UPLOAD_AT}\"}"
加入默认相册(先查 album ID,再 PUT):
# 查 album ID
ALBUM_ID=$(curl -s "${BASE_URL}/api/albums" -H "x-api-key: ${API_KEY}" | python3 -c "import sys,json;albums=json.load(sys.stdin);print(next(a['id'] for a in albums if a['albumName']=='ALBUM_NAME'))")
# 加入相册
curl -s -X PUT "${BASE_URL}/api/albums/${ALBUM_ID}/assets" \
-H "x-api-key: ${API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"ids\": [\"ASSET_ID\"]}"
# 成功加入公开相册后,向用户展示资源链接
echo "Public URL: ${PUBLIC_ALBUM_URL%/}/photos/${ASSET_ID}"
本 skill 不下载网络资源。用户提供视频 URL 并要求上传 Immich 时,按以下顺序组合两个 skill:
video-downloader 检查 backend 并完成下载。upload 命令;视频号下载还应把完整
Original description 通过 --description 原样传入。public_url 返回给用户。下载文件默认保留。只有用户明确要求清理时,才在确认 Immich 上传成功后删除。
用户直接提供本地文件或附件时,跳过 video-downloader,直接上传。
批量上传指定目录下的文件(默认从 ~/Downloads 上传 mp4 文件):
# 上传 ~/Downloads 下所有 mp4 文件
uv run immich batch-upload
# 上传指定目录下的所有 mp4 和 jpg 文件
uv run immich batch-upload /path/to/photos jpg mp4
# 递归上传所有视频文件(包括子目录)
uv run immich batch-upload /path/to/videos mp4 mkv mov --recursive --album "Videos"
# 上传后不删除本地文件
uv run immich batch-upload --no-delete
uv run immich init
Immich 没法改 originalFileName,但可以在 asset 详情面板的"Description"
字段里写任意文本(实际存储在 asset_exif.description)。如果之前的
上传因为 sanitize 把文件名改成 test.mp4,可以用这个子命令把原始
文件名、作者、来源 URL 写进去:
cd ~/.agents && uv run --project {SCRIPTS_DIR} python -c "from immich.cli import main; main()" \
update-description <ASSET_UUID> "原文件名: xxx.mp4
抖音作者: 某某
抖音ID: 7659048818268179754
原始 URL: https://v.douyin.com/xxxxx/"
references/ghcr-mirroring-and-immich-migration.mdoriginalFileName 不可改、时区必带、中文
文件名实际支持、duplicate/replaced 状态码、description 存在
asset_exif 而非 asset,以及一个通用的 4xx 排障脚本):
references/api-pitfalls-and-debugging.md| 配置项 | 必需 | 说明 |
|---|---|---|
base_url | 是 | Immich 服务器地址,不要包含 /api 后缀;客户端会自动添加 |
api_key | 是 | Immich API 密钥 |
default_album | 否 | 默认上传的 Album 名称 |
public_album_url | 否 | 默认相册的公开分享地址;成功加入该相册后生成资源公开链接 |
asset_time_source | 否 | 时间线时间来源:upload(默认,本次上传时间)或 source(媒体/文件原始时间) |
originalFileName 不可通过 API 改名。 Immich 的 UpdateAssetDto
字段(isFavorite、visibility、dateTimeOriginal、latitude、
longitude、rating、description、livePhotoVideoId)里没有
originalFileName。PUT/PATCH /api/assets/{id} 即使带这个字段
也只更新 updatedAt,文件名不变。想改名必须删除后重新上传。
fileCreatedAt / fileModifiedAt 必须带时区,且媒体元数据可能覆盖它们。 Immich 的 DTO
校验 ISO 8601 datetime 必须带时区(Z 或 +08:00)。
datetime.fromtimestamp(mtime).isoformat() 在 Linux 上返回
2025-07-12T18:49:05.130080(无时区),服务器返回
HTTP 400 {"message":"Validation failed", ...}。
client.py::upload_asset 现在用
datetime.fromtimestamp(mtime, tz=timezone.utc).isoformat().replace("+00:00","Z")
生成 2025-07-12T10:49:05.130080Z 才合法。默认 upload 策略还会等待
hasMetadata=true 后使用运行机器的本地时区偏移 PATCH dateTimeOriginal,
避免 MP4 内嵌发布时间覆盖上传时间或造成时间线分组偏移。
非 ASCII 文件名实际是支持的。 之前 client.py 用
re.sub(r'[^\x00-\x7F]', '_', filename) 把中文文件名替换成 ASCII
下划线(test.mp4),但这个 sanitize 是错误的——Immich 服务器
端能正确处理中文 multipart filename 字段,库里 生日视频.MOV、
IMG_3129.mov 等中英文混合文件名都正常存储。已移除该 sanitize。
真正的 400 原因是 #2 的时区,不是文件名。
base_url 不要包含 /api 后缀。 客户端会自动拼接 /api/assets
等路径。如果配置中写了 /api,最终 URL 会变成 /api/api/assets → 404。
必须使用 default_album 配置。 如果用户在 agent_config.toml
中设置了 default_album,上传时应使用该相册。Python 脚本通过
get_default_album() 自动读取。curl fallback 方式需要手动查 album ID
并调用加入相册 API。
上传返回 duplicate 是正常成功。 服务器对已存在 checksum 的
文件返回 HTTP 200 {"status":"duplicate","id":"<uuid>"}。
client.py::upload_asset 已把这种情况标准化成
{"status":"duplicate","id":"<uuid>"} 返回值,不抛异常。
公开链接只属于默认相册。 配置 public_album_url 后,资源成功加入
default_album 才会返回 public_url,格式为
{public_album_url}/photos/{asset_id}。上传到其他相册或加入相册失败时
不应展示公开链接;duplicate 资源成功加入默认相册后仍应展示。
默认时间策略是本次上传时间。 asset_time_source = "upload" 对新资源和
duplicate 都按本次命令开始上传的时间更新 Immich 时间线。需要保留照片拍摄时间
或视频内嵌创建时间时,配置 source 或单次使用 --asset-time source。
from immich.config import load_config, get_immich_config
from immich.client import ImmichClient
from immich.uploader import ImmichUploader
# 加载配置
load_config()
# 使用客户端
async with ImmichClient() as client:
uploader = ImmichUploader(client)
# 上传本地文件
result = await uploader.upload_file(
Path("photo.jpg"),
album_name="My Photos",
description="原标题 #话题",
)
print(result.get("public_url"))
# 上传多个文件(并行)
await uploader.upload_files([Path("a.jpg"), Path("b.png")], album_name="Photos")