diff --git a/tkvideo/tkvideo.py b/tkvideo/tkvideo.py index 38db79b..1b58227 100644 --- a/tkvideo/tkvideo.py +++ b/tkvideo/tkvideo.py @@ -10,6 +10,7 @@ try: except ImportError: import tkinter as tk # for Python3 import threading +from time import perf_counter, sleep import imageio from PIL import Image, ImageTk @@ -28,15 +29,19 @@ class tkvideo(): :param size: Changes the video's dimensions (2-tuple, default is 640x360) + :param hz: + Sets the video's frame rate (float, + default 0 is unchecked) """ - def __init__(self, path, label, loop = 0, size = (640,360)): + def __init__(self, path, label, loop = 0, size = (640,360), hz = 0): self.path = path self.label = label self.loop = loop self.size = size + self.hz = hz - def load(self, path, label, loop): + def load(self, path, label, loop, hz): """ Loads the video's frames recursively onto the selected label widget's image parameter. Loop parameter controls whether the function will run in an infinite loop @@ -44,23 +49,44 @@ class tkvideo(): """ frame_data = imageio.get_reader(path) + if hz > 0: + frame_duration = float(1 / hz) + else: + frame_duration = float(0) + if loop == 1: while True: + before = perf_counter() for image in frame_data.iter_data(): frame_image = ImageTk.PhotoImage(Image.fromarray(image).resize(self.size)) label.config(image=frame_image) label.image = frame_image + + diff = frame_duration + before + after = perf_counter() + diff = diff - after + if diff > 0: + sleep(diff) + before = perf_counter() else: + before = perf_counter() for image in frame_data.iter_data(): frame_image = ImageTk.PhotoImage(Image.fromarray(image).resize(self.size)) label.config(image=frame_image) label.image = frame_image + diff = frame_duration + before + after = perf_counter() + diff = diff - after + if diff > 0: + sleep(diff) + before = perf_counter() + def play(self): """ Creates and starts a thread as a daemon that plays the video by rapidly going through the video's frames. """ - thread = threading.Thread(target=self.load, args=(self.path, self.label, self.loop)) + thread = threading.Thread(target=self.load, args=(self.path, self.label, self.loop, self.hz)) thread.daemon = 1 thread.start()