def get_video(self, path=None, is_random=False, paused=False, eos="stop", player=None,volume=0): path = "Videos/" + path if is_random: files = os.listdir(path) video_path = path + "/" + random.choice(files) else: print(path) video_path = path if player is not None: player.source=video_path player.state="stop" if paused else "play" player.eos=eos player.volume=volume return player s = { "source": video_path, "state": "stop" if paused else "play", "options": {"allow_stretch": True}, "volume":volume, "size":self.screen.size, "eos":eos } player = Video(**s) player.bind(on_eos=self.on_video_end) return player
class VideoApp(App): def build(self): self.v = Video(source=sys.argv[1], state='play') self.v.bind(state=self.update_state) return self.v def update_state(self, *args): if self.v.state == 'stop': outlet.push_sample([2], time.time()) exit()
class ScreenThree(Screen): def __init__(self, **kwargs): super(ScreenThree, self).__init__(**kwargs) self.video1 = Video(source=os.path.join(original_dir, "cityCC0.mpg")) float_layout = FloatLayout() self.label1 = Label(text="Just a place holder video", opacity=0, pos_hint={ "x": 0, "bottom": 1 }, size_hint=[0.2, 0.1]) # self.label2 = Label(text="loading video", opacity=0) # pos_hint = {"x": 0, "bottom": 1}, size_hint=[0.2, 0.1] self.add_widget(float_layout) float_layout.add_widget(self.label1, index=0) # float_layout.add_widget(self.label2) float_layout.add_widget(self.video1, index=1) self.video1.opacity = 0 def video1_play(self, *dt): do_nothing(dt) self.video1.state = "play" # self.event1 = Clock.schedule_interval(partial(print, self.video1.loaded), 0.5) self.label1.opacity = 1 self.video1.opacity = 1 # self.label2.opacity = 0 self.video1.volume = 1 def on_video1_eos(self, *dt): do_nothing(dt, self) global audio_playback # print(self.video1.loaded) # Clock.schedule_once(self.video1_play) audio_playback = False change_screen_to('screen_two') # self.event1.cancel() def on_enter(self): self.video1.allow_stretch = True self.video1.state = "play" self.label1.opacity = 1 self.video1.bind(eos=self.on_video1_eos) # self.label2.opacity = 1 Clock.schedule_once(self._adjust_opacity, 1) # self.event1 = Clock.schedule_interval(self._check_loaded, 0.5) # def _check_loaded(self, *dt): # if self.video1.loaded: # self.video1.play = True # do_nothing(dt, self.video1.loaded) def _adjust_opacity(self, *dt): do_nothing(dt) self.video1.opacity = 1
def build(self): if len(argv) > 1: filename = argv[1] else: curdir = dirname(__file__) filename = join(curdir, 'softboy.avi') video = Video(source=filename, play=True) scatter = Scatter() video.bind(texture_size=scatter.setter('size')) scatter.add_widget(video) return scatter
class VideoApp(App): def build(self): self.v = Video(source=sys.argv[1], state='play') self.v.bind(state=self.replay) return self.v def replay(self, *args): if self.v.state == 'stop': self.v.state = 'stop' time.sleep(1) exit()
def setup_ui(self): layout = BoxLayout(orientation='vertical') # 请注意,由于 kivy 的官方实现 video 是有 bug 的 # 所以官方文档也是错的,你要按照我给的这样的例子来写才行,这是我看源码扒出来的可行方法 # 自动播放的写法 v = Video(source='demo.mp4', state='play') self.video = v # on_loaded 函数会在视频载入成功后被调用 v.bind(texture_size=self.on_loaded) # on_position_change 函数会在视频播放的时候不断调用,具体你播放一下就好了 v.bind(position=self.on_position_change) layout.add_widget(v) return layout
class VideoScreen(Screen): def __init__(self, **kwargs): super(VideoScreen, self).__init__(**kwargs) self.video = Video(source='test.mkv', state='stop') # Specific function that switches to EscapeRoom screen def switch(self, kwargs): sm.switch_to(PasswordScreen()) # Bind a callback to eos event. Eos is when the video ends self.video.bind(eos=switch) self.add_widget(self.video) # When the screen enters view, play the video def on_enter(self, *args): self.video.state = 'play'
def test_video_unload(self): # fix issue https://github.com/kivy/kivy/issues/2275 # AttributeError: 'NoneType' object has no attribute 'texture' from kivy.uix.video import Video from kivy.clock import Clock from kivy.base import runTouchApp, stopTouchApp from os.path import join, dirname here = dirname(__file__) source = join(here, "..", "..", "examples", "widgets", "softboy.avi") video = Video(source=source, play=True) Clock.schedule_once(lambda x: stopTouchApp(), 1) def unload_video(video, position): if position > 0.01: video.unload() Clock.schedule_once(lambda x: stopTouchApp(), 0.1) video.bind(position=unload_video) runTouchApp(video)
def test_video_unload(self): # fix issue https://github.com/kivy/kivy/issues/2275 # AttributeError: 'NoneType' object has no attribute 'texture' from kivy.uix.video import Video from kivy.clock import Clock from kivy.base import runTouchApp, stopTouchApp from kivy import kivy_examples_dir from os.path import join, dirname, abspath source = abspath(join(kivy_examples_dir, "widgets", "cityCC0.mpg")) video = Video(source=source, play=True) Clock.schedule_once(lambda x: stopTouchApp(), 1) def unload_video(video, position): if position > 0.01: video.unload() Clock.schedule_once(lambda x: stopTouchApp(), 0.1) video.bind(position=unload_video) runTouchApp(video)
def __init__(self, **kwargs): # 父类构造方法 super().__init__(**kwargs) # 进度位置变化 def on_position_change(instance, value): # 打印文本 print('进度位置变化', value) # 持续时间变化 def on_duration_change(instance, value): # 打印文本 print('持续时间变化', value) # 视频 video = Video(source='34.mp4', state='play') # 视频信号与槽 video.bind(position=on_position_change, duration=on_duration_change) # 加组件(视频) self.add_widget(video)
class VideoPlayer(GridLayout): '''VideoPlayer class. See module documentation for more information. ''' source = StringProperty('') '''Source of the video to read. :attr:`source` is a :class:`~kivy.properties.StringProperty` and defaults to ''. .. versionchanged:: 1.4.0 ''' thumbnail = StringProperty('') '''Thumbnail of the video to show. If None, VideoPlayer will try to find the thumbnail from the :attr:`source` + '.png'. :attr:`thumbnail` a :class:`~kivy.properties.StringProperty` and defaults to ''. .. versionchanged:: 1.4.0 ''' duration = NumericProperty(-1) '''Duration of the video. The duration defaults to -1 and is set to the real duration when the video is loaded. :attr:`duration` is a :class:`~kivy.properties.NumericProperty` and defaults to -1. ''' position = NumericProperty(0) '''Position of the video between 0 and :attr:`duration`. The position defaults to -1 and is set to the real position when the video is loaded. :attr:`position` is a :class:`~kivy.properties.NumericProperty` and defaults to -1. ''' volume = NumericProperty(1.0) '''Volume of the video in the range 0-1. 1 means full volume and 0 means mute. :attr:`volume` is a :class:`~kivy.properties.NumericProperty` and defaults to 1. ''' state = OptionProperty('stop', options=('play', 'pause', 'stop')) '''String, indicates whether to play, pause, or stop the video:: # start playing the video at creation video = VideoPlayer(source='movie.mkv', state='play') # create the video, and start later video = VideoPlayer(source='movie.mkv') # and later video.state = 'play' :attr:`state` is an :class:`~kivy.properties.OptionProperty` and defaults to 'play'. ''' play = BooleanProperty(False) ''' .. deprecated:: 1.4.0 Use :attr:`state` instead. Boolean, indicates whether the video is playing or not. You can start/stop the video by setting this property:: # start playing the video at creation video = VideoPlayer(source='movie.mkv', play=True) # create the video, and start later video = VideoPlayer(source='movie.mkv') # and later video.play = True :attr:`play` is a :class:`~kivy.properties.BooleanProperty` and defaults to False. ''' image_overlay_play = StringProperty( 'atlas://data/images/defaulttheme/player-play-overlay') '''Image filename used to show a "play" overlay when the video has not yet started. :attr:`image_overlay_play` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/player-play-overlay'. ''' image_loading = StringProperty('data/images/image-loading.gif') '''Image filename used when the video is loading. :attr:`image_loading` is a :class:`~kivy.properties.StringProperty` and defaults to 'data/images/image-loading.gif'. ''' image_play = StringProperty( 'atlas://data/images/defaulttheme/media-playback-start') '''Image filename used for the "Play" button. :attr:`image_play` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/media-playback-start'. ''' image_stop = StringProperty( 'atlas://data/images/defaulttheme/media-playback-stop') '''Image filename used for the "Stop" button. :attr:`image_stop` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/media-playback-stop'. ''' image_pause = StringProperty( 'atlas://data/images/defaulttheme/media-playback-pause') '''Image filename used for the "Pause" button. :attr:`image_pause` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/media-playback-pause'. ''' image_volumehigh = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-high') '''Image filename used for the volume icon when the volume is high. :attr:`image_volumehigh` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/audio-volume-high'. ''' image_volumemedium = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-medium') '''Image filename used for the volume icon when the volume is medium. :attr:`image_volumemedium` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/audio-volume-medium'. ''' image_volumelow = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-low') '''Image filename used for the volume icon when the volume is low. :attr:`image_volumelow` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/audio-volume-low'. ''' image_volumemuted = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-muted') '''Image filename used for the volume icon when the volume is muted. :attr:`image_volumemuted` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/audio-volume-muted'. ''' annotations = StringProperty('') '''If set, it will be used for reading annotations box. :attr:`annotations` is a :class:`~kivy.properties.StringProperty` and defaults to ''. ''' fullscreen = BooleanProperty(False) '''Switch to fullscreen view. This should be used with care. When activated, the widget will remove itself from its parent, remove all children from the window and will add itself to it. When fullscreen is unset, all the previous children are restored and the widget is restored to its previous parent. .. warning:: The re-add operation doesn't care about the index position of it's children within the parent. :attr:`fullscreen` is a :class:`~kivy.properties.BooleanProperty` and defaults to False. ''' allow_fullscreen = BooleanProperty(True) '''By default, you can double-tap on the video to make it fullscreen. Set this property to False to prevent this behavior. :attr:`allow_fullscreen` is a :class:`~kivy.properties.BooleanProperty` defaults to True. ''' options = DictProperty({}) '''Optional parameters can be passed to a :class:`~kivy.uix.video.Video` instance with this property. :attr:`options` a :class:`~kivy.properties.DictProperty` and defaults to {}. ''' # internals container = ObjectProperty(None) def __init__(self, **kwargs): self._video = None self._image = None self._annotations = '' self._annotations_labels = [] super(VideoPlayer, self).__init__(**kwargs) self._load_thumbnail() self._load_annotations() if self.source: self._trigger_video_load() def _trigger_video_load(self, *largs): Clock.unschedule(self._do_video_load) Clock.schedule_once(self._do_video_load, -1) def on_source(self, instance, value): # we got a value, try to see if we have an image for it self._load_thumbnail() self._load_annotations() if self._video is not None: self._video.unload() self._video = None def _load_thumbnail(self): if not self.container: return self.container.clear_widgets() # get the source, remove extension, and use png thumbnail = self.thumbnail if not thumbnail: filename = self.source.rsplit('.', 1) thumbnail = filename[0] + '.png' self._image = VideoPlayerPreview(source=thumbnail, video=self) self.container.add_widget(self._image) def _load_annotations(self): if not self.container: return self._annotations_labels = [] annotations = self.annotations if not annotations: filename = self.source.rsplit('.', 1) annotations = filename[0] + '.jsa' if exists(annotations): with open(annotations, 'r') as fd: self._annotations = load(fd) if self._annotations: for ann in self._annotations: self._annotations_labels.append( VideoPlayerAnnotation(annotation=ann)) def on_state(self, instance, value): if self._video is not None: self._video.state = value def _set_state(self, instance, value): self.state = value def _do_video_load(self, *largs): self._video = Video(source=self.source, state=self.state, volume=self.volume, pos_hint={'x': 0, 'y': 0}, **self.options) self._video.bind(texture=self._play_started, duration=self.setter('duration'), position=self.setter('position'), volume=self.setter('volume'), state=self._set_state) def on_play(self, instance, value): value = 'play' if value else 'stop' return self.on_state(instance, value) def on_volume(self, instance, value): if not self._video: return self._video.volume = value def on_position(self, instance, value): labels = self._annotations_labels if not labels: return for label in labels: start = label.start duration = label.duration if start > value or (start + duration) < value: if label.parent: label.parent.remove_widget(label) elif label.parent is None: self.container.add_widget(label) def seek(self, percent): '''Change the position to a percentage of the duration. Percentage must be a value between 0-1. .. warning:: Calling seek() before video is loaded has no effect. ''' if not self._video: return self._video.seek(percent) def _play_started(self, instance, value): self.container.clear_widgets() self.container.add_widget(self._video) def on_touch_down(self, touch): if not self.collide_point(*touch.pos): return False if touch.is_double_tap and self.allow_fullscreen: self.fullscreen = not self.fullscreen return True return super(VideoPlayer, self).on_touch_down(touch) def on_fullscreen(self, instance, value): window = self.get_parent_window() if not window: Logger.warning('VideoPlayer: Cannot switch to fullscreen, ' 'window not found.') if value: self.fullscreen = False return if not self.parent: Logger.warning('VideoPlayer: Cannot switch to fullscreen, ' 'no parent.') if value: self.fullscreen = False return if value: self._fullscreen_state = state = { 'parent': self.parent, 'pos': self.pos, 'size': self.size, 'pos_hint': self.pos_hint, 'size_hint': self.size_hint, 'window_children': window.children[:]} # remove all window children for child in window.children[:]: window.remove_widget(child) # put the video in fullscreen if state['parent'] is not window: state['parent'].remove_widget(self) window.add_widget(self) # ensure the video widget is in 0, 0, and the size will be # reajusted self.pos = (0, 0) self.size = (100, 100) self.pos_hint = {} self.size_hint = (1, 1) else: state = self._fullscreen_state window.remove_widget(self) for child in state['window_children']: window.add_widget(child) self.pos_hint = state['pos_hint'] self.size_hint = state['size_hint'] self.pos = state['pos'] self.size = state['size'] if state['parent'] is not window: state['parent'].add_widget(self)
class VideoPlayer(GridLayout): '''VideoPlayer class. See module documentation for more information. ''' source = StringProperty('') '''Source of the video to read. :attr:`source` is a :class:`~kivy.properties.StringProperty` and defaults to ''. .. versionchanged:: 1.4.0 ''' thumbnail = StringProperty('') '''Thumbnail of the video to show. If None, VideoPlayer will try to find the thumbnail from the :attr:`source` + '.png'. :attr:`thumbnail` a :class:`~kivy.properties.StringProperty` and defaults to ''. .. versionchanged:: 1.4.0 ''' duration = NumericProperty(-1) '''Duration of the video. The duration defaults to -1 and is set to the real duration when the video is loaded. :attr:`duration` is a :class:`~kivy.properties.NumericProperty` and defaults to -1. ''' position = NumericProperty(0) '''Position of the video between 0 and :attr:`duration`. The position defaults to -1 and is set to the real position when the video is loaded. :attr:`position` is a :class:`~kivy.properties.NumericProperty` and defaults to -1. ''' volume = NumericProperty(1.0) '''Volume of the video in the range 0-1. 1 means full volume and 0 means mute. :attr:`volume` is a :class:`~kivy.properties.NumericProperty` and defaults to 1. ''' state = OptionProperty('stop', options=('play', 'pause', 'stop')) '''String, indicates whether to play, pause, or stop the video:: # start playing the video at creation video = VideoPlayer(source='movie.mkv', state='play') # create the video, and start later video = VideoPlayer(source='movie.mkv') # and later video.state = 'play' :attr:`state` is an :class:`~kivy.properties.OptionProperty` and defaults to 'stop'. ''' play = BooleanProperty(False, deprecated=True) ''' .. deprecated:: 1.4.0 Use :attr:`state` instead. Boolean, indicates whether the video is playing or not. You can start/stop the video by setting this property:: # start playing the video at creation video = VideoPlayer(source='movie.mkv', play=True) # create the video, and start later video = VideoPlayer(source='movie.mkv') # and later video.play = True :attr:`play` is a :class:`~kivy.properties.BooleanProperty` and defaults to False. ''' image_overlay_play = StringProperty( 'atlas://data/images/defaulttheme/player-play-overlay') '''Image filename used to show a "play" overlay when the video has not yet started. :attr:`image_overlay_play` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/player-play-overlay'. ''' image_loading = StringProperty('data/images/image-loading.gif') '''Image filename used when the video is loading. :attr:`image_loading` is a :class:`~kivy.properties.StringProperty` and defaults to 'data/images/image-loading.gif'. ''' image_play = StringProperty( 'atlas://data/images/defaulttheme/media-playback-start') '''Image filename used for the "Play" button. :attr:`image_play` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/media-playback-start'. ''' image_stop = StringProperty( 'atlas://data/images/defaulttheme/media-playback-stop') '''Image filename used for the "Stop" button. :attr:`image_stop` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/media-playback-stop'. ''' image_pause = StringProperty( 'atlas://data/images/defaulttheme/media-playback-pause') '''Image filename used for the "Pause" button. :attr:`image_pause` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/media-playback-pause'. ''' image_volumehigh = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-high') '''Image filename used for the volume icon when the volume is high. :attr:`image_volumehigh` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/audio-volume-high'. ''' image_volumemedium = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-medium') '''Image filename used for the volume icon when the volume is medium. :attr:`image_volumemedium` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/audio-volume-medium'. ''' image_volumelow = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-low') '''Image filename used for the volume icon when the volume is low. :attr:`image_volumelow` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/audio-volume-low'. ''' image_volumemuted = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-muted') '''Image filename used for the volume icon when the volume is muted. :attr:`image_volumemuted` is a :class:`~kivy.properties.StringProperty` and defaults to 'atlas://data/images/defaulttheme/audio-volume-muted'. ''' annotations = StringProperty('') '''If set, it will be used for reading annotations box. :attr:`annotations` is a :class:`~kivy.properties.StringProperty` and defaults to ''. ''' fullscreen = BooleanProperty(False) '''Switch to fullscreen view. This should be used with care. When activated, the widget will remove itself from its parent, remove all children from the window and will add itself to it. When fullscreen is unset, all the previous children are restored and the widget is restored to its previous parent. .. warning:: The re-add operation doesn't care about the index position of its children within the parent. :attr:`fullscreen` is a :class:`~kivy.properties.BooleanProperty` and defaults to False. ''' allow_fullscreen = BooleanProperty(True) '''By default, you can double-tap on the video to make it fullscreen. Set this property to False to prevent this behavior. :attr:`allow_fullscreen` is a :class:`~kivy.properties.BooleanProperty` defaults to True. ''' options = DictProperty({}) '''Optional parameters can be passed to a :class:`~kivy.uix.video.Video` instance with this property. :attr:`options` a :class:`~kivy.properties.DictProperty` and defaults to {}. ''' # internals container = ObjectProperty(None) _video_load_ev = None def __init__(self, **kwargs): self._video = None self._image = None self._annotations = '' self._annotations_labels = [] super(VideoPlayer, self).__init__(**kwargs) self._load_thumbnail() self._load_annotations() if self.source: self._trigger_video_load() def _trigger_video_load(self, *largs): ev = self._video_load_ev if ev is None: ev = self._video_load_ev = Clock.schedule_once( self._do_video_load, -1) ev() def on_source(self, instance, value): # we got a value, try to see if we have an image for it self._load_thumbnail() self._load_annotations() if self._video is not None: self._video.unload() self._video = None if value: self._trigger_video_load() def on_image_overlay_play(self, instance, value): self._image.image_overlay_play = value def on_image_loading(self, instance, value): self._image.image_loading = value def _load_thumbnail(self): if not self.container: return self.container.clear_widgets() # get the source, remove extension, and use png thumbnail = self.thumbnail if not thumbnail: filename = self.source.rsplit('.', 1) thumbnail = filename[0] + '.png' if not exists(thumbnail): thumbnail = '' self._image = VideoPlayerPreview(source=thumbnail, video=self) self.container.add_widget(self._image) def _load_annotations(self): if not self.container: return self._annotations_labels = [] annotations = self.annotations if not annotations: filename = self.source.rsplit('.', 1) annotations = filename[0] + '.jsa' if exists(annotations): with open(annotations, 'r') as fd: self._annotations = load(fd) if self._annotations: for ann in self._annotations: self._annotations_labels.append( VideoPlayerAnnotation(annotation=ann)) def on_state(self, instance, value): if self._video is not None: self._video.state = value def _set_state(self, instance, value): self.state = value def _do_video_load(self, *largs): self._video = Video(source=self.source, state=self.state, volume=self.volume, pos_hint={ 'x': 0, 'y': 0 }, **self.options) self._video.bind(texture=self._play_started, duration=self.setter('duration'), position=self.setter('position'), volume=self.setter('volume'), state=self._set_state) def on_play(self, instance, value): value = 'play' if value else 'stop' return self.on_state(instance, value) def on_volume(self, instance, value): if not self._video: return self._video.volume = value def on_position(self, instance, value): labels = self._annotations_labels if not labels: return for label in labels: start = label.start duration = label.duration if start > value or (start + duration) < value: if label.parent: label.parent.remove_widget(label) elif label.parent is None: self.container.add_widget(label) def seek(self, percent, precise=True): '''Change the position to a percentage of duration. :Parameters: `percent`: float or int Position to seek, must be between 0-1. `precise`: bool, defaults to True Precise seeking is slower, but seeks to exact requested percent. .. warning:: Calling seek() before the video is loaded has no effect. .. versionadded:: 1.2.0 .. versionchanged:: 1.10.1 The `precise` keyword argument has been added. ''' if not self._video: return self._video.seek(percent, precise=precise) def _play_started(self, instance, value): self.container.clear_widgets() self.container.add_widget(self._video) def on_touch_down(self, touch): if not self.collide_point(*touch.pos): return False if touch.is_double_tap and self.allow_fullscreen: self.fullscreen = not self.fullscreen return True return super(VideoPlayer, self).on_touch_down(touch) def on_fullscreen(self, instance, value): window = self.get_parent_window() if not window: Logger.warning('VideoPlayer: Cannot switch to fullscreen, ' 'window not found.') if value: self.fullscreen = False return if not self.parent: Logger.warning('VideoPlayer: Cannot switch to fullscreen, ' 'no parent.') if value: self.fullscreen = False return if value: self._fullscreen_state = state = { 'parent': self.parent, 'pos': self.pos, 'size': self.size, 'pos_hint': self.pos_hint, 'size_hint': self.size_hint, 'window_children': window.children[:] } # remove all window children for child in window.children[:]: window.remove_widget(child) # put the video in fullscreen if state['parent'] is not window: state['parent'].remove_widget(self) window.add_widget(self) # ensure the video widget is in 0, 0, and the size will be # readjusted self.pos = (0, 0) self.size = (100, 100) self.pos_hint = {} self.size_hint = (1, 1) else: state = self._fullscreen_state window.remove_widget(self) for child in state['window_children']: window.add_widget(child) self.pos_hint = state['pos_hint'] self.size_hint = state['size_hint'] self.pos = state['pos'] self.size = state['size'] if state['parent'] is not window: state['parent'].add_widget(self)
class SlideAndVideoShow(App): def __init__(self): super(SlideAndVideoShow, self).__init__() self.INSTAGRAM_ACCESS_TOKEN = "put your access token here" self.MOST_RECENT_PHOTOS_AND_VIDEOS_URL = "https://api.instagram.com/v1/users/self/media/recent/?access_token={}".format( self.INSTAGRAM_ACCESS_TOKEN) self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH = "./instagram_photos_and_videos/" self.INI_FILE = "./instagram_slide_and_video_show.ini" self.title = "Instagram Slide and Video Show" self.HOUR_IN_SECONDS = 60 * 60 # default configuration settings, used to create instagram_slide_and_video_show.ini if it doesn't already exist self.SECONDS_BEFORE_CHANGING_PHOTO = 15 self.PHOTO_AND_VIDEO_DISPLAY_ORDER_DIRECTORY = "directory" self.PHOTO_AND_VIDEO_DISPLAY_ORDER_RANDOM = "random" self.PHOTO_AND_VIDEO_DISPLAY_ORDER_SORTED = "sorted" self.PHOTO_AND_VIDEO_DISPLAY_ORDER = self.PHOTO_AND_VIDEO_DISPLAY_ORDER_RANDOM self.SOUND_ON = 1 self.SOUND_OFF = 0 self.VIDEO_VOLUME_ON_OR_OFF = self.SOUND_ON # get stored configuration settings self.get_preferences_from_ini_file() # download any new photos or videos self.download_any_new_instagram_photos_or_videos() # get the filenames of all newly and/or previously-downloaded photos and videos self.photos_and_videos = self.get_photo_and_video_filenames() self.current_image_index = -1 def get_preferences_from_ini_file(self): if os.path.isfile(self.INI_FILE): # if the .ini file exists, read in the configuration settings config = ConfigParser.RawConfigParser() config.read(self.INI_FILE) self.PHOTO_AND_VIDEO_DISPLAY_ORDER = config.get( "DisplaySettings", "photo_and_video_display_order") self.SECONDS_BEFORE_CHANGING_PHOTO = int( config.get("DisplaySettings", "seconds_before_changing_photo")) self.VIDEO_VOLUME_ON_OR_OFF = int( config.get("DisplaySettings", "video_volume_on_or_off")) else: # or if it doesn't exist, create it with the default settings self.create_ini_file() def create_ini_file(self): # create the ini file with the default settings the first time you run the program config = ConfigParser.RawConfigParser(allow_no_value=True) ini_file = open(self.INI_FILE, 'w') config.add_section("DisplaySettings") config.set( 'DisplaySettings', '; Valid display order settings are directory, random, or sorted') config.set("DisplaySettings", "photo_and_video_display_order", self.PHOTO_AND_VIDEO_DISPLAY_ORDER) config.set("DisplaySettings", "seconds_before_changing_photo", self.SECONDS_BEFORE_CHANGING_PHOTO) config.set("DisplaySettings", "video_volume_on_or_off", self.VIDEO_VOLUME_ON_OR_OFF) config.write(ini_file) ini_file.close() def download_any_new_instagram_photos_or_videos(self, value=None): # create the instagram_photos_and_videos subdirectory if it doesn't already exist if not os.path.isdir(self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH): os.mkdir(self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH) print( "Checking for any new Instagram photos or videos at {} ...".format( datetime.now())) internet_connection = True # get URLs, captions, etc. on the 20 most recent Instagram photos and videos try: json_data = json.loads( requests.get(self.MOST_RECENT_PHOTOS_AND_VIDEOS_URL).text) except: internet_connection = False print( "Unable to reach Instagram ... check your Internet connection. Showing stored photos and videos." ) if internet_connection: new_photos_and_videos_downloaded = False # and check to see whether or not they have already been downloaded try: for photo_or_video in json_data["data"]: if "videos" in photo_or_video: photo_or_video_url = photo_or_video["videos"][ "standard_resolution"]["url"] else: photo_or_video_url = photo_or_video["images"][ "standard_resolution"]["url"] photo_or_video_filename = photo_or_video_url[ photo_or_video_url.rindex("/") + 1:] if not os.path.isfile( self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH + photo_or_video_filename): new_photos_and_videos_downloaded = True if photo_or_video["caption"]: print('Downloading and saving "{}"'.format( photo_or_video["caption"]["text"].encode("utf8" ) if photo_or_video["caption"] else "...")) else: print('Downloading and saving "{}"'.format( photo_or_video_filename)) photo_or_video_file = requests.get( photo_or_video_url).content with open( self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH + photo_or_video_filename, 'wb') as handler: handler.write(photo_or_video_file) except: print("Instagram error:", json_data) if new_photos_and_videos_downloaded: # update the list of filenames in the instagram_photos_and_videos subdirectory self.get_photo_and_video_filenames() else: print("No new photos or videos found.") # check for new photos and videos once an hour Clock.schedule_once(self.download_any_new_instagram_photos_or_videos, self.HOUR_IN_SECONDS) def on_position_change(self, instance, value): # I'm doing it this way because eos wasn't always firing at the end of a video, # plus position isn't updated often enough to get all the way to the duration value. # If the program hangs at the end of a video you may need to increase the .3 value # (which means .3 of a second) a little more. if value > self.video_duration - .3: self.video.state = "stop" self.next_photo_or_video() def on_duration_change(self, instance, value): self.video_duration = value def on_texture_change(self, instance, value): # I'm doing it this way because I couldn't get loaded or on_load to actually fire, # but texture has reliably only been there only after a video finishes loading. if self.video.texture: self.video.opacity = 1 self.photo.opacity = 0 def build(self): # This line is for running under Windows but crashes things on the Raspberry Pi # Window.fullscreen = "auto" Window.show_cursor = False self.photo = Image() self.photo.allow_stretch = True # Without this line the Raspberry Pi starts blacking out photos after a few images. self.photo.nocache = True self.video = Video(allow_stretch=True, options={ 'eos': 'stop', 'autoplay': True }) self.video.bind(position=self.on_position_change, duration=self.on_duration_change, texture=self.on_texture_change) self.video.opacity = 0 self.video.allow_stretch = True self.video.nocache = True self.video.volume = self.VIDEO_VOLUME_ON_OR_OFF self.screen = FloatLayout() self.screen.add_widget(self.photo) self.screen.add_widget(self.video) Clock.schedule_once(self.next_photo_or_video, 1) return self.screen def next_photo_or_video(self, value=None): if self.PHOTO_AND_VIDEO_DISPLAY_ORDER in [ self.PHOTO_AND_VIDEO_DISPLAY_ORDER_DIRECTORY, self.PHOTO_AND_VIDEO_DISPLAY_ORDER_SORTED ]: self.current_image_index = (self.current_image_index + 1) % len( self.photos_and_videos) elif self.PHOTO_AND_VIDEO_DISPLAY_ORDER == self.PHOTO_AND_VIDEO_DISPLAY_ORDER_RANDOM: self.current_image_index = random.randint( 0, len(self.photos_and_videos) - 1) next = self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH + self.photos_and_videos[ self.current_image_index] if next.endswith(".jpg"): self.photo.source = next self.video.opacity = 0 self.photo.opacity = 1 Clock.schedule_once(self.next_photo_or_video, self.SECONDS_BEFORE_CHANGING_PHOTO) else: self.video.source = next self.video.state = "play" def get_photo_and_video_filenames(self): # get all the jpg and mp4 filenames in the instagram_photos_and_videos subdirectory photo_and_video_filenames = [ file for file in os.listdir(self.LOCAL_PHOTO_AND_VIDEO_DIRECTORY_PATH) if file.endswith(".jpg") or file.endswith(".mp4") ] if self.PHOTO_AND_VIDEO_DISPLAY_ORDER == self.PHOTO_AND_VIDEO_DISPLAY_ORDER_SORTED: photo_and_video_filenames.sort() if not photo_and_video_filenames: # If there are no stored photos and/or videos, and the program was not able to download any, # you need to fix your Internet connection and/or Instagram Access Token. print("No stored photos or videos found. Make sure that you're") print("(1) connected to the Internet, and") print( "(2) that you've obtained an Instagram Access Token for the Instagram account you want to use, and entered it correctly as the self.INSTAGRAM_ACCESS_TOKEN value at the beginning of the code," ) print("and then try again.") exit() return photo_and_video_filenames
class MainScreen(Screen): foldername = "" filename = "" frame_per_sec = "" sr = None ss = None video = None logger = None def __init__(self, **kwargs): self.name = 'MainScreen' super(MainScreen, self).__init__() from kivy.app import App app = App.get_running_app() self.ids.select_folder_label.text = app.config.get("CustSettings", "defaultFolder") self.ids.frame_per_sec.text = app.config.get("CustSettings", "framePerSec") self.ids.file_name.text = app.config.get("CustSettings", "defaultFileName") MSToolbar = self.ids.MainScreen_Toolbar MSToolbar.left_action_items = [["play" ,self.play_video]] MSToolbar.right_action_items = [["file-search" ,self.file_manager_open] ,["camera" ,self.start_recording] ,["camera-party-mode" ,self.stop_recording ]] self.ss = SettingsClass() self.ids.screen_resolution.text = str(self.ss.get_screen_resolution()) #def build(self): # return Builder.load_string(mainscreen_kv) def file_manager_open(self, widget): raw_path = filechooser.choose_dir() if raw_path: self.ids.select_folder_label.text = raw_path[0] def start_recording(self,widget): self.foldername = self.ids.select_folder_label.text self.filename = self.ids.file_name.text self.frame_per_sec = self.ids.frame_per_sec.text if self.foldername is None or self.foldername == "": Toast().toast("Please select a valid folder...") if self.filename is None or self.filename == "": Toast().toast("Please select a valid filename...") if self.frame_per_sec is None or self.frame_per_sec == "": Toast().toast("Please select a valid rate of frame per seconds...") try: if not self.sr: self.sr = RecordClass(foldername = self.foldername ,filename = self.filename ,frame_per_sec = self.frame_per_sec) self.sr.start_recording() except Exception as e: print("Error: ", __name__, " Exception ", e) applogger().logger.error('{ModuleName} - Error = {Exception}'.format(ModuleName=__name__, Exception = e)) def stop_recording(self,widget): try: if self.sr: self.sr.stop_recording() except Exception as e: print("Error: ", __name__, " Exception ", e) applogger().logger.error('{ModuleName} - Error = {Exception}'.format(ModuleName=__name__, Exception = e)) def play_video(self,widget): try: self.foldername = self.ids.select_folder_label.text self.filename = self.ids.file_name.text if self.foldername is None or self.foldername == "": Toast().toast("Please select a valid folder...") if self.filename is None or self.filename == "": Toast().toast("Please select a valid filename...") self.filename = os.path.join(self.foldername, self.filename) if self.video: self.ids.videoContainer.remove_widget(self.video) self.video = None self.video = Video() self.video.source = self.filename self.video.state = 'play' #self.video.options = {'eos':'stop'} self.video.bind(eos=self.VideoDone) self.video.allow_stretch = True self.ids.videoContainer.add_widget(self.video) except Exception as e: print("Error: ", __name__, " Exception ", e) applogger().logger.error('{ModuleName} - Error = {Exception}'.format(ModuleName=__name__, Exception = e)) def VideoDone(self,value,value2): #print("video Done",value,value2) self.video.state = 'stop' self.video.unload() applogger().logger.info('{ModuleName} - {Message}'.format(ModuleName=__name__,Message="video completed successfully"))
class VideoPlayer(GridLayout): '''VideoPlayer class, see module documentation for more information. ''' source = StringProperty(None) '''Source of the video to read :data:`source` a :class:`~kivy.properties.StringProperty`, default to None. ''' thumbnail = StringProperty(None) '''Thumbnail of the video to show. If None, it will try to search the thumbnail from the :data:`source` + .png. :data:`thumbnail` a :class:`~kivy.properties.StringProperty`, default to None. ''' duration = NumericProperty(-1) '''Duration of the video. The duration is default to -1, and set to real duration when the video is loaded. :data:`duration` is a :class:`~kivy.properties.NumericProperty`, default to -1. ''' position = NumericProperty(0) '''Position of the video between 0 and :data:`duration`. The position is default to -1, and set to real position when the video is loaded. :data:`position` is a :class:`~kivy.properties.NumericProperty`, default to -1. ''' volume = NumericProperty(1.0) '''Volume of the video, in the range 0-1. 1 mean full volume, 0 mean mute. :data:`volume` is a :class:`~kivy.properties.NumericProperty`, default to 1. ''' play = BooleanProperty(False) '''Boolean, indicates if the video is playing. You can start/stop the video by setting this property. :: # start playing the video at creation video = VideoPlayer(source='movie.mkv', play=True) # create the video, and start later video = VideoPlayer(source='movie.mkv') # and later video.play = True :data:`play` is a :class:`~kivy.properties.BooleanProperty`, default to False. ''' image_overlay_play = StringProperty( 'atlas://data/images/defaulttheme/player-play-overlay') '''Image filename used to show an "play" overlay when the video is not yet started. :data:`image_overlay_play` a :class:`~kivy.properties.StringProperty` ''' image_loading = StringProperty('data/images/image-loading.gif') '''Image filename used when the video is loading. :data:`image_loading` a :class:`~kivy.properties.StringProperty` ''' image_play = StringProperty( 'atlas://data/images/defaulttheme/media-playback-start') '''Image filename used for the "Play" button. :data:`image_loading` a :class:`~kivy.properties.StringProperty` ''' image_pause = StringProperty( 'atlas://data/images/defaulttheme/media-playback-pause') '''Image filename used for the "Pause" button. :data:`image_pause` a :class:`~kivy.properties.StringProperty` ''' image_volumehigh = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-high') '''Image filename used for the volume icon, when the volume is high. :data:`image_volumehigh` a :class:`~kivy.properties.StringProperty` ''' image_volumemedium = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-medium') '''Image filename used for the volume icon, when the volume is medium. :data:`image_volumemedium` a :class:`~kivy.properties.StringProperty` ''' image_volumelow = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-low') '''Image filename used for the volume icon, when the volume is low. :data:`image_volumelow` a :class:`~kivy.properties.StringProperty` ''' image_volumemuted = StringProperty( 'atlas://data/images/defaulttheme/audio-volume-muted') '''Image filename used for the volume icon, when the volume is muted. :data:`image_volumemuted` a :class:`~kivy.properties.StringProperty` ''' annotations = StringProperty(None) '''If set, it will be used for reading annotations box. ''' fullscreen = BooleanProperty(False) '''Switch to a fullscreen view. This must be used with care. When activated, the widget will remove itself from its parent, remove all children from the window and add itself to it. When fullscreen is unset, all the previous children are restored, and the widget is readded to its previous parent. .. warning:: The re-add operation doesn't care about it's children index position within the parent. :data:`fullscreen` a :class:`~kivy.properties.BooleanProperty`, default to False ''' allow_fullscreen = BooleanProperty(True) '''By default, you can double-tap on the video to make it fullscreen. Set this property to False to prevent this behavior. :data:`allow_fullscreen` a :class:`~kivy.properties.BooleanProperty`, default to True ''' options = DictProperty({}) '''Optionals parameters can be passed to :class:`~kivy.uix.video.Video` instance with this property. :data:`options` a :class:`~kivy.properties.DictProperty`, default to {} ''' # internals container = ObjectProperty(None) def __init__(self, **kwargs): self._video = None self._image = None self._annotations = None self._annotations_labels = [] super(VideoPlayer, self).__init__(**kwargs) self._load_thumbnail() self._load_annotations() def on_source(self, instance, value): # we got a value, try to see if we have an image for it self._load_thumbnail() self._load_annotations() def _load_thumbnail(self): if not self.container: return self.container.clear_widgets() # get the source, remove extension, and use png thumbnail = self.thumbnail if thumbnail is None: filename = self.source.rsplit('.', 1) thumbnail = filename[0] + '.png' self._image = VideoPlayerPreview(source=thumbnail, video=self) self.container.add_widget(self._image) def _load_annotations(self): if not self.container: return self._annotations_labels = [] annotations = self.annotations if annotations is None: filename = self.source.rsplit('.', 1) annotations = filename[0] + '.jsa' if exists(annotations): with open(annotations, 'r') as fd: self._annotations = load(fd) if self._annotations: for ann in self._annotations: self._annotations_labels.append( VideoPlayerAnnotation(annotation=ann)) def on_play(self, instance, value): if self._video is None: self._video = Video(source=self.source, play=True, volume=self.volume, pos_hint={ 'x': 0, 'y': 0 }, **self.options) self._video.bind(texture=self._play_started, duration=self.setter('duration'), position=self.setter('position'), volume=self.setter('volume')) self._video.play = value def on_volume(self, instance, value): if not self._video: return self._video.volume = value def on_position(self, instance, value): labels = self._annotations_labels if not labels: return for label in labels: start = label.start duration = label.duration if start > value or (start + duration) < value: if label.parent: label.parent.remove_widget(label) elif label.parent is None: self.container.add_widget(label) def seek(self, percent): '''Change the position to a percentage of duration. Percentage must be a value between 0-1. .. warning:: Calling seek() before video is loaded have no impact. ''' if not self._video: return self._video.seek(percent) def _play_started(self, instance, value): self.container.clear_widgets() self.container.add_widget(self._video) def on_touch_down(self, touch): if not self.collide_point(*touch.pos): return False if touch.is_double_tap and self.allow_fullscreen: self.fullscreen = not self.fullscreen return True return super(VideoPlayer, self).on_touch_down(touch) def on_fullscreen(self, instance, value): window = self.get_parent_window() if not window: Logger.warning('VideoPlayer: Cannot switch to fullscreen, ' 'window not found.') if value: self.fullscreen = False return if not self.parent: Logger.warning('VideoPlayer: Cannot switch to fullscreen, ' 'no parent.') if value: self.fullscreen = False return if value: self._fullscreen_state = state = { 'parent': self.parent, 'pos': self.pos, 'size': self.size, 'pos_hint': self.pos_hint, 'size_hint': self.size_hint, 'window_children': window.children[:] } # remove all window children for child in window.children[:]: window.remove_widget(child) # put the video in fullscreen if state['parent'] is not window: state['parent'].remove_widget(self) window.add_widget(self) # ensure the video widget is in 0, 0, and the size will be reajusted self.pos = (0, 0) self.size = (100, 100) self.pos_hint = {} self.size_hint = (1, 1) else: state = self._fullscreen_state window.remove_widget(self) for child in state['window_children']: window.add_widget(child) self.pos_hint = state['pos_hint'] self.size_hint = state['size_hint'] self.pos = state['pos'] self.size = state['size'] if state['parent'] is not window: state['parent'].add_widget(self)
class Karaotool(FloatLayout): def __init__(self, **kwargs): super(Karaotool, self).__init__(**kwargs) self.source = kwargs.get('source', None) if self.source == None: self.selecttextfile = Popup(title='Select the lirycs') self.selecttextfile.content = BoxLayout(orientation='vertical') self.selecttextfile.content.add_widget(Button(text='Seleccionar archivo') ) self.selecttextfile.content.add_widget(Button(text='Insertar texto') ) self.selecttextfile.open() else: self.base_filename = os.path.splitext(self.source)[0] with open(self.base_filename + '.kot') as f: #open karaotool text file self.content = f.readlines() self.line = 0; self.video = Video(source=self.source, state='play', allow_stretch=True, keep_ratio=False) self.video.bind(on_loaded=self.on_loaded) self.kar_english = LabelShadow(text='KARAOKELAND', size_hint_y=None, color=(0,0,0,1), font_size=32 ) self.add_widget(self.video) self.add_widget(self.kar_english) #si existe el archivo con los tiempos if os.path.exists(self.base_filename + '.kos'): self.kar_spanish = LabelShadow(text='KARAOKELAND ESP', size_hint_y=1, color=(0,0,0,1), font_size=32 ) self.add_widget(self.kar_spanish) self.fsteps = open(self.base_filename + '.kos') #steps self.steps = self.fsteps.readlines() try: self.efsteps = open(self.base_filename + '.koe') #subtitulos en lenguaje traducido self.esteps = self.efsteps.readlines() except: pass #Clock.schedule_interval(self.stepchecker, .1) self.video.bind(position=self.on_position) self.cursteptime = self.steps[self.line] else: self.btn_stepline = Button(text='Iniciar !', #size_hint=(1,None), on_press=self.nextline ) self.add_widget(self.btn_stepline, index=len(self.children) ) #open for steps creation self.fsteps = open(self.base_filename + '.kos', 'w+') #karaotool steps def on_loaded(self, w): print("Iniciando video") def on_position(self, w, val): if val > float(self.cursteptime): try: if hasattr(self, "old_kar_english"): self.remove_widget(self.old_kar_english) self.old_kar_english = self.kar_english #subir titulo Animation(y=self.old_kar_english.y+50, opacity=.5, duration=.5).start(self.old_kar_english) #self.kar_english.y += 80 self.kar_english = LabelShadow(text=self.content[self.line], size_hint_y=None, color=(0,0,0,1), font_size=32 ) self.add_widget(self.kar_english) try: self.kar_spanish.text = self.esteps[self.line] except: pass self.line += 1 #print "Step: ", self.video.position self.cursteptime = self.steps[self.line] except: self.kar_english.text = "END" self.kar_spanish.text = "FIN" def nextline(self, w): try: #advance one line self.kar_english.text = self.content[self.line] self.line += 1 #self.kar_english.pos.y += 200 self.fsteps.write(str(self.video.position) + '\n') except: self.kar_english.text = "FIN"
def phone(self): button = Button(text='挂断', size_hint=(0.3, 0.15), pos_hint={ 'x': .35, 'y': .05 }) #button.pos_x = 370 #label = Label(text='内容',size_hint=(None, None),size=(300,500)) #初始化摄像头,此时Play=False camera = Camera(id='camera', resolution=(480, 640), play=False, pos=(0, -80)) phoneTime = Label(text="00:00", pos_hint={'x': .15, 'y': .55}) #filename = 'E:\\PythonProjects\\project_kivy\\venv\\share\\kivy-examples\\widgets\\cityCC0.mpg' #filename = 'http://192.168.0.100:8080/' #filename = 'udp://@:192.168.0.100:1234' #filename = 'rtsp://192.168.0.100:8554/play' filename = 'rtsp://192.168.0.100:8554/play' #filename = 'http://192.168.0.100:6060' ''' 当两次连接时,可以正常看视频,当有视频出现,显示视频纹理 size默认值为(100,100) ?添加部件通话时长 连接成功后,得到视频数据时,显示(如何判断) VLC RTSP通过UDP实现,Gstream通过什么? ''' video = Video(source=filename, play='True', pos=(0, 120), volume=0.8) #通话时间 count = 0 relaytiveLayout = RelativeLayout(id='phone') relaytiveLayout.add_widget(camera) relaytiveLayout.add_widget(phoneTime) relaytiveLayout.add_widget(video) relaytiveLayout.add_widget(button) # label = Label(text='内容',size_hint=(None, None)) # floatLayout = FloatLayout(size_hint=(None, None),size=(400, 600)) # floatLayout.add_widget(label) # floatLayout.add_widget(relaytiveLayout) #覆盖整个窗口 popup = Popup(title='正在与谁通话', content=relaytiveLayout, size_hint=(None, None), size=(300, 500), auto_dismiss=False) #self.proxy_ref.add_widget(popup) #print(popup.parent) popup.id = 'popup' #button.pos_x = popup.center_x + (popup.size[0] - button.size[0])/2 #print(camera.size) #print(self.children[0].children) #print(self.ids.popup) #print(camera.properties()) #print(self.id['camera']) #print(type(self.id['popup'])) #print(popup.proxy_ref) ''' 摄像头没有释放,因为属性play值为True ''' button.bind(on_press=popup.dismiss) #button.bind(on_touch_down=cv2.) #button.bind(on_press=) #popup.bind(on_dismiss=self.play) popup.open() for widget in self.walk(): print('{} -> {}'.format(widget, widget.id)) # if isinstance(widget,RelativeLayout): # #print('{} -> {}'.format(widget,widget.id)) # for child in widget.walk(): # print('{} -> {}'.format(child, child.id)) #为什么需要obj,其他值也可以,或许需要它来绑定事件的对象 def closeCamera(obj): print(camera.play) #print(str(obj)) camera.play = False print(camera.play) def closeVideo(obj): video.play = False video.unload() Clock.unschedule(phone_time_callback) def displayPhoneTime(*largs): # obj is float # print('obj is',type(largs)) # print(largs) nonlocal count count = count + 1 #print(count) #true #print(str(video.duration)) phoneTime.text = str(s2t(count)) phone_time_callback = Clock.schedule_interval(displayPhoneTime, 1.) video.bind(on_play=phone_time_callback) #video.bind(play=phone_time_callback) button.bind(on_press=closeCamera) button.bind(on_press=closeVideo) # 稍后启动摄像头 camera.play = True
class TestApp(App): def build(self): # open config.ini to access the user's settings self.config = configparser.ConfigParser() self.config.read(os.environ['HOME'] + "/.config_showoff.ini") # ******************* DECIDE WINDOW SIZE ******************* # in fullscreen is enable go full screen; otherwise use width and height provided if ConfigStuff.get_config_video_fullscreen(self.config): Window.fullscreen = "auto" else: # set the width and height from config.ini Window.size = ( ConfigStuff.get_config_video_width(self.config), ConfigStuff.get_config_video_height(self.config)) # ******************* DECIDE WHAT VIDEO IS PLAYED ******************* # set the directory where the videos will be taken from self.video_directory = ConfigStuff.get_config_video_directory(self.config) # get the list of video files found self.video_list = PlaylistFromDir.create_playlist(self.video_directory) # the number of the file form video_list currently played self.curr_video_iterator = -1 # todo: [ERROR ] [Image ] Error loading texture , try to deal with it at some point self.video1 = Video(source="./1_Second_of_Blank.mp4", state="play", volume=0) self.video1.fullscreen = True self.video1.allow_stretch = True self.video1.image_loading = "./GUI/loading.png" self.video1.pos_hint = {"center_x": .5, "center_y": .5} # when the video reaches its end, on_eos is called (eos= end of stream) self.video1.bind(position=self.on_position_change, eos=self.on_eos) # ******************* DEAL UI STUFF ******************* self.label_help = Label( text="Approach your hand to control the Billboard. Hover over a button for 2s to activate it.", color=(1, 0, 0, 1)) self.label_help.pos_hint = {"center_x": .5, "center_y": 0.98} self.button_loop = Button(text="Reset", background_normal="./GUI/loop.png", border=(0, 0, 0, 0), size_hint=(.2, .2), color=(1, 0, 0, 1)) self.button_loop.pos_hint = {"center_x": 0.85, "center_y": 0.2} self.button_loop.opacity = 0.5 self.button_loop.bind(on_press=self.callback_button_loop) self.button_next = Button(text="NEXT", background_normal="./GUI/arrow_next.png", border=(0, 0, 0, 0), size_hint=(.2, .2), color=(1, 0, 0, 1)) self.button_next.pos_hint = {"center_x": 0.85, "center_y": 0.5} self.button_next.opacity = 0.5 self.button_next.bind(on_press=self.callback_button_next) self.button_previous = Button(text="PREVIOUS", background_normal="./GUI/arrow_previous.png", border=(0, 0, 0, 0), size_hint=(.2, .2), color=(1, 0, 0, 1)) self.button_previous.pos_hint = {"center_x": 0.15, "center_y": 0.5} self.button_previous.opacity = 0.5 self.button_previous.bind(on_press=self.callback_button_previous) self.button_next_ppt = Button(text="NEXT SLIDE", background_normal="./GUI/arrow_next_2.png", border=(0, 0, 0, 0), size_hint=(.2, .2), color=(1, 0, 0, 1)) self.button_next_ppt.pos_hint = {"center_x": 0.85, "center_y": 0.7} self.button_next_ppt.opacity = 0.5 self.button_next_ppt.bind(on_press=self.callback_button_next_ppt) self.button_previous_ppt = Button(text="PREVIOUS SLIDE", background_normal="./GUI/arrow_previous_2.png", border=(0, 0, 0, 0), size_hint=(.2, .2), color=(1, 0, 0, 1)) self.button_previous_ppt.pos_hint = {"center_x": 0.15, "center_y": 0.7} self.button_previous_ppt.opacity = 0.5 self.button_previous_ppt.bind(on_press=self.callback_button_previous_ppt) self.label_help_ppt = Label(text="The power point will pause if you approach your hand", color=(1, 0, 0, 1)) self.label_help_ppt.pos_hint = {"center_x": .5, "center_y": 0.02} # ******************* DEAL WITH LAYOUT ******************* self.root = FloatLayout(size=Window.size) self.root_video = FloatLayout(size=Window.size) self.root_UI = FloatLayout(size=Window.size) self.root_UI.opacity=0.8 if ConfigStuff.get_config_kinect_enable(self.config): self.faceAndEmotionAnalyser = apiFaceAndEmotion.apiFaceDetectAndClassifier() self.handTracking = HandTracking.MyHandTrackingApp() self.handTracking.pos_hint = {"center_x": .5, "center_y": .5} self.root_UI.add_widget(self.label_help) self.root_video.add_widget(self.video1) self.root.add_widget(self.root_video) self.root.add_widget(self.root_UI) # ******************* VIDEO MANAGEMENT ATTRIBUTES ******************* self.playlist_management_event = None # ******************* PPT MANAGEMENT ATTRIBUTES ******************* self.list_of_correct_extension_image = (".jpg", ".png") self.delay_image = ConfigStuff.get_config_image_delay(self.config) self.playing_ppt = False self.bool_ppt_UI_shown = False self.next_slide = False self.previous_slide = False self.bool_show_UI = False self.event_ppt = None # used to cancel several power point management at the same time self.iterator_check_if_click = 0 self.time_limit_beetween_clicks = 2 # in seconds # ******************* USER MANAGEMENT ATTRIBUTES ******************* self.seen_users = set() self.current_people = None self.smart_video_choice = ConfigStuff.get_config_smart_video_enable( self.config) and ConfigStuff.get_config_kinect_enable(self.config) # ******************* CALL LOOPS ******************* Clock.schedule_interval(self.check_mouse_position, 1) Clock.schedule_interval(self.hide_mouse_if_unmoved, 10) return self.root def callback_button_loop(self, instance): print("button loop") if(self.video1.source.endswith(self.list_of_correct_extension_image)): filename, file_extension = os.path.splitext(self.video1.source) # extract image number number_old = re.search('(\d+)$', filename).group(0) number_new = 1 # replace the current image number to the next one filename = re.sub(str(number_old) + "$", str(number_new), filename) self.video1.source = filename + file_extension self.video1.reload() self.set_ppt_event(Clock.schedule_once(self.play_next_image, self.delay_image)) else: self.video1.seek(0) def callback_button_next(self, instance): print("from button next") self.set_playlist_management_event(Clock.schedule_once(partial(self.playlist_management_next), 0)) def callback_button_previous(self, instance): print("from button previous") self.set_playlist_management_event(Clock.schedule_once(partial(self.playlist_management_previous), 0)) def callback_button_next_ppt(self, instance): self.next_slide = True self.set_ppt_event(Clock.schedule_once(self.play_next_image, 0)) def callback_button_previous_ppt(self, instance): self.previous_slide = True self.set_ppt_event(Clock.schedule_once(self.play_next_image, 0)) def check_users(self): self.current_people = self.faceAndEmotionAnalyser.check_who_it_is() for name in self.current_people: if name not in self.seen_users: self.seen_users.add(name) self.show_greetings("Hi " + name, 400, (1, 0, 0, 1)) self.faceAndEmotionAnalyser.quitAndSave() self.faceAndEmotionAnalyser = apiFaceAndEmotion.apiFaceDetectAndClassifier() def check_users_watching_habits(self): # sort the list in accordance to what they have seen # print("Before:", self.video_list) list_video_with_score = [] for video in self.video_list: list_video_with_score.append([video, 0]) # print("Before 0:", list_video_with_score) # for all the people in front for person in self.current_people: parser = configparser.ConfigParser() parser.read("./pics/" + person + '.ini') # for all the videos found for i in range(len(self.video_list)): # if the video has been seen if parser.has_option("WATCHING_HABITS", self.video_list[i]): # add a score base on how many time it was seen, and when was the last time # todo: maybe think of a better formula list_video_with_score[i] = (list_video_with_score[i][0], list_video_with_score[i][1] + parser.getint("WATCHING_HABITS", self.video_list[i]) / ( time.time() - parser.getfloat("WATCHING_HABITS_TIME_TICKS", self.video_list[i]))) # for all the video # sort based on their score # print("Before1:", list_video_with_score) list_video_with_score = sorted(list_video_with_score, key=lambda score: score[1]) # sort by score # print("After 1:", list_video_with_score) # put the previously shown video at the end index = -1 for i in range(len(list_video_with_score)): if (list_video_with_score[i][0] == self.video1.source): index = i break if (index != -1): list_video_with_score.append(list_video_with_score.pop(index)) self.video_list = [] for video in list_video_with_score: self.video_list.append(video[0]) # print("After 2:", self.video_list) def update_users_watching_habits(self): if (not self.video1.source == "./1_second_of_blank.mp4"): # for all the people in front for person in self.current_people: parser = configparser.ConfigParser() parser.read("./pics/" + person + '.ini') # if the person has already seen the video if (parser.has_section("WATCHING_HABITS")): try: parser.set("WATCHING_HABITS", self.video1.source, str(parser.getint("WATCHING_HABITS", self.video1.source) + 1)) except: parser.set("WATCHING_HABITS", self.video1.source, str(1)) # set it to the current time parser.set("WATCHING_HABITS_TIME_TICKS", self.video1.source, str(time.time())) parser.set("WATCHING_HABITS_TIME_DATE", self.video1.source, str(time.asctime(time.localtime(time.time())))) else: # create the section parser.add_section("WATCHING_HABITS") parser.add_section("WATCHING_HABITS_TIME_TICKS") parser.add_section("WATCHING_HABITS_TIME_DATE") parser.set("WATCHING_HABITS", self.video1.source, str(1)) # set it to the current time parser.set("WATCHING_HABITS_TIME_TICKS", self.video1.source, str(time.time())) parser.set("WATCHING_HABITS_TIME_DATE", self.video1.source, str(time.asctime(time.localtime(time.time())))) # print("writing in:",person+'.ini' ) with open("./pics/" + person + '.ini', "w") as config_file: parser.write(config_file) # decide which video is played next def playlist_management_next(self, dt=None): if (self.playing_ppt or self.video1.source.endswith(self.list_of_correct_extension_image)): self.root_UI.remove_widget(self.label_help_ppt) if (self.bool_show_UI): self.root_UI.remove_widget(self.button_next_ppt) self.root_UI.remove_widget(self.button_previous_ppt) self.bool_ppt_UI_shown = False self.playing_ppt = False filename, file_extension = os.path.splitext(self.video1.source) # extract image number number_old = re.search('(\d+)$', filename).group(0) number_new = 1 # replace the current image number to the next one filename = re.sub(str(number_old) + "$", str(number_new), filename) self.video1.source = filename + file_extension # print("new:", self.video1.source) self.video1.state = 'pause' self.video_list = PlaylistFromDir.create_playlist(self.video_directory) if not self.video_list: print("no video to play") self.video1.source = "./1_Second_of_Blank.mp4" self.video1.state = 'play' else: # todo check users activity with App and adjust list if (self.smart_video_choice): # check who is there self.check_users() if(self.current_people): # check what the people there have seen and choose a content self.check_users_watching_habits() self.video1.source = self.video_list[0] # the most appropriate is the first one # for those there, add the chosen content to their watching habits self.update_users_watching_habits() if(not self.current_people): self.curr_video_iterator = self.video_list.index( self.video1.source) if self.video1.source in self.video_list else 0 self.curr_video_iterator += 1 if (len(self.video_list) == self.curr_video_iterator): self.curr_video_iterator = 0 self.video1.source = self.video_list[self.curr_video_iterator] if (self.video1.source.endswith(self.list_of_correct_extension_image)): self.video1.source = self.video1.source self.playing_ppt = True self.root_UI.add_widget(self.label_help_ppt) if (self.bool_show_UI): self.root_UI.add_widget(self.button_next_ppt) self.root_UI.add_widget(self.button_previous_ppt) self.bool_ppt_UI_shown = True self.set_ppt_event(Clock.schedule_once(self.play_next_image, self.delay_image)) else: self.video1.state = 'play' print("Playing:", self.video1.source) # decide which video is played next def playlist_management_previous(self, dt=None): if (self.playing_ppt): self.root_UI.remove_widget(self.label_help_ppt) if (self.bool_show_UI): self.root_UI.remove_widget(self.button_next_ppt) self.root_UI.remove_widget(self.button_previous_ppt) self.bool_ppt_UI_shown = False self.playing_ppt = False filename, file_extension = os.path.splitext(self.video1.source) # extract image number number_old = re.search('(\d+)$', filename).group(0) number_new = 1 # replace the current image number to the next one filename = re.sub(str(number_old) + "$", str(number_new), filename) self.video1.source = filename + file_extension self.video1.state = 'pause' self.video_list = PlaylistFromDir.create_playlist(self.video_directory) if not self.video_list: print("no video to play") self.video1.source = "./1_Second_of_Blank.mp4" self.video1.state = 'play' else: self.curr_video_iterator = self.video_list.index( self.video1.source) if self.video1.source in self.video_list else 0 self.curr_video_iterator -= 1 if (self.curr_video_iterator < 0): self.curr_video_iterator = len(self.video_list) - 1 self.video1.source = self.video_list[self.curr_video_iterator] # todo check users activity with App and adjust list if (self.smart_video_choice): # check who is there self.check_users() if(self.current_people): # for those there, add the chosen content to their watching habits self.update_users_watching_habits() # if ppt treat it accordingly if (self.video1.source.endswith(self.list_of_correct_extension_image)): self.video1.source = self.video1.source self.playing_ppt = True self.root_UI.add_widget(self.label_help_ppt) if (self.bool_show_UI): self.root_UI.add_widget(self.button_next_ppt) self.root_UI.add_widget(self.button_previous_ppt) self.bool_ppt_UI_shown = True self.set_ppt_event(Clock.schedule_once(self.play_next_image, self.delay_image)) else: self.video1.state = 'play' print("Playing:", self.video1.source) def set_ppt_event(self, event): if (self.event_ppt != None): self.event_ppt.cancel() self.event_ppt = event def set_playlist_management_event(self, event): if (self.playlist_management_event != None): self.playlist_management_event.cancel() self.playlist_management_event = event def play_next_image(self, dt): print("Entering play_next_image") if (self.playing_ppt): if (self.previous_slide): # print("play next") # get name and extension filename, file_extension = os.path.splitext(self.video1.source) # extract image number number_old = re.search('(\d+)$', filename).group(0) number_new = int(number_old) - 1 # print("before :",filename) # replace the current image number to the next one filename = re.sub(str(number_old) + "$", str(number_new), filename) # print("after :", filename) # if the file does no exist we pass to the video/powerpoint if (os.path.isfile(filename + file_extension)): # if it exist we update the image drawn new_source = filename + file_extension # print(self.video1.source," new image is :",new_source) self.video1.source = new_source self.previous_slide = False self.next_slide = False self.set_ppt_event(Clock.schedule_once(self.play_next_image, self.delay_image)) elif (self.next_slide): # print("play next") # get name and extension filename, file_extension = os.path.splitext(self.video1.source) # extract image number number_old = re.search('(\d+)$', filename).group(0) number_new = int(number_old) + 1 # print("before :",filename) # replace the current image number to the next one filename = re.sub(str(number_old) + "$", str(number_new), filename) # print("after :", filename) # if the file does no exist we pass to the video/powerpoint if (os.path.isfile(filename + file_extension)): # if it exist we update the image drawn new_source = filename + file_extension # print(self.video1.source," new image is :",new_source) self.video1.source = new_source self.previous_slide = False self.next_slide = False self.set_ppt_event(Clock.schedule_once(self.play_next_image, self.delay_image)) else: # print("play next") # get name and extension filename, file_extension = os.path.splitext(self.video1.source) # extract image number number_old = re.search('(\d+)$', filename).group(0) number_new = int(number_old) + 1 # print("before :",filename) # replace the current image number to the next one filename = re.sub(str(number_old) + "$", str(number_new), filename) # print("after :", filename) # if the file does no exist we pass to the video/powerpoint if (not os.path.isfile(filename + file_extension)): print("from play_next_image") self.set_playlist_management_event(Clock.schedule_once(partial(self.playlist_management_next), 0)) else: # if it exist we update the image drawn new_source = filename + file_extension # print(self.video1.source," new image is :",new_source) self.video1.source = new_source self.previous_slide = False self.next_slide = False self.set_ppt_event(Clock.schedule_once(self.play_next_image, self.delay_image)) def show_overlay(self): if (self.bool_show_UI == False): self.root_UI.add_widget(self.handTracking.painter) self.root_UI.add_widget(self.button_next) self.root_UI.add_widget(self.button_previous) self.root_UI.add_widget(self.button_loop) if (not self.bool_ppt_UI_shown and self.playing_ppt): self.root_UI.add_widget(self.button_next_ppt) self.root_UI.add_widget(self.button_previous_ppt) self.bool_ppt_UI_shown = True self.bool_show_UI = True self.check_users() def hide_overlay(self): if (self.bool_show_UI == True): self.root_UI.remove_widget(self.handTracking.painter) self.root_UI.remove_widget(self.button_next) self.root_UI.remove_widget(self.button_previous) self.root_UI.remove_widget(self.button_loop) if (self.bool_ppt_UI_shown): self.root_UI.remove_widget(self.button_next_ppt) self.root_UI.remove_widget(self.button_previous_ppt) self.bool_ppt_UI_shown = False self.bool_show_UI = False # move the mouse to the middle of the window and hide fullscreen (works best when full screen) def hide_mouse_if_unmoved(self, dt): if (Window.mouse_pos[0] == self.last_mouse_pose[0] and Window.mouse_pos[1] == self.last_mouse_pose[ 1] and self.bool_show_UI == False): pyautogui.moveTo(Window.width / 2, Window.height / 2) Window.show_cursor = False # check the mouse position, if situated on the right, the grid is show def check_mouse_position(self, dt): # show mouse cursor if hidden and not in the center of the screen x = Window.mouse_pos[0] y = Window.mouse_pos[1] if (x != Window.width / 2 and y != Window.height / 2 and Window.show_cursor == False): Window.show_cursor = True # todo: check if mouse over widget for click if (self.bool_show_UI): if (self.iterator_check_if_click == self.time_limit_beetween_clicks): self.check_if_click(0) self.iterator_check_if_click = 0 else: self.iterator_check_if_click += 1 self.last_mouse_pose = (Window.mouse_pos[0], Window.mouse_pos[1]) # print(Window.mouse_pos) def check_if_click(self, dt): x = Window.mouse_pos[0] y = Window.mouse_pos[1] if (self.button_next.collide_point(x, y)): self.callback_button_next(None) if (self.button_previous.collide_point(x, y)): self.callback_button_previous(None) if (self.button_loop.collide_point(x, y)): self.callback_button_loop(None) if (self.bool_ppt_UI_shown): if (self.button_next_ppt.collide_point(x, y)): self.callback_button_next_ppt(None) if (self.button_previous_ppt.collide_point(x, y)): self.callback_button_previous_ppt(None) # todo: that may be a bit heavy on processing def on_position_change(self, instance, value): if (value > 30): print("from 30 sec !") self.set_playlist_management_event(Clock.schedule_once(partial(self.playlist_management_next), 0)) def show_greetings(self, text, size=200, color=(1, 1, 1, 1)): label_hello = Label( text=text ) self.root_UI.add_widget(label_hello) # Animate and fade out the message anim = Animation(font_size=size, color=color, t='in_quad', s=1 / 30) anim.start(label_hello) def tick_hello_anim(dt): label_hello.canvas.ask_update() Clock.schedule_once(tick_hello_anim) tick_hello_anim(0) def end_hello_anim(dt): self.root_UI.remove_widget(label_hello) Clock.unschedule(end_hello_anim) Clock.schedule_once(end_hello_anim, 1) # on end of stream, playlist_management is shown def on_eos(self, instance, value): if (not self.video1.source.endswith(self.list_of_correct_extension_image)): print("from eos", self.video1.source) self.set_playlist_management_event(Clock.schedule_once(partial(self.playlist_management_next), 0)) def __init__(self, **kwargs): super(TestApp, self).__init__(**kwargs) self._keyboard = Window.request_keyboard(self._keyboard_closed, self) self._keyboard.bind(on_key_down=self._on_keyboard_down) self._keyboard.bind(on_key_up=self._on_keyboard_up) def _keyboard_closed(self): self._keyboard.unbind(on_key_down=self._on_keyboard_down) self._keyboard = None def _on_keyboard_down(self, *args): # print ('down', args) if args[1][1] == 'f': Window.fullscreen = "auto" if args[1][1] == 'right': print("from right") self.set_playlist_management_event(Clock.schedule_once(partial(self.playlist_management_next), 0)) if args[1][1] == 'left': print("from left") self.set_playlist_management_event(Clock.schedule_once(partial(self.playlist_management_previous), 0)) if args[1][1] == 'enter': self.show_greetings("Hi Yoann") if args[1][1] == 's': self.faceAndEmotionAnalyser.quitAndSave() self.faceAndEmotionAnalyser = apiFaceAndEmotion.apiFaceDetectAndClassifier() if args[1][1] == 'c': self.faceAndEmotionAnalyser.changeName("36", "Yoann", self.faceAndEmotionAnalyser.personsDB) def _on_keyboard_up(self, *args): print(args[1][1])