scenedetect 🎬 Package — PySceneDetect 0.6.5-dev1 documentation

# `scenedetect` 🎬 Package

The scenedetect API is easy to integrate with most application workflows, while also being highly extensible. See the Getting Started section below for some common use cases and integrations. The scenedetect package contains several modules:

> - scenedetect 🎬: Includes the `scenedetect.detect` function which takes a path and a detector to find scene transitions (example), and `scenedetect.open_video` for video input

> - scenedetect.scene_manager 🎞️: The `SceneManager` acts as a way to coordinate detecting scenes (via SceneDetector instances) on video frames (via VideoStream instances). This module also contains functionality to export information about scenes in various formats: `save_images` to save images for each scene, `write_scene_list` to save scene/cut info as CSV, and `write_scene_list_html` to export scenes in viewable HTML format.

> - scenedetect.detectors 🕵️: Detection algorithms:

>   > - `ContentDetector`: detects fast cuts using weighted average of HSV changes

>   > - `ThresholdDetector`: finds fades in/out using average pixel intensity changes in RGB

>   > - `AdaptiveDetector` finds fast cuts using rolling average of HSL changes

>   > - `HistogramDetector` finds fast cuts using HSV histogram changes

>   > - `HashDetector`: finds fast cuts using perceptual image hashing

> - scenedetect.video_stream 🎥: Video input is handled through the `VideoStream` interface. Implementations for common video libraries are provided in `scenedetect.backends`:

>   > - OpenCV: `VideoStreamCv2`

>   > - PyAV: `VideoStreamAv`

>   > - MoviePy: `VideoStreamMoviePy`

> - scenedetect.video_splitter ✂️: Contains `split_video_ffmpeg` and `split_video_mkvmerge` to split a video based on the detected scenes.

> - scenedetect.frame_timecode ⏱️: Contains `FrameTimecode` class for storing, converting, and performing arithmetic on timecodes with frame-accurate precision.

> - scenedetect.scene_detector 🌐: Contains `SceneDetector` interface which detection algorithms must implement.

> - scenedetect.stats_manager 🧮: Contains `StatsManager` class for caching frame metrics and loading/saving them to disk in CSV format for analysis.

> - scenedetect.platform 🐱‍💻: Logging and utility functions.

Most types/functions are also available directly from the scenedetect package to make imports simpler.

Warning

The PySceneDetect API is still under development. It is recommended that you pin the scenedetect version in your requirements to below the next major release:

    scenedetect<0.7

## Getting Started

PySceneDetect makes it very easy to find scene transitions in a video with the `scenedetect.detect()` function:

    from scenedetect import detect, ContentDetector
    path = "video.mp4"
    scenes = detect(path, ContentDetector())
    for (scene_start, scene_end) in scenes:
        print(f'{scene_start}-{scene_end}')

`scenes` now contains a list of `FrameTimecode` pairs representing the start/end of each scene. Note that you can set `show_progress=True` when calling `detect` to display a progress bar with estimated time remaining.

Here, we use `ContentDetector` to detect fast cuts. There are many detector types which can be used to find fast cuts and fades in/out. PySceneDetect can also export scene data in various formats, and can split the input video automatically if ffmpeg is available:

    from scenedetect import detect, ContentDetector, split_video_ffmpeg
    scene_list = detect("my_video.mp4", ContentDetector())
    split_video_ffmpeg("my_video.mp4", scenes)

Recipes for common use cases can be found on Github including limiting detection time and storing per-frame metrics. For advanced workflows, start with the SceneManager usage examples.

## Functions

The `scenedetect` module comes with helper functions to simplify common use cases. `detect()` can be used to perform scene detection on a video by path. `open_video()` can be used to open a video for a `SceneManager`.

scenedetect.detect(video_path, detector, stats_file_path=None, show_progress=False, start_time=None, end_time=None, start_in_scene=False)

  Perform scene detection on a given video path using the specified detector.

  Parameters:

    - video_path (str) – Path to input video (absolute or relative to working directory).

    - detector (SceneDetector) – A SceneDetector instance (see `scenedetect.detectors` for a full list of detectors).

    - stats_file_path (str | None) – Path to save per-frame metrics to for statistical analysis or to determine a better threshold value.

    - show_progress (bool) – Show a progress bar with estimated time remaining. Default is False.

    - start_time (str | float | int | None) – Starting point in video, in the form of a timecode `HH:MM:SS[.nnn]` (str), number of seconds `123.45` (float), or number of frames `200` (int).

    - end_time (str | float | int | None) – Starting point in video, in the form of a timecode `HH:MM:SS[.nnn]` (str), number of seconds `123.45` (float), or number of frames `200` (int).

    - start_in_scene (bool) – Assume the video begins in a scene. This means that when detecting fast cuts with ContentDetector, if no cuts are found, the resulting scene list will contain a single scene spanning the entire video (instead of no scenes). When detecting fades with ThresholdDetector, the beginning portion of the video will always be included until the first fade-out event is detected.

  Returns:

    List of scenes (pairs of `FrameTimecode` objects).

  Raises:

    - VideoOpenFailure – video_path could not be opened.

    - StatsFileCorrupt – stats_file_path is an invalid stats file

    - ValueError – start_time or end_time are incorrectly formatted.

    - TypeError – start_time or end_time are invalid types.

  Return type:

    List[Tuple[FrameTimecode, FrameTimecode]]

scenedetect.open_video(path, framerate=None, backend='opencv', **kwargs)

  Open a video at the given path. If backend is specified but not available on the current system, OpenCV (VideoStreamCv2) will be used as a fallback.

  Parameters:

    - path (str) – Path to video file to open.

    - framerate (float | None) – Overrides detected framerate if set.

    - backend (str) – Name of specific backend to use, if possible. See `scenedetect.backends.AVAILABLE_BACKENDS` for backends available on the current system. If the backend fails to open the video, OpenCV will be used as a fallback.

    - kwargs – Optional named arguments to pass to the specified backend constructor for overriding backend-specific options.

  Returns:

    Backend object created with the specified video path.

  Raises:

    VideoOpenFailure – Constructing the VideoStream fails. If multiple backends have been attempted, the error from the first backend will be returned.

  Return type:

    VideoStream

## Module Reference

PySceneDetect Module Documentation

- Detection Algorithms
  - `AdaptiveDetector`
    - `AdaptiveDetector.get_content_val()`
    - `AdaptiveDetector.get_metrics()`
    - `AdaptiveDetector.post_process()`
    - `AdaptiveDetector.process_frame()`
    - `AdaptiveDetector.stats_manager_required()`
    - `AdaptiveDetector.event_buffer_length`
  - `ContentDetector`
    - `ContentDetector.Components`
    - `ContentDetector.get_metrics()`
    - `ContentDetector.is_processing_required()`
    - `ContentDetector.process_frame()`
    - `ContentDetector.DEFAULT_COMPONENT_WEIGHTS`
    - `ContentDetector.FRAME_SCORE_KEY`
    - `ContentDetector.LUMA_ONLY_WEIGHTS`
    - `ContentDetector.METRIC_KEYS`
  - `HashDetector`
    - `HashDetector.get_metrics()`
    - `HashDetector.hash_frame()`
    - `HashDetector.is_processing_required()`
    - `HashDetector.process_frame()`
  - `HistogramDetector`
    - `HistogramDetector.calculate_histogram()`
    - `HistogramDetector.get_metrics()`
    - `HistogramDetector.is_processing_required()`
    - `HistogramDetector.process_frame()`
  - `ThresholdDetector`
    - `ThresholdDetector.Method`
    - `ThresholdDetector.get_metrics()`
    - `ThresholdDetector.post_process()`
    - `ThresholdDetector.process_frame()`
- Backends
  - Video Files
  - Devices / Cameras / Pipes
  - `AVAILABLE_BACKENDS`
  - `VideoCaptureAdapter`
    - `VideoCaptureAdapter.read()`
    - `VideoCaptureAdapter.reset()`
    - `VideoCaptureAdapter.seek()`
    - `VideoCaptureAdapter.BACKEND_NAME`
    - `VideoCaptureAdapter.aspect_ratio`
    - `VideoCaptureAdapter.capture`
    - `VideoCaptureAdapter.duration`
    - `VideoCaptureAdapter.frame_number`
    - `VideoCaptureAdapter.frame_rate`
    - `VideoCaptureAdapter.frame_size`
    - `VideoCaptureAdapter.is_seekable`
    - `VideoCaptureAdapter.name`
    - `VideoCaptureAdapter.path`
    - `VideoCaptureAdapter.position`
    - `VideoCaptureAdapter.position_ms`
  - `VideoStreamCv2`
    - `VideoStreamCv2.read()`
    - `VideoStreamCv2.reset()`
    - `VideoStreamCv2.seek()`
    - `VideoStreamCv2.BACKEND_NAME`
    - `VideoStreamCv2.aspect_ratio`
    - `VideoStreamCv2.capture`
    - `VideoStreamCv2.duration`
    - `VideoStreamCv2.frame_number`
    - `VideoStreamCv2.frame_rate`
    - `VideoStreamCv2.frame_size`
    - `VideoStreamCv2.is_seekable`
    - `VideoStreamCv2.name`
    - `VideoStreamCv2.path`
    - `VideoStreamCv2.position`
    - `VideoStreamCv2.position_ms`
  - `VideoStreamAv`
    - `VideoStreamAv.read()`
    - `VideoStreamAv.reset()`
    - `VideoStreamAv.seek()`
    - `VideoStreamAv.BACKEND_NAME`
    - `VideoStreamAv.aspect_ratio`
    - `VideoStreamAv.duration`
    - `VideoStreamAv.frame_number`
    - `VideoStreamAv.frame_rate`
    - `VideoStreamAv.frame_size`
    - `VideoStreamAv.is_seekable`
    - `VideoStreamAv.name`
    - `VideoStreamAv.path`
    - `VideoStreamAv.position`
    - `VideoStreamAv.position_ms`
  - `VideoStreamMoviePy`
    - `VideoStreamMoviePy.read()`
    - `VideoStreamMoviePy.reset()`
    - `VideoStreamMoviePy.seek()`
    - `VideoStreamMoviePy.BACKEND_NAME`
    - `VideoStreamMoviePy.aspect_ratio`
    - `VideoStreamMoviePy.duration`
    - `VideoStreamMoviePy.frame_number`
    - `VideoStreamMoviePy.frame_rate`
    - `VideoStreamMoviePy.frame_size`
    - `VideoStreamMoviePy.is_seekable`
    - `VideoStreamMoviePy.name`
    - `VideoStreamMoviePy.path`
    - `VideoStreamMoviePy.position`
    - `VideoStreamMoviePy.position_ms`
- SceneManager
  - Usage
  - Storing Per-Frame Statistics
  - `Interpolation`
    - `Interpolation.AREA`
    - `Interpolation.CUBIC`
    - `Interpolation.LANCZOS4`
    - `Interpolation.LINEAR`
    - `Interpolation.NEAREST`
  - `SceneManager`
    - `SceneManager.add_detector()`
    - `SceneManager.clear()`
    - `SceneManager.clear_detectors()`
    - `SceneManager.detect_scenes()`
    - `SceneManager.get_num_detectors()`
    - `SceneManager.get_scene_list()`
    - `SceneManager.stop()`
    - `SceneManager.auto_downscale`
    - `SceneManager.downscale`
    - `SceneManager.interpolation`
    - `SceneManager.stats_manager`
  - `compute_downscale_factor()`
  - `get_scenes_from_cuts()`
  - `save_images()`
  - `write_scene_list()`
  - `write_scene_list_html()`
  - `DEFAULT_MIN_WIDTH`
  - `MAX_FRAME_QUEUE_LENGTH`
  - `MAX_FRAME_SIZE_ERRORS`
  - `PROGRESS_BAR_DESCRIPTION`
- Video Splitting
  - `SceneMetadata`
    - `SceneMetadata.end`
    - `SceneMetadata.index`
    - `SceneMetadata.start`
  - `VideoMetadata`
    - `VideoMetadata.name`
    - `VideoMetadata.path`
    - `VideoMetadata.total_scenes`
  - `default_formatter()`
  - `is_ffmpeg_available()`
  - `is_mkvmerge_available()`
  - `split_video_ffmpeg()`
  - `split_video_mkvmerge()`
  - `DEFAULT_FFMPEG_ARGS`
  - `FFMPEG_PATH`
  - `TimecodePair`
  - `test_api_detect()`
  - `test_api_detect_start_end_time()`
  - `test_api_detect_stats()`
  - `test_api_device_callback()`
  - `test_api_scene_manager()`
  - `test_api_scene_manager_callback()`
  - `test_api_scene_manager_start_end_time()`
  - `test_api_stats_manager()`
  - `test_api_timecode_types()`
- StatsManager
  - `StatsFileCorrupt`
  - `StatsManager`
    - `StatsManager.get_metrics()`
    - `StatsManager.is_save_required()`
    - `StatsManager.metrics_exist()`
    - `StatsManager.register_metrics()`
    - `StatsManager.save_to_csv()`
    - `StatsManager.set_metrics()`
    - `StatsManager.valid_header()`
  - `COLUMN_NAME_FRAME_NUMBER`
  - `COLUMN_NAME_TIMECODE`
- FrameTimecode
  - Usage Examples
  - `FrameTimecode`
    - `FrameTimecode.equal_framerate()`
    - `FrameTimecode.get_framerate()`
    - `FrameTimecode.get_frames()`
    - `FrameTimecode.get_seconds()`
    - `FrameTimecode.get_timecode()`
    - `FrameTimecode.previous_frame()`
  - `MAX_FPS_DELTA`
- SceneDetector
  - `SceneDetector`
    - `SceneDetector.get_metrics()`
    - `SceneDetector.is_processing_required()`
    - `SceneDetector.post_process()`
    - `SceneDetector.process_frame()`
    - `SceneDetector.stats_manager_required()`
    - `SceneDetector.event_buffer_length`
    - `SceneDetector.stats_manager`
  - `SparseSceneDetector`
    - `SparseSceneDetector.post_process()`
    - `SparseSceneDetector.process_frame()`
- VideoStream
  - `FrameRateUnavailable`
  - `SeekError`
  - `VideoOpenFailure`
  - `VideoStream`
    - `VideoStream.BACKEND_NAME()`
    - `VideoStream.read()`
    - `VideoStream.reset()`
    - `VideoStream.seek()`
    - `VideoStream.aspect_ratio`
    - `VideoStream.base_timecode`
    - `VideoStream.duration`
    - `VideoStream.frame_number`
    - `VideoStream.frame_rate`
    - `VideoStream.frame_size`
    - `VideoStream.is_seekable`
    - `VideoStream.name`
    - `VideoStream.path`
    - `VideoStream.position`
    - `VideoStream.position_ms`
- Platform & Logging
  - `CommandTooLong`
  - `FakeTqdmLoggingRedirect`
  - `FakeTqdmObject`
    - `FakeTqdmObject.close()`
    - `FakeTqdmObject.set_description()`
    - `FakeTqdmObject.update()`
  - `Template`
  - `get_and_create_path()`
  - `get_cv2_imwrite_params()`
  - `get_ffmpeg_path()`
  - `get_ffmpeg_version()`
  - `get_file_name()`
  - `get_mkvmerge_version()`
  - `get_system_version_info()`
  - `init_logger()`
  - `invoke_command()`
- Migration Guide
  - VideoManager Class
    - Seeking and Start/End Times
  - SceneManager Class
  - save_images Function
  - split_video_* Functions
  - StatsManager Class
  - AdaptiveDetector Class
  - Other
    - ThresholdDetector Class
    - ContentDetector Class
    - MINIMUM_FRAMES_PER_SECOND_* Constants
    - get_aspect_ratio Function

## Logging

PySceneDetect outputs messages to a logger named `pyscenedetect` which does not have any default handlers. You can use `scenedetect.init_logger` with `show_stdout=True` or specify a log file (verbosity can also be specified) to attach some common handlers, or use `logging.getLogger("pyscenedetect")` and attach log handlers manually.

## Migrating From 0.5

PySceneDetect 0.6 introduces several breaking changes which are incompatible with 0.5. See Migration Guide for details on how to update your application. In addition, demonstrations of common use cases can be found in the tests/test_api.py file.