SceneManager

PySceneDetect scenedetect.scene_manager Module

This module implements the SceneManager object, which is used to coordinate SceneDetectors and frame sources (VideoManager or cv2.VideoCapture), creating a cut list (see SceneManager.get_cut_list()) of all changes in scene, which is used to generate a final list of scenes (see SceneManager.get_scene_list()) which contains pairs of start/end FrameTimecode objects at each scene boundaries.

The FrameTimecode objects and tuples thereof returned by get_cut_list and get_scene_list, respectively, can be sorted if for some reason the scene (or cut) list becomes unsorted. The SceneManager also facilitates passing a scenedetect.stats_manager.StatsManager, if any is defined, to the associated scenedetect.scene_detector.SceneDetector objects for caching of frame metrics.

This speeds up subsequent calls to the SceneManager.detect_scenes() method that process the same frames with the same detection algorithm, even if different threshold values (or other algorithm options) are used.

Usage Example

In the code example below, we create a function find_scenes() which performs the following actions:

  • loads a video file by path (str) as argument video_path using a VideoManager
  • loads/saves a stats file for the video to {video_path}.stats.csv using a StatsManager
  • performs content-aware scene detection on the video using a ContentDetector bound to a SceneManager
  • print() out a table of detected scenes to the terminal/console
  • returns a list of tuples of FrameTimecode objects of the start and end times for each detected scene

This example is a modified version of the api_test.py file, and shows complete usage of a SceneManager object to perform content-aware scene detection using the ContentDetector, printing a list of scenes, and both saving/loading a stats file.

from __future__ import print_function
import os

# Standard PySceneDetect imports:
from scenedetect.video_manager import VideoManager
from scenedetect.scene_manager import SceneManager
# For caching detection metrics and saving/loading to a stats file
from scenedetect.stats_manager import StatsManager

# For content-aware scene detection:
from scenedetect.detectors.content_detector import ContentDetector


def find_scenes(video_path):
    # type: (str) -> List[Tuple[FrameTimecode, FrameTimecode]]
    video_manager = VideoManager([video_path])
    stats_manager = StatsManager()
    # Construct our SceneManager and pass it our StatsManager.
    scene_manager = SceneManager(stats_manager)

    # Add ContentDetector algorithm (each detector's constructor
    # takes detector options, e.g. threshold).
    scene_manager.add_detector(ContentDetector())
    base_timecode = video_manager.get_base_timecode()

    # We save our stats file to {VIDEO_PATH}.stats.csv.
    stats_file_path = '%s.stats.csv' % video_path

    scene_list = []

    try:
        # If stats file exists, load it.
        if os.path.exists(stats_file_path):
            # Read stats from CSV file opened in read mode:
            with open(stats_file_path, 'r') as stats_file:
                stats_manager.load_from_csv(stats_file, base_timecode)

        # Set downscale factor to improve processing speed.
        video_manager.set_downscale_factor()

        # Start video_manager.
        video_manager.start()

        # Perform scene detection on video_manager.
        scene_manager.detect_scenes(frame_source=video_manager)

        # Obtain list of detected scenes.
        scene_list = scene_manager.get_scene_list(base_timecode)
        # Each scene is a tuple of (start, end) FrameTimecodes.

        print('List of scenes obtained:')
        for i, scene in enumerate(scene_list):
            print(
                'Scene %2d: Start %s / Frame %d, End %s / Frame %d' % (
                i+1,
                scene[0].get_timecode(), scene[0].get_frames(),
                scene[1].get_timecode(), scene[1].get_frames(),))

        # We only write to the stats file if a save is required:
        if stats_manager.is_save_required():
            with open(stats_file_path, 'w') as stats_file:
                stats_manager.save_to_csv(stats_file, base_timecode)

    finally:
        video_manager.release()

    return scene_list

The use of a StatsManager allows subsequent calls to find_scenes() (specifically the detect_scenes method) with the same video to be significantly faster, and saving/loading the stats file to a CSV file on disk allows the stats to persist even after the program exits. This is the same file that is generated when running the scenedetect command with the -s/--stats option.

SceneManager Class

class scenedetect.scene_manager.SceneManager(stats_manager=None)

The SceneManager facilitates detection of scenes via the detect_scenes() method, given a video source (VideoManager or cv2.VideoCapture), and SceneDetector algorithms added via the add_detector() method.

Can also optionally take a StatsManager instance during construction to cache intermediate scene detection calculations, making subsequent calls to detect_scenes() much faster, allowing the cached values to be saved/loaded to/from disk, and also manually determining the optimal threshold values or other options for various detection algorithms.

add_detector(detector)

Adds/registers a SceneDetector (e.g. ContentDetector, ThresholdDetector) to run when detect_scenes is called. The SceneManager owns the detector object, so a temporary may be passed.

Parameters:detector (SceneDetector) – Scene detector to add to the SceneManager.
clear()

Clears all cuts/scenes and resets the SceneManager’s position.

Any statistics generated are still saved in the StatsManager object passed to the SceneManager’s constructor, and thus, subsequent calls to detect_scenes, using the same frame source reset at the initial time (if it is a VideoManager, use the reset() method), will use the cached frame metrics that were computed and saved in the previous call to detect_scenes.

clear_detectors()

Removes all scene detectors added to the SceneManager via add_detector().

detect_scenes(frame_source, end_time=None, frame_skip=0, show_progress=True)

Perform scene detection on the given frame_source using the added SceneDetectors.

Blocks until all frames in the frame_source have been processed. Results can be obtained by calling either the get_scene_list() or get_cut_list() methods.

Parameters:
  • frame_source (scenedetect.video_manager.VideoManager or cv2.VideoCapture) – A source of frames to process (using frame_source.read() as in VideoCapture). VideoManager is preferred as it allows concatenation of multiple videos as well as seeking, by defining start time and end time/duration.
  • end_time (int or FrameTimecode) – Maximum number of frames to detect (set to None to detect all available frames). Only needed for OpenCV VideoCapture objects; for VideoManager objects, use set_duration() instead.
  • frame_skip (int) – Not recommended except for extremely high framerate videos. Number of frames to skip (i.e. process every 1 in N+1 frames, where N is frame_skip, processing only 1/N+1 percent of the video, speeding up the detection time at the expense of accuracy). frame_skip must be 0 (the default) when using a StatsManager.
  • show_progress (bool) – If True, and the tqdm module is available, displays a progress bar with the progress, framerate, and expected time to complete processing the video frame source.
Returns:

Number of frames read and processed from the frame source.

Return type:

int

Raises:

ValueErrorframe_skip must be 0 (the default) if the SceneManager was constructed with a StatsManager object.

get_cut_list(base_timecode)

Returns a list of FrameTimecodes of the detected scene changes/cuts.

Unlike get_scene_list, the cutting list returns a list of FrameTimecodes representing the point in the input video(s) where a new scene was detected, and thus the frame where the input should be cut/split. The cutting list, in turn, is used to generate the scene list, noting that each scene is contiguous starting from the first frame and ending at the last frame detected.

Returns:List of FrameTimecode objects denoting the points in time where a scene change was detected in the input video(s), which can also be passed to external tools for automated splitting of the input into individual scenes.
get_num_detectors()

Gets number of registered scene detectors added via add_detector.

get_scene_list(base_timecode)

Returns a list of tuples of start/end FrameTimecodes for each scene.

The scene list is generated by calling get_scenes_from_cuts() on the cutting list from get_cut_list(), noting that each scene is contiguous, starting from the first and ending at the last frame of the input.

Returns:List of tuples in the form (start_time, end_time), where both start_time and end_time are FrameTimecode objects representing the exact time/frame where each detected scene in the video begins and ends.

scene_manager Functions

scenedetect.scene_manager.get_scenes_from_cuts(cut_list, base_timecode, num_frames, start_frame=0)

Returns a list of tuples of start/end FrameTimecodes for each scene based on a list of detected scene cuts/breaks.

This function is called when using the SceneManager.get_scene_list() method. The scene list is generated from a cutting list (SceneManager.get_cut_list()), noting that each scene is contiguous, starting from the first to last frame of the input.

Parameters:
  • cut_list (List[FrameTimecode]) – List of FrameTimecode objects where scene cuts/breaks occur.
  • base_timecode (FrameTimecode) – The base_timecode of which all FrameTimecodes in the cut_list are based on.
  • num_frames (int or FrameTimecode) – The number of frames, or FrameTimecode representing duration, of the video that was processed (used to generate last scene’s end time).
  • start_frame (int or FrameTimecode) – The start frame or FrameTimecode of the cut list. Used to generate the first scene’s start time.
Returns:

List of tuples in the form (start_time, end_time), where both start_time and end_time are FrameTimecode objects representing the exact time/frame where each scene occupies based on the input cut_list.

scenedetect.scene_manager.write_scene_list(output_csv_file, scene_list, cut_list=None)

Writes the given list of scenes to an output file handle in CSV format.

Parameters:
  • output_csv_file – Handle to open file in write mode.
  • scene_list – List of pairs of FrameTimecodes denoting each scene’s start/end FrameTimecode.
  • cut_list – Optional list of FrameTimecode objects denoting the cut list (i.e. the frames in the video that need to be split to generate individual scenes). If not passed, the start times of each scene (besides the 0th scene) is used instead.