scenedetect
๐ฌ Packageยถ
Overviewยถ
The scenedetect API is designed to be extensible and easy to integrate with most application workflows. Many use cases are covered by the Quickstart and Example sections below. The scenedetect package provides:
scenedetect.scene_manager ๐๏ธ: The
SceneManager
class applies SceneDetector objects on video frames from a VideoStream. Also contains thesave_images
andwrite_scene_list
/write_scene_list_html
functions to export information about the detected scenes in various formats.scenedetect.detectors ๐ต๏ธ: Scene/shot detection algorithms:
ContentDetector
: detects fast changes/cuts in video content.
ThresholdDetector
: detects changes in video brightness/intensity.
AdaptiveDetector
: similar to ContentDetector but may result in less false negatives during rapid camera movement.scenedetect.video_stream ๐ฅ: Contains
VideoStream
interface for video decoding using different backends (scenedetect.backends
). Current supported backends:
OpenCV:
VideoStreamCv2
PyAV: In Development
scenedetect.video_splitter โ๏ธ: Contains
split_video_ffmpeg
andsplit_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
base class for implementing scene detection algorithms.scenedetect.stats_manager ๐งฎ: Contains
StatsManager
class for caching frame metrics and loading/saving them to disk in CSV format for analysis. Also used as a persistent cache to make multiple passes on the same video significantly faster.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
Quickstartยถ
To get started, the scenedetect.detect()
function takes a path to a video and a scene detector object, and returns a list of start/end timecodes. For detecting fast cuts (shot changes), we use the ContentDetector
:
from scenedetect import detect, ContentDetector
scene_list = detect('my_video.mp4', ContentDetector())
scene_list
is now a list of FrameTimecode
pairs representing the start/end of each scene (try calling print(scene_list)
). Note that you can set show_progress=True
when calling detect
to display a progress bar with estimated time remaining.
Next, letโs print the scene list in a more readable format by iterating over it:
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(),))
Now that we know where each scene is, we can also split the input video automatically using ffmpeg (mkvmerge is also supported):
from scenedetect import detect, ContentDetector, split_video_ffmpeg
scene_list = detect('my_video.mp4', ContentDetector())
split_video_ffmpeg('my_video.mp4', scene_list)
This is just a small snippet of what PySceneDetect offers. The library is very modular, and can integrate with most application workflows easily.
In the next example, we show how the library components can be used to create a more customizable scene cut/shot detection pipeline. Additional demonstrations/recipes can be found in the tests/test_api.py file.
Exampleยถ
In this example, we create a function find_scenes()
which will load a video, detect the scenes, and return a list of tuples containing the (start, end) timecodes of each detected scene. Note that you can modify the threshold argument to modify the sensitivity of the ContentDetector
, or use other detection algorithms (e.g. ThresholdDetector
, AdaptiveDetector
).
from scenedetect import SceneManager, open_video, ContentDetector
def find_scenes(video_path, threshold=27.0):
video = open_video(video_path)
scene_manager = SceneManager()
scene_manager.add_detector(
ContentDetector(threshold=threshold))
# Detect all scenes in video from current position to end.
scene_manager.detect_scenes(video)
# `get_scene_list` returns a list of start/end timecode pairs
# for each scene that was found.
return scene_manager.get_scene_list()
Using a SceneManager
directly allows tweaking the Parameters passed to detect_scenes
including setting a limit to the number of frames to process, which is useful for live streams/camera devices. You can also combine detection algorithms or create new ones from scratch.
For a more advanced example of using the PySceneDetect API to with a stats file (to save per-frame metrics to disk and/or speed up multiple passes of the same video), take a look at the example in the SceneManager reference.
In addition to module-level examples, demonstrations of some common use cases can be found in the tests/test_api.py file.
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 seconds123.45
(float), or number of frames200
(int).end_time (str | float | int | None) โ Starting point in video, in the form of a timecode
HH:MM:SS[.nnn]
(str), number of seconds123.45
(float), or number of frames200
(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:
Module Referenceยถ
- Detection Algorithms
- 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
- SceneManager
- Usage
- Storing Per-Frame Statistics
Interpolation
SceneManager
SceneManager.add_detector()
SceneManager.clear()
SceneManager.clear_detectors()
SceneManager.detect_scenes()
SceneManager.get_cut_list()
SceneManager.get_event_list()
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
PROGRESS_BAR_DESCRIPTION
- Video Splitting
- StatsManager
- FrameTimecode
- SceneDetector
- 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
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.