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.


    having trouble writing a video file to local storage -- ends up corrupted

    Pythonista
    video
    2
    3
    3384
    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.
    • jeff_melton
      jeff_melton last edited by

      My end goal is to use Pythonista to upload video taken on my iPhone to Vimeo by way of their API. Using their official library (installed via StaSH), uploads are easy: Just provide a path to a local file. Generally, I'd like to select a video from Photo Roll, write it to Pythonista's local storage, upload it to Vimeo, then remove it from local storage. I'm writing the file, and it has the correct length in bytes, but the upload fails (it creates a tombstone at Vimeo, a zero-length file), and the file in local storage doesn't play when I try opening it in an external resource (Quick Look -> Save in Dropbox; won't play on phone or desktop). Here's what I have so far (truncating a few bits related to patching metadata into the uploaded file, plus local storage file removal):

      # coding: utf-8
      import vimeo
      import photos
      from io import BytesIO
      from objc_util import ObjCInstance
      
      client = vimeo.VimeoClient(token='my_api_token')
      
      video_asset = photos.pick_asset()
      video_data = video_asset.get_image_data()
      video_bytes = video_data.getvalue()
      filename = str(ObjCInstance(video_asset).filename())
      
      with open(filename, 'wb') as video:
          video.write(video_bytes)
      video.close()
      
      video_uri = client.upload(filename)
      

      I feel like I'm missing something obvious here, but I can't figure out what it is. Any help is much obliged. :)

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

        The photos module doesn't really support video out of the box, and get_image_data will always return image data – for videos, it returns just one frame (the preview image in the Photos library).

        You can use objc_util to expose more functionality of the underlying Photos framework though. Here's a quick demo of how you could use the ObjC bridge to get at the file of a video asset. This isn't tested very thoroughly, and I believe it won't work for e.g. timelapse videos, but it might be good enough for your purposes.

        from objc_util import *
        import threading
        import photos
        
        def get_video_path(asset):
        	if asset.media_type != 'video':
        		raise ValueError('Not a video asset')
        	PHImageManager = ObjCClass('PHImageManager')
        	mgr = PHImageManager.defaultManager()
        	e = threading.Event()
        	result = {}
        	def handler_func(_cmd, _av_asset, _audio_mix, _info):
        		av_asset = ObjCInstance(_av_asset)
        		if av_asset.isKindOfClass_(ObjCClass('AVURLAsset')):
        			asset_url = av_asset.URL()
        			asset_path = str(asset_url.path())
        			result['path'] = asset_path
        		e.set()
        	ph_asset = ObjCInstance(asset)
        	handler = ObjCBlock(handler_func, restype=None, argtypes=[c_void_p]*4)
        	mgr.requestAVAssetForVideo_options_resultHandler_(ph_asset, None, handler)
        	e.wait()
        	return result.get('path', None)
        
        # Demo: Pick a video asset from the library, then copy the video file to Pythonista, and show a QuickLook preview...
        if __name__ == '__main__':
        	asset = photos.pick_asset()
        	video_path = get_video_path(asset)
        	if video_path:
        		import shutil, console, os
        		shutil.copy(video_path, 'video.m4v')
        		console.quicklook(os.path.abspath('video.m4v'))
        	else:
        		print('Could not get video file path')
        
        1 Reply Last reply Reply Quote 0
        • jeff_melton
          jeff_melton last edited by

          @omz: Thank you very much. I'd wondered if I wasn't just getting one frame of the video. This does indeed get me started.

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