From 85c651ee3371762d01f0d51f0576991c05b505a8 Mon Sep 17 00:00:00 2001 From: CodeYan01 <65320293+CodeYan01@users.noreply.github.com> Date: Fri, 2 Jun 2023 19:19:35 +0800 Subject: [PATCH] Feat: Add Loop property Makes it easier to toggle looping, and prevents flickering that would be caused by calling `TkinterVideo.play()` after the "<>" event. --- Documentation.md | 3 ++- examples/loop_example.py | 10 +++------- tkVideoPlayer/tkvideoplayer.py | 20 ++++++++++++++++++-- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/Documentation.md b/Documentation.md index 8d2479d..8cb8b0b 100644 --- a/Documentation.md +++ b/Documentation.md @@ -6,8 +6,9 @@ Below are the methods of this library. | Methods | Parameters | Description | |------------------|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| \_\_init\_\_ | scaled(bool), consistant_frame_rate(bool)=True, keep_aspect(bool)=False | The scale parameter scales the video to the label size. The consistant_frame_rate parameter skips frames to keep the framerate consistant and keep_aspect keeps aspect ratio when resizing(note: It will not increase the size) | +| \_\_init\_\_ | scaled(bool), consistant_frame_rate(bool)=True, keep_aspect(bool)=False, loop(bool)=True | The scale parameter scales the video to the label size. The consistant_frame_rate parameter skips frames to keep the framerate consistant and keep_aspect keeps aspect ratio when resizing(note: It will not increase the size) | | set_scaled | scaled(bool), keep_aspect(bool)=False | scales the video to the label size. | +| loop | loop(bool) | Sets whether the video should be looped. | load | file_path(str) | starts loading the video in a thread. | | set_size | size(Tuple[int, int]), keep_aspect(bool)=False | sets the size of the video frame. setting this will set scaled to `False` | | current_duration | - | return video duration in seconds. | diff --git a/examples/loop_example.py b/examples/loop_example.py index 0e16213..de8bdcd 100644 --- a/examples/loop_example.py +++ b/examples/loop_example.py @@ -2,16 +2,12 @@ from tkVideoPlayer import TkinterVideo -def loop(e): - # if the video had ended then replays the video from the beginning - tkvideo.play() - - root = tk.Tk() -tkvideo = TkinterVideo(scaled=True, master=root) +tkvideo = TkinterVideo(scaled=True, master=root, loop=True) +# tkvideo.loop = True # can also set loop value after initialization +# tkvideo.loop(True) # alternative tkvideo.load(r"sample_m4v.m4v") tkvideo.pack(expand=True, fill="both") tkvideo.play() # play the video -tkvideo.bind("<>", loop) # when the video ends calls the loop function root.mainloop() diff --git a/tkVideoPlayer/tkvideoplayer.py b/tkVideoPlayer/tkvideoplayer.py index b687381..1af0714 100644 --- a/tkVideoPlayer/tkvideoplayer.py +++ b/tkVideoPlayer/tkvideoplayer.py @@ -11,7 +11,7 @@ class TkinterVideo(tk.Label): - def __init__(self, master, scaled: bool = True, consistant_frame_rate: bool = True, keep_aspect: bool = False, *args, **kwargs): + def __init__(self, master, scaled: bool = True, consistant_frame_rate: bool = True, keep_aspect: bool = False, loop: bool = False, *args, **kwargs): super(TkinterVideo, self).__init__(master, *args, **kwargs) self.path = "" @@ -19,6 +19,7 @@ def __init__(self, master, scaled: bool = True, consistant_frame_rate: bool = Tr self._paused = True self._stop = True + self._loop = loop self.consistant_frame_rate = consistant_frame_rate # tries to keep the frame rate consistant by skipping over a few frames @@ -53,6 +54,15 @@ def keep_aspect(self, keep_aspect: bool): """ keeps the aspect ratio when resizing the image """ self._keep_aspect_ratio = keep_aspect + @property + def loop(self) -> bool: + """ restarts the video from the start when video ends """ + return self._loop + + @loop.setter + def loop(self, loop: bool): + self._loop = loop + def set_resampling_method(self, method: int): """ sets the resampling method when resizing """ self._resampling_method = method @@ -180,7 +190,13 @@ def _load(self, path): # time.sleep(abs((1 / self._video_info["framerate"]) - (delta / 1000))) - except (StopIteration, av.error.EOFError, tk.TclError): + except av.error.EOFError: + if self._loop: + self.seek(0) + else: + break + + except (StopIteration, tk.TclError): break self._frame_number = 0