Shot Based Segmenter
Content-based shot segmenter without OpenCV / FFmpeg-Python dependencies.
Frame decoding is delegated to the backend-swappable
FrameDecodeProcessor
family (backend="gstreamer" decodes with system GStreamer plugins,
backend="ffmpeg" shells out to the system ffmpeg binary). Shot scoring
uses mean absolute HSV-plane distance between adjacent frames on numpy +
scikit-image (skimage.color.rgb2hsv), with an adaptive neighbour-ratio
detector implemented in pure numpy.
FIPS note: with the default GStreamer FrameDecodeProcessor backend, this
segmenter never imports cv2 and never loads the FFmpeg blobs bundled in
opencv-python / PyAV wheels. The scoring dependencies (numpy +
scikit-image) ship in the existing video-ffmpeg / video-gst
extras; GStreamer decoding needs system GStreamer (video-gst extra).
Switch decode backends via the composite backend preference or
set_processor_backend("FrameDecodeProcessor", ...).
Detector semantics:
content— cut when the HSV distance score>= threshold(default27.0; planes are scaled to 0–255 before the mean-absolute-difference).adaptive— cut whenscore / neighbour_mean >= thresholdandscore >= min_content_val. Neighbours arewindow_widthframes on each side of the current frame (current frame excluded).thresholdis the adaptive ratio.threshold— cut when the absolute change in mean frame brightness (raw RGB mean, matching PySceneDetectThresholdDetector)>= threshold. HSV conversion is skipped in this mode.
Assumes a constant framerate (sample-caps framerate, 30.0 fallback).
Detector
Bases: StrEnum
Supported shot-detector algorithm names.
ShotBasedSegmenter(detector=Detector.CONTENT, threshold=27.0, min_shot_duration=1.0, min_content_val=15.0, window_width=2, sample_fps=5, target_width=320)
Bases: BaseSegmenter
Segment video into shots with swappable decode + numpy/skimage scoring.
Frame decoding is delegated to the nested FrameDecodeProcessor family
(GStreamer by default; override via composite backend or
set_processor_backend); shot scoring runs on numpy + scikit-image.
Attributes:
| Name | Type | Description |
|---|---|---|
detector |
Detector
|
|
_config |
_ShotBasedSegmenterConfig
|
Validated scoring and decode knobs. |
Initialize the FIPS-friendly content segmenter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
detector
|
Detector | str
|
Detector algorithm. Defaults to |
CONTENT
|
threshold
|
float
|
Detector threshold. For |
27.0
|
min_shot_duration
|
float
|
Minimum shot length in seconds. Defaults to 1.0. |
1.0
|
min_content_val
|
float
|
|
15.0
|
window_width
|
int
|
|
2
|
sample_fps
|
int | None
|
Decode-time sampling rate.
Defaults to 5. Pass |
5
|
target_width
|
int | None
|
Downscale decode width.
Defaults to 320. Pass |
320
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
ValidationError
|
If scoring / decode knobs fail |
ImportError
|
If numpy / scikit-image / Pillow are not installed. |
adaptive_cut_indices(scores, *, adaptive_threshold, min_content_val, min_scene_len, window_width)
Cut on adaptive ratio of the score against its neighbour mean.
For each frame i, the neighbour mean is the average of
window_width scores on each side (current frame excluded). A cut
requires score / neighbour_mean >= adaptive_threshold and
score >= min_content_val.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scores
|
list[float]
|
Per-frame content scores. |
required |
adaptive_threshold
|
float
|
Required ratio above the neighbour mean. |
required |
min_content_val
|
float
|
Minimum absolute content score. |
required |
min_scene_len
|
int
|
Minimum cut spacing in frames. |
required |
window_width
|
int
|
Neighbour half-window in frames (per side). |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
list[int]: Cut frame indices. |
brightness_cut_indices(brightness, *, threshold, min_scene_len)
Cut on large frame-to-frame brightness changes (brightness-delta).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
brightness
|
list[float]
|
Per-frame mean brightness values. |
required |
threshold
|
float
|
Cut when |
required |
min_scene_len
|
int
|
Minimum cut spacing in frames. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
list[int]: Cut frame indices. |
content_cut_indices(scores, *, threshold, min_scene_len)
Cut where the content score meets threshold, spaced by min_scene_len.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scores
|
list[float]
|
Per-frame content scores. |
required |
threshold
|
float
|
Cut threshold (compared with |
required |
min_scene_len
|
int
|
Minimum cut spacing in frames. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
list[int]: Cut frame indices. |
enforce_min_scene_len(indices, min_scene_len)
Drop cut indices closer than min_scene_len frames to the kept cut.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
indices
|
list[int]
|
Candidate cut frame indices in ascending order. |
required |
min_scene_len
|
int
|
Minimum spacing in frames. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
list[int]: Filtered cut indices (first candidate always kept). |
mean_pixel_distance(left, right)
Mean absolute per-pixel distance between two equally shaped planes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
left
|
Any
|
First 2D plane (numpy array). |
required |
right
|
Any
|
Second 2D plane (numpy array, same shape as |
required |
Returns:
| Name | Type | Description |
|---|---|---|
float |
float
|
|
rgb_frame_to_hsv_planes(frame)
Convert an RGB uint8 frame to H/S/V planes scaled to 0–255.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frame
|
Any
|
HxWx3 |
required |
Returns:
| Type | Description |
|---|---|
tuple[Any, Any, Any]
|
tuple[Any, Any, Any]: |
score_frame_stream(frames, *, include_content=True)
Score a stream of RGB frames in one pass with O(1) frame memory.
This bounds Python RAM for frames, not decoder disk usage. The decode path still materialises the full sampled PNG sequence before the first yield.
When include_content is True, each frame is converted to HSV and
scored with mean-absolute plane distance. When False (threshold
detector), brightness is the raw RGB mean and HSV work is skipped.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frames
|
Iterable[Any]
|
RGB |
required |
include_content
|
bool
|
Compute HSV content scores. Defaults to True. |
True
|
Returns:
| Type | Description |
|---|---|
tuple[list[float], list[float]]
|
tuple[list[float], list[float]]: |