omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello โ€” I'm @olemoritz on Twitter.


    Create and save Live Photo to Camera Roll

    Pythonista
    2
    17
    7855
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • riePat
      riePat last edited by

      Hi guys,

      I have an image (a.heic) and a video file (a.mov) stored in Pythonista's Documents folder. I would like to save both files to Camera Roll so that iOS recognizes them as a Live Photo.

      Is it possible to create instance of Objective-C class 'PHLivePhoto' and access method 'requestLivePhotoWithResourceFileURLs' to load 'a.heic' and 'a.mov' resource files and save the created 'PHLivePhoto' to Camera Roll? How would this be done by using 'objc_util'?

      Any help would be greatly appreciated. Thank you!

      --Pat

      cvp 1 Reply Last reply Reply Quote 0
      • cvp
        cvp @riePat last edited by

        @riePat Is that not working?

        import photos
        photos.create_image_asset('autumn_1440x960.heic')
        
        1 Reply Last reply Reply Quote 0
        • riePat
          riePat last edited by

          Hi cvp,

          saving images by calling photos.create_image_asset() works fine, but I would like to save an image with a related video file so that iOS recognizes both files as live photo. Saving the video by photos.create_image_asset() will not work.

          Any ideas how to handle this? Thanks!

          --Pat

          cvp 2 Replies Last reply Reply Quote 0
          • cvp
            cvp @riePat last edited by

            @riePat I have downloaded an heic.mov from an iPhone 6s and imported In Pythonista.
            I have copied it to camera roll via FileBrowser and the .mov is visible in Photos app.
            But you are right this does not work...

            photos.create_image_asset('iphone6s_4k.mov')
            

            But I suppose that if FileBrowser can do it, there is a way...

            1 Reply Last reply Reply Quote 0
            • cvp
              cvp @riePat last edited by

              @riePat I'll try in objectivec this afternoon, but success not promised ๐Ÿ˜ข

              1 Reply Last reply Reply Quote 0
              • riePat
                riePat last edited by

                Hi cvp,

                thank you for trying! I look forward to your reply.

                --Pat

                cvp 1 Reply Last reply Reply Quote 0
                • cvp
                  cvp @riePat last edited by

                  @riePat Please try this and let me know because I don't have the Files pair

                  from objc_util import *
                  import threading
                  
                  PHPhotoLibrary = ObjCClass('PHPhotoLibrary')
                  PHAssetChangeRequest = ObjCClass('PHAssetChangeRequest')
                  
                  url = nsurl('iphone6s_4k.mov')
                  
                  lib = PHPhotoLibrary.sharedPhotoLibrary()
                  def change_block():
                  	req = PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(url)
                  def perform_changes():
                  	lib.performChangesAndWait_error_(change_block, None)
                  t = threading.Thread(target=perform_changes)
                  t.start()
                  t.join()
                  
                  1 Reply Last reply Reply Quote 0
                  • riePat
                    riePat last edited by

                    Hi cvp,

                    thanks for that script. It adds a video file to Camera Roll. But how can I manage to add an image and a video to Camera Roll so that they will be displayed as a Live Photo?

                    What do you think of method 'requestLivePhotoWithResourceFileURLs' of class 'PHLivePhoto'? Is it possible to create a Live Photo that way in Pythonista?

                    Thank you for your help!

                    --Pat

                    cvp 2 Replies Last reply Reply Quote 0
                    • cvp
                      cvp @riePat last edited by cvp

                      @riePat I'v tried with this method during two hours without success.
                      I agree that my knowledge about heif/heic is zero and that does not help ๐Ÿ˜ข

                      Edit: I have been able to create the PHLivePhoto but not to add it to a PHAsset to add it in the camera roll
                      You are sure that with both files copied to camera roll you can"t do anything?

                      1 Reply Last reply Reply Quote 0
                      • cvp
                        cvp @riePat last edited by

                        @riePat check here

                        1 Reply Last reply Reply Quote 0
                        • riePat
                          riePat last edited by

                          Hi cvp,

                          I really appreciate your effort! How did you manage to create the PHLivePhoto? Could you please share the code?

                          I checked the link you shared: I also thought of some metadata issue, but I have checked 'a.heic' and 'a.mov' again, both have sames dates. I really don't know why it is not working...

                          Do you have any other ideas? Thank you!

                          --Pat

                          cvp 2 Replies Last reply Reply Quote 0
                          • cvp
                            cvp @riePat last edited by

                            Not at home now, busy with granchildren, later

                            1 Reply Last reply Reply Quote 0
                            • cvp
                              cvp @riePat last edited by cvp

                              @riePat Could you Please try this, I can't because I don't have files pair

                              from objc_util import *
                              import threading
                              import ui
                              
                              PHPhotoLibrary = ObjCClass('PHPhotoLibrary')
                              PHAssetCreationRequest = ObjCClass('PHAssetCreationRequest')
                              
                              url_mov  = nsurl('iphone6s_4k.mov')
                              url_heic = nsurl('iphone6s_4k.heic')
                              
                              lib = PHPhotoLibrary.sharedPhotoLibrary()
                              def create_block():
                              	req = PHAssetCreationRequest.creationRequestForAsset()
                              	PHAssetResourceType = 1	# PHAssetResourceTypePhoto
                              	req.addResourceWithType_fileURL_options_(PHAssetResourceType,url_heic,None)
                              	PHAssetResourceType = 9	# PHAssetResourceTypePairedVideo
                              	req.addResourceWithType_fileURL_options_(PHAssetResourceType,url_mov,None)
                              def perform_changes():
                              	lib.performChangesAndWait_error_(create_block, None)
                              t = threading.Thread(target=perform_changes)
                              t.start()
                              t.join()
                              

                              Edit:

                              def create():
                              	req = PHAssetCreati
                              	req.addResourceWithType_fileURL_options_(PHAssetResourceType,url_jpg,None)
                              	PHAssetResourceType = 9	# PHAssetResourceTypePairedVideo
                              	req.addResourceWithType_fileURL_options_(PHAssetResourceType,url_mov,None)
                              def perform_changes():
                              	create_block = ObjCBlock(create, restype=None, argtypes=None)
                              	err_ptr = c_void_p()
                              	ret = lib.performChangesAndWait_error_(create_block,byref(err_ptr))
                              	if err_ptr:
                              		err = ObjCInstance(err_ptr)
                              		print(err)
                              	print('ok=',ret)
                              

                              Shows process not ok, I don't know why ๐Ÿ˜ญ

                              Error Domain=NSCocoaErrorDomain Code=-1 "(null)"
                              
                              1 Reply Last reply Reply Quote 0
                              • cvp
                                cvp last edited by

                                Same error with, thus I'm doing something bad

                                from objc_util import *
                                import time
                                global handler_done
                                handler_done = False
                                def handler(_cmd,obj1_ptr,obj2_ptr):
                                	global handler_done
                                	if obj1_ptr:
                                		obj1 = ObjCInstance(obj1_ptr)
                                	if obj2_ptr:
                                		obj2 = ObjCInstance(obj2_ptr)
                                		print(obj2)
                                	handler_done = True
                                	return
                                	
                                handler_block = ObjCBlock(handler, restype=None, argtypes=[c_void_p, c_void_p, c_void_p])
                                
                                urls = [url_mov,url_jpg]
                                PHLivePhoto = ObjCClass('PHLivePhoto')
                                uiimage = ObjCInstance(ui.Image.named('iob:alert_circled_256'))
                                PHImageContentMode = 0	# PHImageContentModeAspectFit
                                PHLivePhoto.requestLivePhotoWithResourceFileURLs_placeholderImage_targetSize_contentMode_resultHandler_(urls,uiimage,CGSize(0,0),PHImageContentMode,handler_block)
                                
                                while not handler_done:
                                	time.sleep(1)
                                
                                1 Reply Last reply Reply Quote 0
                                • cvp
                                  cvp last edited by cvp

                                  I think we still have to add some metadata to both files to assure they belong to the same pair...

                                  Edit: I don't know from where your both files come but perhaps the script with PHAssetCreationRequest could work for you if your files contain the right needed metadata, what you could check with an Exit viewer (free) app.

                                  A live photo has two resources. They are tied together with an asset identifier (a UUID as a string).

                                  A JPEG; this must have a metadata entry for kCGImagePropertyMakerAppleDictionary with [17 : assetIdentifier] (17 is the Apple Maker Note Asset Identifier key).
                                  A Quicktime MOV encoded with H.264 at the appropriate framerate (12-15fps) and size (1080p). This MOV must have:
                                  Top-level Quicktime Metadata entry for ["com.apple.quicktime.content.identifier" : assetIdentifier]. If using AVAsset you can get this from asset.metadataForFormat(AVMetadataFormatQuickTimeMetadata)
                                  Timed Metadata track with ["com.apple.quicktime.still-image-time" : 0xFF]; The actual still image time matches up to the presentation timestamp for this metadata item. The payload seems to just be a single 0xFF byte (aka -1) and can be ignored. If using an AVAssetReader you can use CMSampleBufferGetOutputPresentationTimeStamp to get this time.
                                  The assetIdentifier is what ties the two items together and the timed metadata track is what tells the system where the still image sits in the movie timeline.

                                  1 Reply Last reply Reply Quote 0
                                  • riePat
                                    riePat last edited by riePat

                                    @cvp, youโ€™re a genius! Thank you so much for the script you shared, it does exactly what is supposed to do :-)

                                    As the files were created by iOS I do not have to modify any metadata. But thanks anyway for the detailed explanation.

                                    โ€”Pat

                                    cvp 1 Reply Last reply Reply Quote 0
                                    • cvp
                                      cvp @riePat last edited by

                                      @riePat ๐Ÿ˜… I didn't know what I could do more...

                                      1 Reply Last reply Reply Quote 0
                                      • First post
                                        Last post
                                      Powered by NodeBB Forums | Contributors