Source code for mediadecoder.timer

# Python 3 compatibility
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import time
import threading

from mediadecoder.states import *
from moviepy.tools import cvsecs

[docs]class Timer(object): """ Timer serves as a video clock that is used to determine which frame needs to be displayed at a specified time. the clock runs in its own separate thread. Say you have an instance of Timer called ``clock``. The time can be polled by checking >> clock.time and the current frame can be determined by checking >> clock.current_frame. """
[docs] def __init__(self, fps=None, max_duration=None): """ Constructor. Parameters ---------- fps : float, optional The frames per second of the video for which this timer is created. max_duration : float, optional The maximum time in seconds the timer should run for. """ self.status = PAUSED self.max_duration = max_duration self.fps = fps self.reset()
[docs] def reset(self): """ Reset the clock to 0.""" self.previous_intervals = [] self.current_interval_duration = 0.0
[docs] def pause(self): """ Pauses the clock to continue running later. Saves the duration of the current interval in the previous_intervals list.""" if self.status == RUNNING: self.status = PAUSED self.previous_intervals.append(time.time() - self.interval_start) self.current_interval_duration = 0.0 elif self.status == PAUSED: self.interval_start = time.time() self.status = RUNNING
[docs] def start(self): """ Starts the clock from 0. Uses a separate thread to handle the timing functionalities. """ if not hasattr(self,"thread") or not self.thread.isAlive(): self.thread = threading.Thread(target=self.__run) self.status = RUNNING self.reset() self.thread.start() else: print("Clock already running!")
def __run(self): """ Internal function that is run in a separate thread. Do not call directly. """ self.interval_start = time.time() while self.status != STOPPED: if self.status == RUNNING: self.current_interval_duration = time.time() - self.interval_start # If max_duration is set, stop the clock if it is reached if self.max_duration and self.time > self.max_duration: self.status == STOPPED # One refresh per millisecond seems enough time.sleep(0.001)
[docs] def stop(self): """ Stops the clock and resets the internal timers. """ self.status = STOPPED self.reset()
@property def time(self): """ The current time of the clock. """ return sum(self.previous_intervals) + self.current_interval_duration @time.setter def time(self, value): """ Sets the time of the clock. Useful for seeking. Parameters ---------- value : str or int The time to seek to. Can be any of the following formats: >>> 15.4 -> 15.4 # seconds >>> (1,21.5) -> 81.5 # (min,sec) >>> (1,1,2) -> 3662 # (hr, min, sec) >>> '01:01:33.5' -> 3693.5 #(hr,min,sec) >>> '01:01:33.045' -> 3693.045 >>> '01:01:33,5' #comma works too """ seconds = cvsecs(value) self.reset() self.previous_intervals.append(seconds) @property def current_frame(self): """ The current frame number that should be displayed.""" if not self.__fps: raise RuntimeError("fps not set so current frame number cannot be" " calculated") else: return int(self.__fps * self.time) @property def frame_interval(self): """ The duration of a single frame in seconds. """ if not self.__fps: raise RuntimeError("fps not set so current frame interval cannot be" " calculated") else: return 1.0/self.__fps @property def fps(self): """ Returns the frames per second indication that is currently set. """ return self.__fps @fps.setter def fps(self,value): """ Sets the frames per second of the current movie the clock is used for. Parameters ---------- value : float The fps value. """ if not value is None: if not type(value) == float: raise ValueError("fps needs to be specified as a float") if value<1.0: raise ValueError("fps needs to be greater than 1.0") self.__fps = value @property def max_duration(self): """ Returns the max duration the clock should run for. (Usually the duration of the videoclip) """ return self.__max_duration @max_duration.setter def max_duration(self,value): """ Sets the value of max duration Parameters ---------- value : float The value for max_duration Raises ------ TypeError If max_duration is not a number. ValueError If max_duration is smaller than 0. """ if not value is None: if not type(value) in [float, int]: raise TypeError("max_duration needs to be specified as a number") if value<1.0: raise ValueError("max_duration needs to be greater than 1.0") value = float(value) self.__max_duration = value def __repr__(self): """ Creates a string representation for the print function.""" if self.__fps: return "Clock [current time: {0}, fps: {1}, current_frame: {2}]".format( self.time, self.__fps, self.current_frame) else: return "Clock [current time: {0}]".format(self.time)