-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(server): extraction of Samsung Motionphoto videos #6337
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, minus the linting.
Done with the draft. Just need to actually test it now and it should be good to go. Do we want to add unit tests for live/motionphoto video extraction? |
If you could add a unit test or two that would be great. |
Needed for unit testing (immich-app/immich#6337)
Needed for unit testing (immich-app/immich#6337)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! :)
Thanks. Going to make one more change so that running the metadata extraction job will fix broken videos. |
2a466b6
to
91de06e
Compare
99af6d1
to
4beaf5b
Compare
Ok this is finally ready for merging. Thanks to everyone who helped! A few notes:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised this works because motionPath is the same for both the old and new motion assets. Saving the new video would overwrite the old motion file, but then you queue the old one for deletion.
I'm surprised this works because motionPath is the same for both the old and new motion assets. Saving the new video would overwrite the old motion file, but then you queue the old one for deletion. @jrasm91 - that's a really good catch. I'm guessing that by the time the code looked like this, my immich instance had all the right assets, so it never triggered that code. I moved the delete before the save. There's no race condition here, right? Meaning await this.jobRepository.queue({ name: JobName.ASSET_DELETION, data: { id: asset.livePhotoVideoId } }); will block until the job completes? |
No, that only queues it. Who knows when it will be deleted. Although, we can also solve this by simply changing how the original path is generated - it doesn't have to be the parent asset's id. I think we could generate a UUID ahead of time, and use that to create the motion asset and motion asset original path. |
Ok this should take care of things. I've been trying to test it but I can't get the dev docker compose to start up because of some weird docker issue. Tried two different machines and same bug on both... If you have a chance to test it please lmk. |
This should finally be ready for merge @jrasm91
|
I'm going to hold my tongue until this is actually merged :D Formatting fixed and tests fixed and updated to have more |
If the filenames are not uniquified, then we can't delete old/corrupt ones
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested this and it worked well. The only thing I noticed was that the broken video could be cached in the browser and that could prevent it from playing successfully immediately afterwards.
Fixes #4873.
The issue is that the current video extraction relies on data length and padding from the XMP inside the EXIF. This happened to work on One UI 5 (the resulting mp4 file was technically invalid, but still worked because the extra bytes were at the end), but stopped working on One UI 6. In any case, the author of exiftool recommends not using the XMP because it doesn't have any fundamental connection to the "Trailer" of the jpeg where the video data actually resides. See https://exiftool.org/forum/index.php?topic=15565.0
Fortunately, exiftool is already able to parse the jpeg trailer data structure, and exiftool-vendored has methods to leverage that. The data structure is somewhat complicated, (see https://github.com/exiftool/exiftool/blob/master/lib/Image/ExifTool/Samsung.pm#L1532), so I think it's unwise to attempt to parse the structure ourselves.
This also adds support for extracting the video from an heic-encoded motionphoto, since it's just a different tag name. (see https://exiftool.org/forum/index.php?topic=7161)
This is a minimally-invasive but naive implementation. Creating a dedicated exiftool singleton for each video that has to be extracted is inefficient and the performance hit would probably be noticeable if you upload a lot of motionphotos at once. Fixing this pretty straightforward; it would just mean refactoring exiftool up from
metadata.repository
intometadata.service
.I also didn't touch any of the existing extraction code. I'm not sure if it's still needed for iOS or other motionphoto implementations (Google?), but it could potentially be removed if not.