RhetTbull / osxphotos

Python app to work with pictures and associated metadata from Apple Photos on macOS. Also includes a package to provide programmatic access to the Photos library, pictures, and metadata.
MIT License
2.04k stars 95 forks source link

add push-exif command to CLI #160

Closed RhetTbull closed 1 year ago

RhetTbull commented 4 years ago

Some people still use photosmeta due to --inplace exif update feature. Add a similar feature to osxphotos to update the metadata of the photos in the actual library without exporting.

RhetTbull commented 2 years ago

Ideas for how this could work:

osxphotos inplace --exiftool --person-keyword --photos-keyword "{person}"

This would add "{person}" template as a keyword in Photos and add person name as keyword to exif data using exiftool (against the original and edited images).

Could be used with or without exiftool. Without it, wouldn't modify originals, only the keywords or description in Photos.

Use all the usual query arguments as well as the regular metadata arguments:

  --exiftool
  --person-keyword      
  --album-keyword                 
  --keyword-template 
  --replace-keywords   
  --description-template 
  --finder-tag-template 
  --finder-tag-keywords           
  --xattr-template 

Also add new --photos-keywords and --photos-description to modify the keywords and/or description in Photos.

RhetTbull commented 1 year ago

push-exif is probably a better name for this. Some of the functionality envisioned above is now present in osxphotos batch-edit. I think that modifying the Photos metadata (batch-edit) and modifying the EXIF data in the original file (push-exif) should be separate functions.

RhetTbull commented 1 year ago

osxphotos push-exif

osxphotos push-exif command

Pushes metadata from Photos to the exif data of the original file (and optionally edited) using exiftool.

Specify which metadata gets pushed:

osxphotos push-exif [--push|--compare] [all keywords location faces date title description favorite]

specify all or subset using one or more of:

all keywords faces date title description

e.g. osxphotos push-exif keywords,faces

--dry-run would show which files would be updated

--verbose would show each field that's written

--include-edited : also write EXIF data to edited files --skip-original-if-edited: similar to export, skips writing EXIF data to original if file is edited. --skip-edited: would it be better to include this than --include-edited?

What about raw? (can EXIF data be written to raw files?)

When run, first reads the metadata from the file and stores it in an undo database (like batch-edit does). Can then run with --undo to revert to the original. This will slow down the process so could also offer a --no-undo that skips the undo database but prompt the user for this.

--compare: use instead of --push and print out a diff for those fields which are different. Or maybe if --compare is used, it doesn't push. Only need to specify --compare when wanting to compare otherwise will push.

Undo database would use SqliteKVStore with key of UUID and value of JSON dict from reading with ExifTool.

--report to write report of what was updated. Support CSV, JSON, and SQLite as export does. --append to append to report See ReportWriter: https://github.com/RhetTbull/osxphotos/blob/main/osxphotos/cli/report_writer.py

Also support the following exiftool options that export supports

  --exiftool-path EXIFTOOL_PATH   Optionally specify path to exiftool; if not
                                  provided, will look for exiftool in $PATH.
  --exiftool-option OPTION        Optional flag/option to pass to exiftool when
                                  using --exiftool. For example, --exiftool-
                                  option '-m' to ignore minor warnings. Specify
                                  these as you would on the exiftool command
                                  line. See exiftool docs at
                                  https://exiftool.org/exiftool_pod.html for
                                  full list of options. More than one option may
                                  be specified by repeating the option, e.g.
                                  --exiftool-option '-m' --exiftool-option '-F'.
  --exiftool-merge-keywords       Merge any keywords found in the original file
                                  with keywords used for '--exiftool' and '--
                                  sidecar'.
  --exiftool-merge-persons        Merge any persons found in the original file
                                  with persons used for '--exiftool' and '--
                                  sidecar'.
  --favorite-rating               When used with --exiftool or --sidecar, set
                                  XMP:Rating=5 for photos marked as Favorite and
                                  XMP:Rating=0 for non-Favorites. If not
                                  specified, XMP:Rating is not set.
  --ignore-date-modified          If used with --exiftool or --sidecar, will
                                  ignore the photo modification date and set
                                  EXIF:ModifyDate to EXIF:DateTimeOriginal; this
                                  is consistent with how Photos handles the
                                  EXIF:ModifyDate tag.
  --person-keyword                Use person in image as keyword/tag when
                                  exporting metadata.
  --album-keyword                 Use album name as keyword/tag when exporting
                                  metadata.
  --keyword-template TEMPLATE     For use with --exiftool, --sidecar; specify a
                                  template string to use as keyword in the form
                                  '{name,DEFAULT}' This is the same format as
                                  --directory.  For example, if you wanted to
                                  add the full path to the folder and album
                                  photo is contained in as a keyword when
                                  exporting you could specify --keyword-template
                                  "{folder_album}" You may specify more than one
                                  template, for example --keyword-template
                                  "{folder_album}" --keyword-template
                                  "{created.year}". See '--replace-keywords' and
                                  Templating System below.
  --replace-keywords              Replace keywords with any values specified
                                  with --keyword-template. By default,
                                  --keyword-template will add keywords to any
                                  keywords already associated with the photo.
                                  If --replace-keywords is specified, values
                                  from --keyword-template will replace any
                                  existing keywords instead of adding additional
                                  keywords.
  --description-template TEMPLATE
                                  For use with --exiftool, --sidecar; specify a
                                  template string to use as description in the
                                  form '{name,DEFAULT}' This is the same format
                                  as --directory.  For example, if you wanted to
                                  append 'exported with osxphotos on [today's
                                  date]' to the description, you could specify
                                  --description-template "{descr} exported with
                                  osxphotos on {today.date}" See Templating
                                  System below.

To implement, the code from photoexporter.py that handles exiftool should be pulled out into a separate EXIFWriter class that can be used both by PhotoExporter and the new push-exif code.

Create a new ExiftoolOptions option configuration class to pass to the writer. In PhotoExporter this can be created from the ExportOptions with no need to modify the export options code. This options class will also need flags specifying which attributes to write in contrast to PhotoExporter which writes almost all the done with a couple exceptions specified by flags.

https://github.com/RhetTbull/osxphotos/blob/1bdd993a542c0fcbebddb270615492aa56a84d6c/osxphotos/photoexporter.py#L1736-L1760

RhetTbull commented 1 year ago

Implemented in v0.63.0 as osxphotos push-exif

RhetTbull commented 1 year ago

@all-contributors please add @Jmuccigr for ideas

allcontributors[bot] commented 1 year ago

@RhetTbull

I've put up a pull request to add @Jmuccigr! :tada:

pdewost commented 5 months ago

Great to see push-exif coming to life as a distant echo to a conversation we had with @RhetTbull in late 2021. My personal use case is the following : I manage my photo library locally and sync them on a regular basis into my iPhone. They appear on iPhone as a separate "On my Mac" category and it seems they do not retain any of the attributes (person names or tags) that would simplify a search on iPhone.

Wondering whether push-exif would simplify this... Did anybody try already ?

PS: same question about adding the metadata in the Finder tags for each photo in the Photos Library, would this approach make exported photos searchable on the iPhone ?

RhetTbull commented 5 months ago

@pdewost exporting to iPhone isn't a supported use case for osxphotos so I'm not sure there's a whole lot osxphotos can do. What I would try is to export the metadata to a test image then copy that image to the phone to see if the iOS version of Photos picks up the keywords etc. If you import a photo into the Mac version of Photos that contains embedded keywords these do get added as keywords in Photos. If this does work, then push-exif might be helpful in your use case.

pdewost commented 5 months ago

@pdewost exporting to iPhone isn't a supported use case for osxphotos so I'm not sure there's a whole lot osxphotos can do. What I would try is to export the metadata to a test image then copy that image to the phone to see if the iOS version of Photos picks up the keywords etc. If you import a photo into the Mac version of Photos that contains embedded keywords these do get added as keywords in Photos. If this does work, then push-exif might be helpful in your use case.

Thank you @RhetTbull for this quick reply ; last point leaves me puzzled. Imported embedded keywords are passed to Photos yet are they transferred to the iPhone Photos app when you sync using the Finder (on Sonoma) ?

RhetTbull commented 5 months ago

Imported embedded keywords are passed to Photos yet are they transferred to the iPhone Photos app when you sync using the Finder (on Sonoma)

I'm sorry, I don't understand what you're asking. What I was suggesting is to try an experiment: sync keywords to a single photo using push-exif then copy that photo to the iPhone and see if the iPhone reads the embedded keywords when the photo is copied into the library. The Mac version of Photos does this. I do not know if the iPhone version of Photos does also.

pdewost commented 5 months ago

So I exported a photo with osxphotos along with its keywords, person names, including adding those to Finder tags. Then I reimported it in my Mac Photo Library before transferring it to my iPhone with cable sync. The tags do not show yet they are detected with tag search. Same for person names.

So the question becomes : the same operation with push-exif does not result in making the photo searchable on iPhone using tags or person names and I do not understand why...

RhetTbull commented 5 months ago

Interesting. I exported an image using --exiftool which applies the same metadata as using push-exif and when I imported that photo into my iPhone (I used AirDrop on the exported image), the phone did index the keywords -- see screenshot below which shows a sample image from the OSXPhotos test library. It took a few minutes before keywords showed up in search.

How are you copying photos to the Phone? Are you doing this from Photos? If so, it's possible Photos is exporting a version of the photo that strips metadata. In this case, it's probably better to export images using osxphotos export --exiftool then drag those into the phone.

IMG_6418

pdewost commented 5 months ago

I copy photos to the phone using the synchronization feature that was before in iTunes/Music and now is part of the Finder on macOS Sonoma. I select albums (including smart albums) and then let the sync happen, via a usb-c cable. All copied photos appear in "on my Mac" section of the iOS Photos album view yet they cannot be searched by tags or by face name.

Using osxphotos push-exif keywords,faces,persons,description --favorite-rating --person-keyword --report 'push_exif_{today.date}.csv' --append --push-edited --selected followed by syncing to the iPhone does not result in keyword indexing.

Using osxphotos export /Volumes/Samsung_X5/osxphotos2024-exports --selected --touch-file --finder-tag-keywords --person-keyword --xattr-template findercomment "{title}{title?{descr?{newline},},}{descr}" --exiftool-merge-keywords --exiftool-merge-persons --exiftool --strip --update followed by importing the photos back into macOS Photos app, then followed by syncing to the iPhone does it.

Could it be because of the fact that I do export the keywords and persons in the Finder Tags and that these are "ingested" into macOS Photos at import ?

Would there be an option for push-exif to also write Finder Tags that could make keywords indexing happen on the iPhone ?

RhetTbull commented 5 months ago

Could it be because of the fact that I do export the keywords and persons in the Finder Tags and that these are "ingested" into macOS Photos at import ?

I would be surprised if that's it. In my test, the iPhone clearly ingested keywords from the EXIF/XMP keywords fields.

I think you need to do some some experiments to isolate certain variables to see exactly what it is. Try an export with only --exiftool, then reimport, then sync. Does that work? Then try an export with only --finder-tag-keywords and reimport then sync. Does that work? In each case, I would start with a "clean" photo so you know exactly what data is being copied. I am unfamiliar with the sync utility so I don't know what it is doing. In my test of using AirDrop of an exported photo, the iPhone clearly read the data from the embedded keywords.

pdewost commented 5 months ago

The iPhone ingests for sure when using Airdrop. What I am trying to do is to work directly in the Photos macOS App where I manage 900Gb and 40 years and make sure that I can find the "synced" pictures in my iPhone in an easier manner than just scrolling through albums. Using the iOS Photos search feature would help if only it were capable of finding people (faces) as well as keywords (tags). So the osxphotos export to Mac and then import in iPhone is impractical...

Now I did test the following with just one image :

1/ osxphotos export /Volumes/Samsung_X5/osxphotos2024-exports --selected --touch-file --exiftool --person-keyword --exiftool-merge-keywords --exiftool-merge-persons --update . The exported photo was immediately reimported in macOS photos App along with its tags plus a face tag. After synchronizing with iPhone it can be searched by tags which was not the case of the original photo.

2/ osxphotos export /Volumes/Samsung_X5/osxphotos2024-exports --selected --touch-file --finder-tag-keywords --person-keyword --xattr-template findercomment "{title}{title?{descr?{newline},},}{descr}" --update does not keep tags at reimport.

3/ running osxphotos push-exif keywords,faces,persons,description --favorite-rating --person-keyword --report 'push_exif_{today.date}.csv' --append --push-edited --selected on the same picture and checking afterwards with the --compare option shows that the updated file's metadata has been indeed updated. Yet as the metadata are left unchanged in the macOS Photos App tags, they actually have no reason to be updated. It seems indeed that the Finder's sync method from Mac to iPhone does not transfer the files themselves, letting the iPhone rebuild its database from the EXIF tags, but rather exports the macOS Photos tags and keywords.

This sucks.

Tried a rebuild of the Photos Library work hoping it maybe would update the Mac's keywords and tag system with the EXIF metadata found in the pictures, yet there was no change. Photos synchronized to the iPhone are arbitralily searchable by keywords (some keywords will return 3 photos instead of dozens...) and none by person name.

As my purpose is to make photos search as easy on iPhone than it is on my Mac, I was wondering whether such dysfunctional behavior would change if I were using referenced photos instead of photos that are imported (and buried) in the Photos Library package. Maybe the export to the iPhone would leverage buried push-exif metadata ?

Sorry but this is very confusing to me...

RhetTbull commented 5 months ago

but rather exports the macOS Photos tags and keywords.

If this is the case, then you can easily use osxphotos batch-edit to set the tags in Photos before the export.

Select one or more photos in Photos then run:

osxphotos batch-edit --keyword "{person}"

This sets the Photos keywords to include the person name.

Are the other settings like title, description, favorite status transferred?