Backends

scenedetect.backends Module

This module contains VideoStream implementations backed by various Python multimedia libraries. In addition to creating backend objects directly, scenedetect.open_video() can be used to open a video with a specified backend, falling back to OpenCV if not available.

All backends available on the current system can be found via AVAILABLE_BACKENDS.

If you already have a cv2.VideoCapture object you want to use for scene detection, you can use a VideoCaptureAdapter instead of a backend. This is useful when working with devices or streams, for example.

Video Files

Assuming we have a file video.mp4 in our working directory, we can load it and perform scene detection on it using open_video():

from scenedetect import open_video
video = open_video('video.mp4')

An optional backend from AVAILABLE_BACKENDS can be passed to open_video() (e.g. backend=’opencv’). Additional keyword arguments passed to open_video() will be forwarded to the backend constructor. If the specified backend is unavailable, or loading the video fails, opencv will be tried as a fallback.

Lastly, to use a specific backend directly:

# Manually importing and constructing a backend:
from scenedetect.backends.opencv import VideoStreamCv2
video = VideoStreamCv2('video.mp4')

In both examples above, the resulting video can be used with SceneManager.detect_scenes().

Devices / Cameras / Pipes

You can use an existing cv2.VideoCapture object with the PySceneDetect API using a VideoCaptureAdapter. For example, to use a SceneManager with a webcam device:

from scenedetect import SceneManager, ContentDetector
from scenedetect.backends import VideoCaptureAdapter
# Open device ID 2.
cap = cv2.VideoCapture(2)
video = VideoCaptureAdapter(cap)
total_frames = 1000
scene_manager = SceneManager()
scene_manager.add_detector(ContentDetector())
scene_manager.detect_scenes(video=video, duration=total_frames)

When working with live inputs, note that you can pass a callback to detect_scenes() to be called on every scene detection event. See the SceneManager examples for details.

scenedetect.backends.AVAILABLE_BACKENDS: Dict[str, Type] = {'opencv': <class 'scenedetect.backends.opencv.VideoStreamCv2'>, 'pyav': <class 'scenedetect.backends.pyav.VideoStreamAv'>}

All available backends that scenedetect.open_video() can consider for the backend parameter. These backends must support construction with the following signature:

BackendType(path: str, framerate: Optional[float])

OpenCV

VideoStreamCv2 provides an adapter for the OpenCV cv2.VideoCapture object. Works with video files, image sequences, and network streams/URLs.

Uses string identifier 'opencv'.

For wrapping input devices or pipes, there is also the VideoCaptureAdapter which can be created from an existing cv2.VideoCapture. This allows performing scene detection on inputs which do not support seeking.

class scenedetect.backends.opencv.VideoCaptureAdapter(cap, framerate=None, max_read_attempts=5)

Adapter for existing VideoCapture objects. Unlike VideoStreamCv2, this class supports VideoCaptures which may not support seeking.

Create from an existing OpenCV VideoCapture object. Used for webcams, live streams, pipes, or other inputs which may not support seeking.

Parameters
  • cap (VideoCapture) – The cv2.VideoCapture object to wrap. Must already be opened and ready to have cap.read() called on it.

  • framerate (Optional[float]) – If set, overrides the detected framerate.

  • max_read_attempts (int) – Number of attempts to continue decoding the video after a frame fails to decode. This allows processing videos that have a few corrupted frames or metadata (in which case accuracy of detection algorithms may be lower). Once this limit is passed, decoding will stop and emit an error.

Raises

ValueError – capture is not open, framerate or max_read_attempts is invalid

BACKEND_NAME = 'opencv_adapter'

Unique name used to identify this backend.

property aspect_ratio: float

Display/pixel aspect ratio as a float (1.0 represents square pixels).

property capture: cv2.VideoCapture

Returns reference to underlying VideoCapture object. Use with caution.

Prefer to use this property only to take ownership of the underlying cv2.VideoCapture object backing this object. Using the read/grab methods through this property are unsupported and will leave this object in an inconsistent state.

property duration: Optional[scenedetect.frame_timecode.FrameTimecode]

Always None, as the underlying VideoCapture is assumed to not have a known duration.

property frame_number: int

Current position within stream in frames as an int.

1 indicates the first frame was just decoded by the last call to read with advance=True, whereas 0 indicates that no frames have been read.

This method will always return 0 if no frames have been read.

property frame_rate: float

Framerate in frames/sec.

property frame_size: Tuple[int, int]

Reported size of each video frame in pixels as a tuple of (width, height).

property is_seekable: bool

Always False, as the underlying VideoCapture is assumed to not support seeking.

property name: str

Always ‘CAP_ADAPTER’.

property path: str

Always ‘CAP_ADAPTER’.

property position: scenedetect.frame_timecode.FrameTimecode

Current position within stream as FrameTimecode. Use the position_ms() if an accurate duration of elapsed time is required, as position is currently based off of the number of frames, and may not be accurate for devicesor live streams.

This method will always return 0 (e.g. be equal to base_timecode) if no frames have been read.

property position_ms: float

Current position within stream as a float of the presentation time in milliseconds. The first frame has a time of 0.0 ms.

This method will always return 0.0 if no frames have been read.

read(decode=True, advance=True)

Read and decode the next frame as a numpy.ndarray. Returns False when video ends, or the maximum number of decode attempts has passed.

Parameters
  • decode (bool) – Decode and return the frame.

  • advance (bool) – Seek to the next frame. If False, will return the current (last) frame.

Returns

If decode = True, the decoded frame (numpy.ndarray), or False (bool) if end of video. If decode = False, a bool indicating if advancing to the the next frame succeeded.

Return type

Union[ndarray, bool]

reset()

Not supported.

seek(target)

The underlying VideoCapture is assumed to not support seeking.

Parameters

target (Union[FrameTimecode, float, int]) –

class scenedetect.backends.opencv.VideoStreamCv2(path=None, framerate=None, max_decode_attempts=5, path_or_device=None)

OpenCV cv2.VideoCapture backend.

Open a video file, image sequence, or network stream.

Parameters
  • path (AnyStr) – Path to the video. Can be a file, image sequence (‘folder/DSC_%04d.jpg’), or network stream.

  • framerate (Optional[float]) – If set, overrides the detected framerate.

  • max_decode_attempts (int) – Number of attempts to continue decoding the video after a frame fails to decode. This allows processing videos that have a few corrupted frames or metadata (in which case accuracy of detection algorithms may be lower). Once this limit is passed, decoding will stop and emit an error.

  • path_or_device (Union[bytes, str, int]) – [DEPRECATED] Specify path for files, image sequences, or network streams/URLs. Use VideoCaptureAdapter for devices/pipes.

Raises
  • OSError – file could not be found or access was denied

  • VideoOpenFailure – video could not be opened (may be corrupted)

  • ValueError – specified framerate is invalid

BACKEND_NAME = 'opencv'

Unique name used to identify this backend.

property aspect_ratio: float

Display/pixel aspect ratio as a float (1.0 represents square pixels).

property capture: cv2.VideoCapture

Returns reference to underlying VideoCapture object. Use with caution.

Prefer to use this property only to take ownership of the underlying cv2.VideoCapture object backing this object. Seeking or using the read/grab methods through this property are unsupported and will leave this object in an inconsistent state.

property duration: Optional[scenedetect.frame_timecode.FrameTimecode]

Duration of the stream as a FrameTimecode, or None if non terminating.

property frame_number: int

Current position within stream in frames as an int.

1 indicates the first frame was just decoded by the last call to read with advance=True, whereas 0 indicates that no frames have been read.

This method will always return 0 if no frames have been read.

property frame_rate: float

Framerate in frames/sec.

property frame_size: Tuple[int, int]

Size of each video frame in pixels as a tuple of (width, height).

property is_seekable: bool

True if seek() is allowed, False otherwise.

Always False if opening a device/webcam.

property name: str

Name of the video, without extension, or device.

property path: Union[bytes, str]

Video or device path.

property position: scenedetect.frame_timecode.FrameTimecode

Current position within stream as FrameTimecode.

This can be interpreted as presentation time stamp of the last frame which was decoded by calling read with advance=True.

This method will always return 0 (e.g. be equal to base_timecode) if no frames have been read.

property position_ms: float

Current position within stream as a float of the presentation time in milliseconds. The first frame has a time of 0.0 ms.

This method will always return 0.0 if no frames have been read.

read(decode=True, advance=True)

Read and decode the next frame as a numpy.ndarray. Returns False when video ends, or the maximum number of decode attempts has passed.

Parameters
  • decode (bool) – Decode and return the frame.

  • advance (bool) – Seek to the next frame. If False, will return the current (last) frame.

Returns

If decode = True, the decoded frame (numpy.ndarray), or False (bool) if end of video. If decode = False, a bool indicating if advancing to the the next frame succeeded.

Return type

Union[ndarray, bool]

reset()

Close and re-open the VideoStream (should be equivalent to calling seek(0)).

seek(target)

Seek to the given timecode. If given as a frame number, represents the current seek pointer (e.g. if seeking to 0, the next frame decoded will be the first frame of the video).

For 1-based indices (first frame is frame #1), the target frame number needs to be converted to 0-based by subtracting one. For example, if we want to seek to the first frame, we call seek(0) followed by read(). If we want to seek to the 5th frame, we call seek(4) followed by read(), at which point frame_number will be 5.

Not supported if the VideoStream is a device/camera. Untested with web streams.

Parameters

target (Union[FrameTimecode, float, int]) – Target position in video stream to seek to. If float, interpreted as time in seconds. If int, interpreted as frame number.

Raises
  • SeekError – An error occurs while seeking, or seeking is not supported.

  • ValueErrortarget is not a valid value (i.e. it is negative).

scenedetect.backends.opencv.get_aspect_ratio(cap, epsilon=0.0001)

Display/pixel aspect ratio of the VideoCapture as a float (1.0 represents square pixels).

Parameters
  • cap (VideoCapture) –

  • epsilon (float) –

Return type

float

PyAV

VideoStreamAv provides an adapter for the PyAV av.InputContainer object.

Uses string identifier 'pyav'.

class scenedetect.backends.pyav.VideoStreamAv(path_or_io, framerate=None, name=None, threading_mode=None, suppress_output=False)

PyAV av.InputContainer backend.

Open a video by path.

Warning

Using threading_mode with suppress_output = True can cause lockups in your application. See the PyAV documentation for details: https://pyav.org/docs/stable/overview/caveats.html#sub-interpeters

Parameters
  • path_or_io (Union[AnyStr, BinaryIO]) – Path to the video, or a file-like object.

  • framerate (Optional[float]) – If set, overrides the detected framerate.

  • name (Optional[str]) – Overrides the name property derived from the video path. Should be set if path_or_io is a file-like object.

  • threading_mode (Optional[str]) – The PyAV video stream thread_type. See av.codec.context.ThreadType for valid threading modes (‘AUTO’, ‘FRAME’, ‘NONE’, and ‘SLICE’). If this mode is ‘AUTO’ or ‘FRAME’ and not all frames have been decoded, the video will be reopened if seekable, and the remaining frames decoded in single-threaded mode.

  • suppress_output (bool) – If False, ffmpeg output will be sent to stdout/stderr by calling av.logging.restore_default_callback() before any other library calls. If True the application may deadlock if threading_mode is set. See the PyAV documentation for details: https://pyav.org/docs/stable/overview/caveats.html#sub-interpeters

Raises
  • OSError – file could not be found or access was denied

  • VideoOpenFailure – video could not be opened (may be corrupted)

  • ValueError – specified framerate is invalid

BACKEND_NAME = 'pyav'

Unique name used to identify this backend.

property aspect_ratio: float

Pixel aspect ratio as a float (1.0 represents square pixels).

property duration: scenedetect.frame_timecode.FrameTimecode

Duration of the video as a FrameTimecode.

property frame_number: int

Current position within stream as the frame number.

Will return 0 until the first frame is read.

property frame_rate: float

Frame rate in frames/sec.

property frame_size: Tuple[int, int]

Size of each video frame in pixels as a tuple of (width, height).

property is_seekable: bool

True if seek() is allowed, False otherwise.

property name: Union[bytes, str]

Name of the video, without extension.

property path: Union[bytes, str]

Video path.

property position: scenedetect.frame_timecode.FrameTimecode

Current position within stream as FrameTimecode.

This can be interpreted as presentation time stamp, thus frame 1 corresponds to the presentation time 0. Returns 0 even if frame_number is 1.

property position_ms: float

Current position within stream as a float of the presentation time in milliseconds. The first frame has a PTS of 0.

read(decode=True, advance=True)

Read and decode the next frame as a numpy.ndarray. Returns False when video ends.

Parameters
  • decode (bool) – Decode and return the frame.

  • advance (bool) – Seek to the next frame. If False, will return the current (last) frame.

Returns

If decode = True, the decoded frame (numpy.ndarray), or False (bool) if end of video. If decode = False, a bool indicating if advancing to the the next frame succeeded.

Return type

Union[ndarray, bool]

reset()

Close and re-open the VideoStream (should be equivalent to calling seek(0)).

seek(target)

Seek to the given timecode. If given as a frame number, represents the current seek pointer (e.g. if seeking to 0, the next frame decoded will be the first frame of the video).

For 1-based indices (first frame is frame #1), the target frame number needs to be converted to 0-based by subtracting one. For example, if we want to seek to the first frame, we call seek(0) followed by read(). If we want to seek to the 5th frame, we call seek(4) followed by read(), at which point frame_number will be 5.

May not be supported on all input codecs (see is_seekable).

Parameters

target (Union[FrameTimecode, float, int]) – Target position in video stream to seek to. If float, interpreted as time in seconds. If int, interpreted as frame number.

Raises

ValueErrortarget is not a valid value (i.e. it is negative).

Return type

None

MoviePy