-
-
Notifications
You must be signed in to change notification settings - Fork 5
Exif
kei reads EXIF dates on every downloaded photo and can optionally write EXIF, XMP, or sidecar metadata from iCloud back to disk.
After downloading a JPEG file, the DateTimeOriginal EXIF tag is read. If present, it is used to set the file's modification time so that file managers sort photos by capture date rather than download date.
Regardless of the write-through flags below, the file modification time is always synced to the asset's creation date from iCloud when no embedded EXIF date is available. This keeps chronological ordering correct in file managers.
All write-through is opt-in and defaults to false. Nothing is written to downloaded files unless you pass a flag.
| Flag | What it writes |
|---|---|
--set-exif-datetime |
DateTime, DateTimeOriginal, DateTimeDigitized when missing |
--set-exif-rating |
Rating tag (0x4746) from favorite flag / explicit rating |
--set-exif-gps |
GPS tags from iCloud location, only when the file lacks GPS |
--set-exif-description |
ImageDescription from iCloud description / title |
--embed-xmp |
Full XMP packet with every available metadata field |
--xmp-sidecar |
.xmp sidecar next to the media file, merges with existing sidecars |
--set-exif-* flags target narrow EXIF tags and are useful when you just want ratings or GPS for file-manager browsing.
--embed-xmp and --xmp-sidecar deliver the full metadata record to Lightroom, Darktable, digiKam, Bridge, and other asset managers. They can be combined or used independently.
| Format | EXIF tags | XMP embed | XMP sidecar |
|---|---|---|---|
| JPEG | yes | yes | yes |
| PNG | yes | yes | yes |
| TIFF | yes | yes | yes |
| MP4 | (n/a) | yes | yes |
| MOV | (n/a) | yes | yes |
| HEIC | (n/a) | yes | yes |
| HEIF | (n/a) | yes | yes |
| AVIF | (n/a) | yes | yes |
| Raw / other | - | - | yes |
For HEIC / HEIF / AVIF, the XMP packet is inserted as a MIME item inside the ISO-BMFF meta box via a pure-Rust mp4-atom writer. The encoded image bytes are not touched.
For JPEG / PNG / TIFF / MP4 / MOV, writes go through Adobe's XMP Toolkit (vendored C++).
For formats without a write path, use --xmp-sidecar.
When iCloud metadata changes after download (you favorite a photo, add a keyword, edit the caption), kei detects the change via a metadata_hash comparison at the next sync and queues a rewrite pass. The on-disk file is patched in place without re-fetching pixel bytes.
The marker clears on success and stays on failure so the next sync retries.
Every write-through path uses .part + atomic rename:
- Copy the downloaded file to
<file>.meta-tmp. - Patch EXIF / XMP into the copy.
- Atomic rename
.meta-tmp-> final path.
A RAII guard removes the .meta-tmp on any exit path, including a C++ FFI panic from xmp_toolkit. Sidecar and sync-report writers share one fs_util::atomic_install helper that prefers rename and falls back to copy-to-sibling-then-rename under EXDEV. A crash mid-fallback leaves a sibling tmp file but never exposes a half-written destination.
--xmp-sidecar parses any existing .xmp and layers kei's fields on top rather than overwriting the whole packet. Fields the existing sidecar already set take precedence on conflict, so local edits survive.
A malformed sidecar logs a warning and falls back to a fresh packet.
Write failures (read errors, toolkit errors, sidecar write errors) are logged per-file as warnings and counted across the sync session. The download summary includes the count when any write operations failed - for example: 10 downloaded (2 EXIF failures), 0 failed. The download itself is still considered successful; only the metadata write was skipped.
The /metrics endpoint exposes kei_sync_exif_failures_total for the cumulative counter.