Skip to content

fix(google-takeout): Live Photo video component matched to no metadata - #1432

Open
jazlaan wants to merge 1 commit into
simulot:mainfrom
jazlaan:fix/live-photo-video-sidecar
Open

jazlaan wants to merge 1 commit into
simulot:mainfrom
jazlaan:fix/live-photo-video-sidecar

Conversation

@jazlaan

@jazlaan jazlaan commented Aug 25, 2026

Copy link
Copy Markdown

What

The video half of a Live Photo pair comes out as missing metadata:

  • Google Takeout writes a supplemental-metadata JSON only for the still image half of a Live Photo pair;
  • the video half gets no sidecar of its own;
  • none of the existing matchers account for that, so the video is reported missing even though the still image right next to it matched fine.

Fixes #1321

Cause

Every matcher requires the target file's own extension to show up somewhere in the reduced JSON name. matchNormal strips .json and collapses supplemental-metadata, but what's left still carries the still image's extension (e.g. IMG_1234.HEIC), and a .MP4 file will never equal that. matchFastTrack, matchForgottenDuplicates and matchEditedName have the same gap for a different reason: none of them account for a still-image-only sidecar being the correct match for a video file.

Fix

matchLivePhotoVideo checks that the target file is a video and that the JSON, once reduced, belongs to an image, with the duplicate index matched between the two. It sits right after matchNormal in the matcher list rather than at the end, since matchForgottenDuplicates/matchEditedName use loose prefix matching that can misfire on a plain video/image pair with no index and no edit suffix.

Verified against a real ~90 GB Takeout export (~17,000 assets): matchLivePhotoVideo correctly matched around 4,700 video files that no other matcher touched, all with the expected index-matched JSON. Also reproduced the exact file layout from #1321 directly against the matcher and confirmed the reported file fails without this change and matches via matchLivePhotoVideo with it.

Notes

Based on main rather than develop, since testing this against a live Immich v3 server needs the v3 support that only landed on main.

…sidecar

Google Takeout writes one supplemental-metadata JSON per Live Photo
pair, named after the still image. The video half never gets a
sidecar of its own, so it fails every existing matcher and comes out
as missing metadata. Most visible on duplicate-indexed pairs, e.g.
IMG_1234(1).HEIC / IMG_1234(1).MP4, where the JSON is
IMG_1234.HEIC.supplemental-metadata(1).json. Reported in simulot#1321 with
the same file layout.

Add matchLivePhotoVideo: it only fires for a video file matched
against a JSON that reduces to an image extension, with a matching
duplicate index.

It has to run right after matchFastTrack/matchNormal, ahead of
matchForgottenDuplicates and matchEditedName. Both of those use loose
prefix matching, and matchEditedName in particular will claim a plain
video/image pair with no edit suffix and no index if it gets there
first, since nothing in its check requires an actual "-edited"
marker on the filename.

Tests cover the base pair, duplicate-indexed pairs, a wrong-index
negative case, a video that keeps using its own dedicated sidecar
instead of falling through to this matcher, and the case where the
duplicate index is part of the original filename rather than an
actual duplicate marker.
@jazlaan
jazlaan requested a review from simulot as a code owner August 25, 2026 08:34

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fails to map indexed Live Photo video component (1).mp4 to .HEIC.supplemental-metadata(1).json

1 participant