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.


    how to get last video on iphone?

    Pythonista
    3
    41
    7796
    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.
    • cvp
      cvp @frankL last edited by

      @frankL said:

      How can I update the slider to indicate the elapsed time status of the video

      from objc_util import *
      import ui
      AVPlayerItem=ObjCClass('AVPlayerItem')
      AVPlayer=ObjCClass('AVPlayer')
      AVPlayerLayer=ObjCClass('AVPlayerLayer')
      
      url = nsurl('assets-library://asset/asset.MOV?id=71F89028-7FA0-4C53-B6AD-6659BC8458D8&ext=MOV')
      u=ObjCClass('AVURLAsset').alloc().initWithURL_options_(url,None)
      i=AVPlayerItem.playerItemWithAsset_(u)
      p=AVPlayer.playerWithPlayerItem_(i)
      videolayer=AVPlayerLayer.playerLayerWithPlayer_(p)
      
      #define cmtime, for seeking
      import ctypes
      CMTimeValue=ctypes.c_int64
      CMTimeScale=ctypes.c_int32
      CMTimeFlags=ctypes.c_uint32
      CMTimeEpoch=ctypes.c_int64
      class CMTime(Structure):
         _fields_=[('value',CMTimeValue),
         ('timescale',CMTimeScale),
         ('flags',CMTimeFlags),
         ('epoch',CMTimeEpoch)]
         def __init__(self,value=0,timescale=1,flags=0,epoch=0):
            self.value=value
            self.timescale=timescale
            self.flags=flags
            self.epoch=epoch
      c.CMTimeMakeWithSeconds.argtypes=[ctypes.c_double,ctypes.c_int32]
      c.CMTimeMakeWithSeconds.restype=CMTime
      c.CMTimeGetSeconds.argtypes=[CMTime]
      c.CMTimeGetSeconds.restype=c_double
      
      
      class MyView(ui.View):
      	def __init__(self, *args, **kwargs):
      		ui.View.__init__(self, *args, **kwargs)
      		self.background_color = 'white'
      		
      		V=ObjCInstance(self)
      		videolayer.frame=V.bounds()
      		V.layer().addSublayer_(videolayer)
      
      		bplay = ui.ButtonItem()
      		bplay.title = 'play'
      		def b_play_action(sender):
      		    p.play()
      		bplay.action = b_play_action
      		self.update_interval = 0		
      		
      		bpause = ui.ButtonItem()
      		bpause.title = 'pause'
      		def b_pause_action(sender):
      		    p.pause()
      		bpause.action = b_pause_action		
      		self.right_button_items = (bplay, bpause)
      		
      		slider=ui.Slider(frame=(0,0,self.width,20))		
      		#sender.superview.name = str(sender.value*duration_sec)
      		slider.action=self.slider_action
      		slider.bring_to_front()
      		self.slider = slider
      		self.add_subview(slider)
      		
      	def update(self):
      		s = p.currentTime().a/p.currentTime().b
      		self.slider.value = s/duration_sec
      
      	def slider_action(self, sender):
      		self.seek(sender.value*duration_sec)
      		
      	@on_main_thread
      	def seek(self,t):
      		T=c.CMTimeMakeWithSeconds(t,1)
      		p.seekToTime_(T,argtypes=[CMTime],restype=None)
      
      v=MyView(frame=(0,0,500,500))
      v.present('sheet')
      
      duration=i.duration()
      duration_sec=duration.a/duration.b
      #print(duration_sec)
      
      p.play()
      v.update_interval = 0.1	
      
      
      1 Reply Last reply Reply Quote 0
      • cvp
        cvp @frankL last edited by

        @frankL try until

        v.update_interval = 1/60	
        
        1 Reply Last reply Reply Quote 0
        • cvp
          cvp @frankL last edited by

          @frankL Is it what you wanted?

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

            I see that your code works but I'm trying to implement it in a subview and I can't figure out how to use the v.update_interval method.

            cvp 1 Reply Last reply Reply Quote 0
            • frankL
              frankL last edited by

              To clarify, I have a button in the main view that plays a video that the user selects from the main view. The button action instantiates a subview that runs the video and presents the slider, play, pause and stop buttons. The slider works to move the video playback manually but otherwise the slider doesn't display the elapsed time of the video. Any insight you can give me would be appreciated.

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

                @frankL said:

                how to use the v.update_interval method.

                update_interval is not a method but an attribute setting thé interval in seconds between 2 calls to the update méthod in a subclassed view.

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

                  @frankL said:

                  Any insight you can give me would be appreciated

                  It would be easier to help if you post your script.

                  1 Reply Last reply Reply Quote 0
                  • frankL
                    frankL last edited by ccc

                    Here is the code. The function with the view for the video player is "play_action".

                    import ui
                    import csv
                    import os
                    import objc_util
                    from objc_util import *
                    
                    #
                    def show_list_dialog(items=None, *args, **kwargs):
                    	items = items or []
                    	tbl = ui.TableView(**kwargs)
                    	tbl.data_source = ui.ListDataSource(items)
                    	my_sel = {'value': None}
                    	class MyTableViewDelegate (object):
                    		def tableview_did_select(self, tableview, section, row):
                    			my_sel['value'] = tableview.data_source.items[row]
                    			tableview.close()
                    	tbl.delegate = MyTableViewDelegate()
                    	tbl.present(style='sheet')
                    	tbl.wait_modal()
                    	return my_sel['value']
                    #
                    #
                    def open_video_ref():
                    	matrix=[]
                    	my_path=os.path. abspath("dance_video_ref.csv")
                    	with open(my_path,'r',encoding='utf-8') as reader:
                    		reader=csv.DictReader(reader)
                    		for row in reader:
                    			matrix.append([row['Index'], row['Dance'], row['Instructor'], row['Description'], row['Label'], row['url'], row['level'], row['duration']])
                    	return matrix
                    #
                    #		       MAIN PROGRAM             #
                    #
                    
                    #
                    w, h = ui.get_screen_size()
                    h -= 64
                    bh = bw = 80  # label height and button width
                    mg = 10  # margin
                    view = ui.View(name='Dance Lesson Videos', bg_color='#D98880', frame=(0, 0, w, h))
                    
                    dance_instructor_value='Select Instructor(s)'
                    dance_instructor = ui.TextField(frame=(100,15,130,0),border_color='black', border_width=2, text=dance_instructor_value, bordered=True, font=('Arial Rounded MT Bold',15))
                    dance_instructor.height=30
                    dance_instructor.width=130
                    dance_instructor.enabled=False
                    view.add_subview(dance_instructor)
                    
                    #
                    def instructor_action(sender):
                    	global dance_matrix
                    	matrix = open_video_ref()
                    	priority = int(dance_priority.text)
                    	dance_matrix = []
                    	for row in matrix:
                    		if priority == int(row[6]):
                    			dance_matrix.append(row)
                    	instructor_list = ['All']
                    	for row in dance_matrix:
                    		instructor = row[2]
                    		if instructor in instructor_list:
                    			continue
                    		else:
                    			instructor_list.append(instructor)
                    	f = (0, 0, 400, 300)
                    	try:
                    		result = show_list_dialog (instructor_list, frame=f, name='Select an Instructor')
                    		dance_instructor.text=result
                    		if dance_instructor.text != 'All':
                    			new_matrix = []
                    			for row in dance_matrix:
                    				if row[2] == dance_instructor.text:
                    					new_matrix.append(row)
                    			dance_matrix = new_matrix
                    		dance_button.enabled=True
                    		search_dance.text = 'dance name'
                    	except:
                    		dance_instructor.text = 'try again'
                    	pattern_button.enabled=False
                    	pattern_video.text = 'dance pattern'
                    	play_button.enabled=False
                    	return
                    #
                    instructor_button = ui.Button(frame=(10,10,130,0),border_color='black', border_width=2, corner_radius = 10, tint_color = 'black', background_color='#EAECEE', action=instructor_action, font=('Arial Rounded MT Bold',18))
                    instructor_button.title='Instrctr'
                    instructor_button.width=80
                    instructor_button.height=40
                    view.add_subview(instructor_button)
                    
                    #
                    def priority_action(sender):
                    	matrix = open_video_ref()
                    	priority_list = []
                    	for row in matrix:
                    		priority = row[6]
                    		if priority in priority_list:
                    			continue
                    		else:
                    			priority_list.append(priority)
                    	f = (0, 0, 400, 300)
                    	priority_list.sort()
                    	result = show_list_dialog(priority_list, frame=f, name='Select Priority')
                    	dance_priority.text=str(result)
                    	dance_button.enabled=False
                    	dance_instructor.text = 'Select Instructor(s)'
                    	search_dance.text = 'dance name'
                    	pattern_button.enabled=False
                    	pattern_video.text = 'dance pattern'
                    	play_button.enabled=False
                    	return
                    #
                    priority_button = ui.Button(frame=(240,10,130,0),border_color='black', border_width=2, corner_radius = 10, tint_color = 'black', background_color='#EAECEE', action=priority_action, font=('Arial Rounded MT Bold',18))
                    priority_button.title='Priority'
                    priority_button.width=80
                    priority_button.height=40
                    view.add_subview(priority_button)
                    
                    dance_priority_value='0'
                    dance_priority = ui.TextField(frame=(330,15,130,0),border_color='black', border_width=2, text=dance_priority_value, bordered=True, font=('Arial Rounded MT Bold',15))
                    dance_priority.height=30
                    dance_priority.width=30
                    dance_priority.enabled=False
                    dance_priority.alignment=ui.ALIGN_CENTER
                    view.add_subview(dance_priority)
                    
                    dance_value='dance name'
                    search_dance = ui.TextField(frame=(100,65,130,0),border_color='black', border_width=2, text=dance_value, bordered=True, font=('Arial Rounded MT Bold',15))
                    search_dance.height=30
                    search_dance.width=130
                    search_dance.enabled=False
                    view.add_subview(search_dance)
                    
                    #
                    def dance_action(sender):
                    	global dance_matrix
                    	dance_list = []
                    	for row in dance_matrix:
                    		dance = row [1]
                    		if dance in dance_list:
                    			continue
                    		else:
                    			dance_list.append(dance)
                    	f = (0, 0, 400, 300)
                    	try:
                    		result = show_list_dialog(dance_list, frame=f, name='Select a Dance')
                    		search_dance.text=result
                    		new_matrix = []
                    		for row in dance_matrix:
                    			if row[1] == search_dance.text:
                    				new_matrix.append(row)
                    		dance_matrix = new_matrix
                    		pattern_button.enabled=True
                    	except:
                    		search_dance.text = 'try again'
                    	return
                    #
                    dance_button = ui.Button(frame=(10,60,130,30),border_color='black', border_width=2, corner_radius = 10, tint_color = 'black', background_color='#EAECEE', action=dance_action, font=('Arial Rounded MT Bold',18))
                    dance_button.title='Dance'
                    dance_button.width=80
                    dance_button.height=40
                    dance_button.enabled=False
                    view.add_subview(dance_button)
                    
                    #
                    pattern_value='dance pattern'
                    pattern_video = ui.TextView(frame=(100,105,80,0),border_color='black', border_width=2, text=pattern_value, bordered=True, font=('Arial Rounded MT Bold',15))
                    pattern_video.height=65
                    pattern_video.width=260
                    pattern_video.enabled=False
                    view.add_subview(pattern_video)
                    #
                    def pattern_action(sender):
                    	global found_row
                    	global dance_matrix
                    	pattern_list = []
                    	for row in dance_matrix:
                    		if row[4] in pattern_list:
                    			continue
                    		else:
                    			pattern_list.append(row[4])
                    	f = (0, 0, 400, 300)
                    	result = show_list_dialog(pattern_list, frame=f, name='Select a Pattern')
                    
                    	found=False
                    	for row in dance_matrix:
                    		if row[4] == result:
                    			found_row = row
                    			found=True
                    			break
                    	if found:
                    		pattern_video.text=found_row[3]
                    		dance_instructor.text = found_row[2]
                    		play_button.enabled=True
                    	else:
                    		pattern_video.text='none found'
                    	dance_button.enabled=False
                    	return
                    #
                    pattern_button = ui.Button(frame=(10,120,130,30),border_color='black', border_width=2, corner_radius = 10, tint_color = 'black', background_color='#EAECEE', action=pattern_action, font=('Arial Rounded MT Bold',18))
                    pattern_button.title='Pattern'
                    pattern_button.width=80
                    pattern_button.height=40
                    pattern_button.enabled=False
                    view.add_subview(pattern_button)
                    
                    #
                    def play_action(sender):
                    	n = nsurl(found_row[5])
                    	u=ObjCClass('AVURLAsset'). alloc().initWithURL_options_(n,None)
                    	i=AVPlayerItem.playerItemWithAsset_(u)
                    	p=AVPlayer.playerWithPlayerItem_(i)
                    	videolayer=AVPlayerLayer. playerLayerWithPlayer_(p)
                    
                    	v=ui.View(frame=(0,0,500,500))
                    	V=ObjCInstance(v)
                    	videolayer.frame=V.bounds()
                    	V.layer().addSublayer_(videolayer)
                    	v.present('sheet')
                    	#
                    	def play_video_action(sender):
                    		p.play()
                    		return
                    	#
                    	def pause_video_action(sender):
                    		p.pause()
                    		return
                    	#
                    	def stop_action(sender):
                    		p.pause()
                    		seek(0)
                    		slider.value = 0
                    		return
                    	#
                    	def add_spaces(sender):
                    		print('space')
                    		return
                    	#
                    	duration_sec = float(found_row[7])
                    	slider=ui.Slider(frame=(0,0,v.width,110), background_color = 'lightblue')
                    
                    	@on_main_thread
                    	def seek(t):
                    		T=c.CMTimeMakeWithSeconds(t,1)
                    		p.seekToTime_(T,argtypes=[CMTime], restype=None)
                    	#
                    	def slider_action(sender):
                    		seek(sender.value*duration_sec)
                    	slider.action=slider_action
                    	v.add_subview(slider)
                    	#
                    	v.left_button_items = (((ui.ButtonItem(title='  ', action= add_spaces))),(ui.ButtonItem(title='\u23F8',action=pause_video_action)), ((ui.ButtonItem(title='  ', action= add_spaces))),((ui.ButtonItem(title='\u25B6', action= play_video_action))), ((ui.ButtonItem(title='  ', action= add_spaces))),((ui.ButtonItem(title='\u23F9', action= stop_action))))
                    	#
                    	p.play()
                    
                    	return
                    
                    #
                    play_button = ui.Button(frame=(10,170,130,30),border_color='black', border_width=2, corner_radius = 10, tint_color = 'black', background_color='#EAECEE', action=play_action, font=('Arial Rounded MT Bold',18))
                    play_button.title='\u25B6'
                    play_button.width=80
                    play_button.height=40
                    play_button.enabled=False
                    view.add_subview(play_button)
                    
                    
                    
                    AVPlayerItem=ObjCClass('AVPlayerItem')
                    AVPlayer=ObjCClass('AVPlayer')
                    AVPlayerLayer=ObjCClass('AVPlayerLayer')
                    import photos
                    
                    def pick_asset():
                           assets = photos.get_assets(media_type='video')
                           asset = photos.pick_asset(assets)
                           phasset=ObjCInstance(asset)
                           asseturl=ObjCClass('AVURLAsset').alloc().initWithURL_options_(phasset.ALAssetURL(),None)
                           return asseturl
                    #define cmtime, for seeking
                    import ctypes
                    CMTimeValue=ctypes.c_int64
                    CMTimeScale=ctypes.c_int32
                    CMTimeFlags=ctypes.c_uint32
                    CMTimeEpoch=ctypes.c_int64
                    class CMTime(Structure):
                       _fields_=[('value',CMTimeValue),
                       ('timescale',CMTimeScale),
                       ('flags',CMTimeFlags),
                       ('epoch',CMTimeEpoch)]
                       def __init__(self,value=0,timescale=1,flags=0,epoch=0):
                          self.value=value
                          self.timescale=timescale
                          self.flags=flags
                          self.epoch=epoch
                    c.CMTimeMakeWithSeconds.argtypes=[ctypes.c_double,ctypes.c_int32]
                    c.CMTimeMakeWithSeconds.restype=CMTime
                    c.CMTimeGetSeconds.argtypes=[CMTime]
                    c.CMTimeGetSeconds.restype=c_double
                    
                    ############
                    
                    
                    
                    #########################################
                    nav_view = ui.NavigationView(view)
                    nav_view.present('sheet')
                    #########################################
                    
                    1 Reply Last reply Reply Quote 0
                    • JonB
                      JonB last edited by

                      I could be wrong, but it may be that the update method is only called at the top level view, the one that you called present on. So you would need to set the update interval on the top level view,and then implement an update in that view to call update in cvp's custom view.

                      cvp 1 Reply Last reply Reply Quote 0
                      • JonB
                        JonB last edited by

                        ProbBly the "right_ way to do this is to implement an objcblock that can be passed to the AVPlayer's
                        addPeriodicTimeObserver_forInterval_queue_using_.

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

                          JonB, you're over my head on that. If you look at my code, how would I call an update at the top level before the subview is instantiated? And my understanding of objc is very small. I wouldn't know how to implement an objclock to pass to AVPlayer. Suggestions? Thanks.

                          cvp 1 Reply Last reply Reply Quote 0
                          • JonB
                            JonB last edited by

                            Alternatively, edit your post and add the ``` before and after the code.

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

                              @JonB said:

                              the update method is only called at the top level view

                              I don't think so, I have ui.Views that I simulate as buttons to play a gif in their image, and def update works perfectly.

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

                                This post is deleted!
                                1 Reply Last reply Reply Quote 0
                                • cvp
                                  cvp @frankL last edited by cvp

                                  @frankL the problem is that to can use update method, you have to use a subclass of ui.View, thus, replace all your play_action function by

                                  class MyView(ui.View):
                                  	def __init__(self, *args, **kwargs):
                                  		global found_row
                                  		ui.View.__init__(self, *args, **kwargs)
                                  		n = nsurl(found_row[5])
                                  		u=ObjCClass('AVURLAsset'). alloc().initWithURL_options_(n,None)
                                  		i=AVPlayerItem.playerItemWithAsset_(u)
                                  		p=AVPlayer.playerWithPlayerItem_(i)
                                  		videolayer=AVPlayerLayer. playerLayerWithPlayer_(p)
                                  		self.p = p
                                  		self.i = i
                                  		
                                  		self.background_color = 'white'
                                  		
                                  		V=ObjCInstance(self)
                                  		videolayer.frame=V.bounds()
                                  		V.layer().addSublayer_(videolayer)
                                  
                                  		self.update_interval = 0		
                                  		
                                  		self.left_button_items = (((ui.ButtonItem(title='  ', action= self.add_spaces))),(ui.ButtonItem(title='\u23F8',action=self.pause_video_action)), ((ui.ButtonItem(title='  ', action= self.add_spaces))),((ui.ButtonItem(title='\u25B6', action= self.play_video_action))), ((ui.ButtonItem(title='  ', action= self.add_spaces))),((ui.ButtonItem(title='\u23F9', action= self.stop_action))))
                                  				
                                  		self.slider=ui.Slider(frame=(0,0,self.width,110), background_color = 'lightblue')
                                  		self.slider.action=self.slider_action
                                  		self.slider.bring_to_front()
                                  		self.add_subview(self.slider)
                                  		
                                  	def update(self):
                                  		duration=self.i.duration()
                                  		if duration.b == 0:
                                  			return
                                  		self.duration_sec=duration.a/duration.b
                                  		s = self.p.currentTime().a/self.p.currentTime().b
                                  		self.slider.value = s/self.duration_sec
                                  		
                                  	def play_video_action(self,sender):
                                  		self.p.play()
                                  		return
                                  	#
                                  	def pause_video_action(self,sender):
                                  		self.p.pause()
                                  		return
                                  	#
                                  	def stop_action(self,sender):
                                  		self.p.pause()
                                  		self.seek(0)
                                  		self.slider.value = 0
                                  		return
                                  	#
                                  	def add_spaces(self,sender):
                                  		print('space')
                                  		return
                                  
                                  	def slider_action(self, sender):
                                  		self.seek(sender.value*self.duration_sec)
                                  		
                                  	@on_main_thread
                                  	def seek(self,t):
                                  		T=c.CMTimeMakeWithSeconds(t,1)
                                  		self.p.seekToTime_(T,argtypes=[CMTime],restype=None)
                                  		
                                  def play_action(sender):
                                  	global p
                                  
                                  	v=MyView(frame=(0,0,500,500))
                                  	v.present('sheet')
                                  
                                  	v.p.play()
                                  	v.update_interval = 1/60	
                                  
                                  1 Reply Last reply Reply Quote 0
                                  • frankL
                                    frankL last edited by

                                    cvp,
                                    I replaced the play_action function with your code and I get an error "name '@on_main_thread' is not defined". I'm relatively new to python and haven't tried to create and use "class" so there must be something else I need to add somewhere. What should I do? Thanks

                                    cvp 3 Replies Last reply Reply Quote 0
                                    • cvp
                                      cvp @frankL last edited by

                                      @frankL sure that this line is still in the imports...

                                      from objc_util import *
                                      
                                      1 Reply Last reply Reply Quote 0
                                      • cvp
                                        cvp @frankL last edited by cvp

                                        @frankL I'll be away for 2 hours, sorry. Anyway, if problem still occurs, you can post your code again, included in two lines with ``` (you can use the </> button to generate them).

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

                                          @frankL or if you prefer, I post your full script modified with my little part.

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

                                            Apparently I had the 'from objc_util import *' after the class MyView(ui.View):
                                            Once I move it up everything works perfectly. I can't thank you enough.
                                            I retired a few years ago and just started learning Python last summer and Pythonista late last fall so I've got a lot to learn and I really appreciate all of your help and the help from everyone on the omz:forum.

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