Skip to content
rhoopr edited this page Apr 21, 2026 · 10 revisions

EXIF Handling

kei reads EXIF dates on every downloaded photo and can optionally write EXIF, XMP, or sidecar metadata from iCloud back to disk.

Reading EXIF Dates

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.

Write-Through Flags

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.

Supported Formats

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.

Drift Detection

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.

Atomicity

Every write-through path uses .part + atomic rename:

  1. Copy the downloaded file to <file>.meta-tmp.
  2. Patch EXIF / XMP into the copy.
  3. 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.

Merging with Existing Sidecars

--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.

Failure Tracking

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.

Related

Clone this wiki locally