osxphotos: --exiftool and --update don't catch changes in keyword template
Possibly related, but also I guess more trickier to address, I’ve noticed the following behaviour:
- Run export with
updateandexiftoolandkeyword_template = [ "{keyword}", ] - Run export again with
updateandexiftoolandkeyword_template = [ "{keyword}", "{label}", ] - The pics are not exported with the new values on
keywords - As it is not an actual change of the pic, nor a change of metadata but a change of config/data to export is not detected and processed.
- I have a workaround which is to delete the exported files (in batches to run this over several cycles) and run export/update
BTW, I noticed that keyword_template defines the values to be set by exiftool on the keywords and subject fields. I imagine this to be intentional.
_Originally posted by @oPromessa in https://github.com/RhetTbull/osxphotos/issues/621#issuecomment-1034167047_
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 22 (22 by maintainers)
Commits related to this issue
- Fix for #630 — committed to RhetTbull/osxphotos by RhetTbull 2 years ago
- Added exportdb command, removed logic for missing export_db, #630 — committed to RhetTbull/osxphotos by RhetTbull 2 years ago
- Exportdb refactor (#638) * Working on export_db refactor * Added exportdb command, removed logic for missing export_db, #630 * Updated tests * updated docs * Added --config-only, #606 ... — committed to RhetTbull/osxphotos by RhetTbull 2 years ago
This is almost working. The “should update” logic above misses one case: if user ran export with
--exiftoolthen ran again with--updatebut not--exiftool, the logic above would lead to skipping the export even though the file should be re-exported (the signature on disk, which is the exiftool signature, will match what’s in the database).I haven’t tested it yet but I think the same will be true for
--convert-to-jpegUpdate: solved this by adding a bit mask field to the database that stores a bit mask representing the options that make a difference (like exiftool) so it’s easy to check if exporting with a different set of options
All tests passing!
====== 1192 passed, 13 skipped in 554.38s (0:09:14) ======If you want to give the new version a try, it’s in the
exportdb_refactorbranchI want to do some more more testing with my own library before releasing but all the tests are passing including a couple of complex
--update, and--force-updatecases built specifically to catch the errors for this issue.Also, this release adds a new (hidden)
exportdbcommand to osxphotos for doing maintenance on the export database. For example, you can useosxphotos exportdb --check-signaturesto find any exported photos with a signature different than what’s in the database orosxphotos exportdb --touch-fileto update the touch time for all photos. This is useful if you used --touch-time previous to this version as it’ll prevent osxphotos from re-exporting everything when you run--update. The export database also now saves the configuration for the last 10 exports and you can recover the most recent (in case you didn’t save the toml file) withosxphotos --save-config config.toml.If you’re going to try this version, I recommend you backup your export database as osxphotos will migrate the database to a new schema and this cannot be rolled back.
It will by default add (1), etc. to each file unless you specify
--overwriteYou can also run
--update --cleanuptwice to get the same result (this of course results in redundant exports. The first cleanup deletes the pre-existing files and the second--updatewill use the now available original names and--cleanupwill delete the files from the last--update.I’m almost done with this major refactor of the export logic. The code is much simpler to understand and will be far more maintainable as well as doing the “right” thing in all cases I can think of. However, I’m at an impasse with one issue: osxphotos depends on the export database for state information about the export to do
--update. In previous versions, I’ve gone to great lengths in the code to try to do the right thing if for some reason the the export database was missing and user running with--update. I think I’ve found a case where this can be indeterminate and thus may have to drop this “feature” meaning if you delete or lose your export database, you won’t be able to do--updatewithout first doing a full export to rebuild the database. The edge case is this:--exiftool--touch-file--update--exiftoolbut it is possible to run exiftool and have the new file size the same. In this case, the file won’t be updated even though it should be.I think the only safe solution to guarantee the integrity of the export is to remove the code that attempts to rebuild the export database and just require the user to do a full export if the export database is lost.
Progress! This test uses @oPromessa 's toml file to run multiple exports whilst editing photos, etc and verifies --update behaves as expected.
Jotting all this down so I don’t forget it… I’ve been thinking through how to refactor the export code and I think I have a simpler design I can implement. But–this will likely require some schema changes to the export database and may mean everything gets re-exported the first time you run the new code. The current export logic is a bit of a mess because it’s evolved over time as I’ve added features that affect
--update:--exiftool,--convert-to-jpeg,--touch-time, etc. In each case, I’ve tried to adjust the export DB so it doesn’t require a new export and “just works” except that now, with some combinations of options, it “just doesn’t work”.Here’s the current paths a photo can take to get exported (also, yay that Github markdown now supports mermaid):
To properly do
--update,--force-update,--ignore-signature, etc. osxphotos needs to know the following information:--ignore-signaturewas specified. (looks at destination file signature)--person-keyword, etc) change? If so, export the photo. (Looks at stored json string of the inputs that osxphotos would feed to exiftool which captures both changes in Photos and changes in the command line options/templates)--convert-to-jpegand had source images namedIMG_1234.HEICandIMG_1234.JPEGthen ran again with--update --convert-to-jpeg, osxphotos will need to know that the existingIMG_1234.JPEGis not the converted version ofIMG_1234.HEIC. It does this by looking up the UUID associated with a destination file in the export database.--touch-filethen ran again with--update --touch-file, all the files will look different and will be re-exported. osxphotos currently tries to handle this by computing what the file signature would have been had--touch-timebeen specified the first time but this over-complicates the code. I may need to drop this check. I could add a--touch-onlyoption that doesn’t export anything but touches files and updates the database in case user didn’t use--touch-filethen changed their mind.--force-update, need to compare if any metadata for the image changed in Photos since last export. This is currently done by computing a hash of the json string of all photo metadata and storing that in the database.Given this logic, I think something like the following should work (pseudo-code):
Detecting the template change is actually pretty easy (the current export database stores a json string of all the fields sent to exiftool) – it’s the interplay of all the other options that’s been tough. I think I’m just going to rewrite this part of the code from scratch. As I was looking at the code this weekend there are parts where I have no idea why I did something…not good for maintainability! I’m mapping out all the different options that affect
--updateand--force-updateand will try to come up with some cleaner logic for detecting changes. Where at all possible, I’d like osxphotos to “do the right thing” even if the user changes export options between updates. But this could take a little while.--touch-timeis definitely a desirable feature so I want to make sure the other options work with it and--update.No worries and no stress for a quick fix. I have time. And there is always the workaround to delete files on the destination and force
The reason why I use the
touch-timeis to make sure other apps get the pic ‘date taken’ right 'cause they some times get it from the modify time of the pic/video for files like mpg (yikes… I’m converting them to mov soon…) the modify date of the file would be the current exported time.Maybe you could leave it to the user to indicate ‘hey keyword_template changed!’ to make it re-export… and simplify the osxphotos logic.
Working on a fix but it’ll take some time. The interplay between all these options you’re using is ferreting out some bugs in the export logic. Very difficult to determine if a file should be exported with --update as so many things can affect it: did data in Photos change? Did template change? Did photo get edited? Was touch time update? Was photo converted to jpeg? And every combination of each of these. osxphotos currently tries to export a photo only if absolutely needed. (e.g. maybe photo wasn’t changed but the touch-time changed) What if user ran with --touch-time then ran again without it? osxphotos currently won’t export the photos all over it’ll just fix the touch time. But this is complicated by all the other options. It might be easier to export if anything changed regardless of whether it really needs to or not.
It’s
touch_file. I found a bug in the logic: if touch_file is True and the touch signatures of source and destination file match, then the file is not re-exported even if the exifdata changed. It’ll take a little work to re-do the logic.https://github.com/RhetTbull/osxphotos/blob/9c26e5519b2d48f3a0ae80d1cc4a765c12b62d40/osxphotos/photoexporter.py#L1042
In this case, the touch signatures match (
cmp_touch) even though the exif data doesn’t match (cmp_orig)I just tried with your .toml and got the same results you did. So it’s something about the combination of options. I’ll dig deeper!
I’ll take a look. This should have been fixed (I even have a test case for this that shows it’s working). I’ll try with your .toml and see if I can figure out what’s going on.
I just did a test and it worked as expected:
Clean export:
osxphotos export ~/Desktop/export --keyword-template "{keyword}" --exiftool --db tests/Test-10.15.7.photoslibraryProcessed: 27 photos, exported: 33, missing: 3, error: 1Run update, no files updated
osxphotos export ~/Desktop/export --keyword-template "{keyword}" --exiftool --db tests/Test-10.15.7.photoslibrary --updateProcessed: 27 photos, exported: 0, updated: 0, skipped: 33, updated EXIF data: 0, missing: 3, error: 0Add a new keyword-template, some files updated as expected
osxphotos export ~/Desktop/export --keyword-template "{keyword}" --keyword-template "{label}" --exiftool --db tests/Test-10.15.7.photoslibrary --updateProcessed: 27 photos, exported: 0, updated: 6, skipped: 27, updated EXIF data: 6, missing: 3, error: 1Run --update again, no files should be exported
osxphotos export ~/Desktop/export --keyword-template "{keyword}" --keyword-template "{label}" --exiftool --db tests/Test-10.15.7.photoslibrary --updateProcessed: 27 photos, exported: 0, updated: 0, skipped: 33, updated EXIF data: 0, missing: 3, error: 0Yes, this is correct. The metadata field is only calculated when
--force-updateis used.--updateand--force-updatework differently and should not be used interchangeably – you should pick one or the other depending on your use case.--force-updateforces the photo to be updated if any of the metadata in Photos changes, even if this change wouldn’t otherwise trigger an export (e.g. you weren’t using--exiftool).--updateonly exports the photo if the exported photo is different than the one in Photos or if--exiftoolwould produce different metadata. In your case, you want--updateand it should trigger an update based on the new keyword template.OK, I think it’s fixed for real this time in v0.45.10