VideoManager

PySceneDetect scenedetect.video_manager Module

This module contains the VideoManager class, which provides a consistent interface to reading videos, specific exceptions raised upon certain error conditions, and some global helper functions to open/close multiple videos, as well as validate their parameters.

The VideoManager can be constructed with a path to a video (or sequence of videos) and a start and end time/duration, then passed to a SceneManager object for performing scene detection analysis. If the start time is modified, then it also needs to be reflected in the SceneManager.

The VideoManager class attempts to emulate some methods of the OpenCV cv2.VideoCapture object, and can be used interchangably with one with respect to a SceneManager object.

Usage Example

Assuming we have a file video.mp4, we can load it and iterate through the first 2 minutes using the default downscale factor as follows.

We start by creating a VideoManager and getting the base FrameTimecode:

video_manager = VideoManager(['video.mp4'])
base_timecode = video_manager.get_base_timecode()

Note that the first argument to the VideoManager constructor is a list of video files to open. Any number of videos can be appended by adding more paths to the list, however, each video must have the same framerate and resolution.

Tip

If the video framerates differ slightly, supply the framerate argument to override the framerate check:

video_manager = VideoManager(['video1.mp4', 'video2.mp4'],
                             framerate=23.976)
# base_timecode will have a framerate of 23.976 now.
base_timecode = video_manager.get_base_timecode()

Next, we set the duration to 2 minutes and the downscale factor to the default based on video resolution:

video_manager.set_duration(duration=base_timecode + '00:02:00')
video_manager.set_downscale_factor()

set_duration() takes up to two arguments of start_time, end_time, and duration, where end_time and duration are mutually exclusive. Each argument should be a FrameTimecode object.

Note that if you are using a SceneManager and set the start_time argument of VideoManager.set_duration(), you must pass set the same start_time argument to the SceneManager.detect_scenes() method.

After calling the above, the number of frames returned by the VideoManager will be limited to 2 minutes of video exactly, and setting the default downscale factor ensures an adequate frame size for performing scene detection in most use cases.

Warning

The set_duration() and set_downscale_factor() methods must be called before start().

Now that all of our options have been set, we can call VideoManager.start() and begin processing frames the same way we would with an OpenCV VideoCapture object:

video_manager.start()
while True:
    ret_val, frame_image = video_manager.read()
    if not ret_val:
        break
    # Do stuff with frame_image here.

Note that the VideoManager.read(), VideoManager.grab() and VideoManager.retrieve() methods all have the same prototypes and function as their OpenCV counterparts. Likewise, the frame image returned by these methods is a standard Numpy ndarray which can be operated on as expected.

Lastly, when all processing is done, make sure to call VideoManager.release() to cleanup all resources acquired by the VideoManager object.

Hint

Use a try/finally block to ensure that the release() method is called. For example:

video_manager = VideoManager(['video.mp4'])
try:
    video_manager.set_downscale_factor()
    video_manager.start()
    while True:
        if not video_manager.grab():
            break
finally:
    # Ensures release() is called even if an exception
    # is thrown during any code added to process frames.
    video_manager.release()

When passing a VideoManager to a SceneManager class, the start() method must already have been called. See the example in the SceneManager reference for more details.

VideoManager Class

class scenedetect.video_manager.VideoManager(video_files, framerate=None, logger=None)

Provides a cv2.VideoCapture-like interface to a set of one or more video files, or a single device ID. Supports seeking and setting end time/duration.

get(capture_prop, index=None)

Get (cv2.VideoCapture method) - obtains capture properties from the current VideoCapture object in use. Index represents the same index as the original video_files list passed to the constructor. Getting/setting the position (POS) properties has no effect; seeking is implemented using VideoDecoder methods.

Note that getting the property CAP_PROP_FRAME_COUNT will return the integer sum of the frame count for all VideoCapture objects if index is not specified (or is None), otherwise the frame count for the given VideoCapture index is returned instead.

Parameters:
  • capture_prop – OpenCV VideoCapture property to get (i.e. CAP_PROP_FPS).
  • index (int, optional) – Index in file_list of capture to get property from (default is zero). Index is not checked and will raise exception if out of bounds.
Returns:

Return value from calling get(property) on the VideoCapture object.

Return type:

float

get_base_timecode()

Get Base Timecode - returns a FrameTimecode object at frame 0 / time 00:00:00.

The timecode returned by this method can be used to perform arithmetic (e.g. addition), passing the resulting values back to the VideoManager (e.g. for the set_duration() method), as the framerate of the returned FrameTimecode object matches that of the VideoManager.

As such, this method is equivalent to creating a FrameTimecode at frame 0 with the VideoManager framerate, for example, given a VideoManager called obj, the following expression will evaluate as True:

obj.get_base_timecode() == FrameTimecode(0, obj.get_framerate())

Furthermore, the base timecode object returned by a particular VideoManager should not be passed to another one, unless you first verify that their framerates are the same.

Returns:00:00 with the video(s) framerate.
Return type:FrameTimecode object set to frame 0/time 00
get_current_timecode()

Get Current Timecode - returns a FrameTimecode object at current VideoManager position.

Returns:Timecode at the current VideoManager position.
Return type:FrameTimecode
get_framerate()

Get Framerate - returns the framerate the VideoManager is assuming for all open VideoCaptures. Obtained from either the capture itself, or the passed framerate parameter when the VideoManager object was constructed.

Returns:Framerate, in frames/sec.
Return type:float
get_framesize()

Get Frame Size - returns the frame size of the video(s) open in the VideoManager’s capture objects.

Returns:Video frame size in the form (width, height) where width and height represent the size of the video frame in pixels.
Return type:Tuple[int, int]
get_framesize_effective()

Get Frame Size - returns the frame size of the video(s) open in the VideoManager’s capture objects, divided by the current downscale factor.

Returns:Video frame size in the form (width, height) where width and height represent the size of the video frame in pixels.
Return type:Tuple[int, int]
get_num_videos()

Get Number of Videos - returns the length of the capture list (self._cap_list), representing the number of videos the VideoManager has opened.

Returns:Number of videos, equal to length of capture list.
Return type:int
get_video_paths()

Get Video Paths - returns list of strings containing paths to the open video(s).

Returns:List of paths to the video files opened by the VideoManager.
Return type:List[str]
grab()

Grab (cv2.VideoCapture method) - retrieves a frame but does not return it.

Returns:True if a frame was grabbed, False otherwise.
Return type:bool
Raises:VideoDecoderNotStarted – Must call start() before this method.
read()

Read (cv2.VideoCapture method) - retrieves and returns a frame.

Returns:Returns tuple of (True, frame_image) if a frame was grabbed, where frame_image is a numpy ndarray of the decoded frame, otherwise (False, None).
Return type:Tuple[bool, Union[None, numpy.ndarray]]
Raises:VideoDecoderNotStarted – Must call start() before this method.
release()

Release (cv2.VideoCapture method), releases all open capture(s).

reset()

Reset - Reopens captures passed to the constructor of the VideoManager.

Can only be called after the release() method has been called.

Raises:VideoDecodingInProgress – Must call release() before this method.
retrieve()

Retrieve (cv2.VideoCapture method) - retrieves and returns a frame.

Frame returned corresponds to last call to get().

Returns:Returns tuple of (True, frame_image) if a frame was grabbed during the last call to grab(), and where frame_image is a numpy ndarray of the decoded frame, otherwise returns (False, None).
Return type:Tuple[bool, Union[None, numpy.ndarray]]
Raises:VideoDecoderNotStarted – Must call start() before this method.
seek(timecode)

Seek - seeks forwards to the passed timecode.

Only supports seeking forwards (i.e. timecode must be greater than the current VideoManager position). Can only be used after the start() method has been called.

Parameters:timecode (FrameTimecode) – Time in video to seek forwards to.
Returns:True if seeking succeeded, False if no more frames / end of video.
Return type:bool
Raises:VideoDecoderNotStarted – Must call start() before this method.
set_downscale_factor(downscale_factor=None)

Set Downscale Factor - sets the downscale/subsample factor of returned frames.

If N is the downscale_factor, the size of the frames returned becomes frame_width/N x frame_height/N via subsampling.

If downscale_factor is None, the downscale factor is computed automatically based on the current video’s resolution. A downscale_factor of 1 indicates no downscaling.

set_duration(duration=None, start_time=None, end_time=None)

Set Duration - sets the duration/length of the video(s) to decode, as well as the start/end times. Must be called before start() is called, otherwise a VideoDecodingInProgress exception will be thrown. May be called after reset() as well.

Parameters:
  • duration (Optional[FrameTimecode]) – The (maximum) duration in time to decode from the opened video(s). Mutually exclusive with end_time (i.e. if duration is set, end_time must be None).
  • start_time (Optional[FrameTimecode]) – The time/first frame at which to start decoding frames from. If set, the input video(s) will be seeked to when start() is called, at which point the frame at start_time can be obtained by calling retrieve().
  • end_time (Optional[FrameTimecode]) – The time at which to stop decoding frames from the opened video(s). Mutually exclusive with duration (i.e. if end_time is set, duration must be None).
Raises:

VideoDecodingInProgress – Must call before start().

start()

Start - starts video decoding and seeks to start time. Raises exception VideoDecodingInProgress if the method is called after the decoder process has already been started.

Raises:VideoDecodingInProgress – Must call stop() before this method if start() has already been called after initial construction.

video_manager Functions and Constants

The following functions and constants are available in the scenedetect.video_manager module.

scenedetect.video_manager.DEFAULT_DOWNSCALE_FACTORS = {400: 2, 600: 3, 900: 4, 1200: 5, 1700: 6, 2100: 8, 3200: 12}

Dict[int, int] – The default downscale factor for a video of size W x H, which enforces the constraint that W >= 200 to ensure an adequate amount of pixels for scene detection while providing a speedup in processing.

scenedetect.video_manager.compute_downscale_factor(frame_width)

Compute Downscale Factor: Returns the optimal default downscale factor based on a video’s resolution (specifically, the width parameter).

Returns:The defalt downscale factor to use with a video of frame_height x frame_width.
Return type:int
exception scenedetect.video_manager.InvalidDownscaleFactor

InvalidDownscaleFactor: Raised when trying to set invalid downscale factor, i.e. the supplied downscale factor was not a positive integer greater than zero.

scenedetect.video_manager.get_video_name(video_file)

Get Video Name: Returns a string representing the video file/device name.

Returns:
Video file name or device ID. In the case of a video, only the file
name is returned, not the whole path. For a device, the string format is ‘Device 123’, where 123 is the integer ID of the capture device.
Return type:str
scenedetect.video_manager.get_num_frames(cap_list)

Get Number of Frames: Returns total number of frames in the cap_list.

Calls get(CAP_PROP_FRAME_COUNT) and returns the sum for all VideoCaptures.

scenedetect.video_manager.open_captures(video_files, framerate=None, validate_parameters=True)

Open Captures - helper function to open all capture objects, set the framerate, and ensure that all open captures have been opened and the framerates match on a list of video file paths, or a list containing a single device ID.

Parameters:
  • video_files (list of str(s)/int) – A list of one or more paths (str), or a list of a single integer device ID, to open as an OpenCV VideoCapture object. A ValueError will be raised if the list does not conform to the above.
  • framerate (float, optional) – Framerate to assume when opening the video_files. If not set, the first open video is used for deducing the framerate of all videos in the sequence.
  • validate_parameters (bool, optional) – If true, will ensure that the frame sizes (width, height) and frame rate (FPS) of all passed videos is the same. A VideoParameterMismatch is raised if the framerates do not match.
Returns:

A tuple of form (cap_list, framerate, framesize) where cap_list is a list of open OpenCV VideoCapture objects in the same order as the video_files list, framerate is a float of the video(s) framerate(s), and framesize is a tuple of (width, height) where width and height are integers representing the frame size in pixels.

Raises:
  • ValueError – No video file(s) specified, or invalid/multiple device IDs specified.
  • TypeErrorframerate must be type float.
  • IOError – Video file(s) not found.
  • VideoFramerateUnavailable – Video framerate could not be obtained and framerate was not set manually.
  • VideoParameterMismatch – All videos in video_files do not have equal parameters. Set validate_parameters=False to skip this check.
  • VideoOpenFailure – Video(s) could not be opened.
scenedetect.video_manager.release_captures(cap_list)

Close Captures: Calls the release() method on every capture in cap_list.

scenedetect.video_manager.close_captures(cap_list)

Close Captures: Calls the close() method on every capture in cap_list.

scenedetect.video_manager.validate_capture_framerate(video_names, cap_framerates, framerate=None)

Validate Capture Framerate: Ensures that the passed capture framerates are valid and equal.

Raises:
  • ValueError – Invalid framerate (must be positive non-zero value).
  • TypeError – Framerate must be of type float.
  • VideoFramerateUnavailable – Framerate for video could not be obtained, and framerate was not set.
scenedetect.video_manager.validate_capture_parameters(video_names, cap_frame_sizes, check_framerate=False, cap_framerates=None)

Validate Capture Parameters: Ensures that all passed capture frame sizes and (optionally) framerates are equal. Raises VideoParameterMismatch if there is a mismatch.

Raises:VideoParameterMismatch

Exceptions

exception scenedetect.video_manager.VideoOpenFailure(file_list=None, message='OpenCV VideoCapture object failed to return True when calling isOpened().')

VideoOpenFailure: Raised when an OpenCV VideoCapture object fails to open (i.e. calling the isOpened() method returns a non True value).

exception scenedetect.video_manager.VideoFramerateUnavailable(file_name=None, file_path=None, message='OpenCV VideoCapture object failed to return framerate when calling get(cv2.CAP_PROP_FPS).')

VideoFramerateUnavailable: Raised when the framerate cannot be determined from the video, and the framerate has not been overriden/forced in the VideoManager.

exception scenedetect.video_manager.VideoParameterMismatch(file_list=None, message='OpenCV VideoCapture object parameters do not match.')

VideoParameterMismatch: Raised when opening multiple videos with a VideoManager, and some of the video parameters (frame height, frame width, and framerate/FPS) do not match.

exception scenedetect.video_manager.VideoDecodingInProgress

VideoDecodingInProgress: Raised when attempting to call certain VideoManager methods that must be called before start() has been called.

exception scenedetect.video_manager.VideoDecoderNotStarted

VideoDecodingInProgress: Raised when attempting to call certain VideoManager methods that must be called after start() has been called.

exception scenedetect.video_manager.InvalidDownscaleFactor

InvalidDownscaleFactor: Raised when trying to set invalid downscale factor, i.e. the supplied downscale factor was not a positive integer greater than zero.