Skip to content

Commit 4d8b0bc

Browse files
committed
[api] Remove SparseSceneDetector and SceneManager.get_event_list()
1 parent a4d0439 commit 4d8b0bc

File tree

3 files changed

+17
-101
lines changed

3 files changed

+17
-101
lines changed

scenedetect/detector.py

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -102,45 +102,6 @@ def event_buffer_length(self) -> int:
102102
return 0
103103

104104

105-
# TODO(v0.7): Remove this early, no point in keeping it around.
106-
class SparseSceneDetector(SceneDetector):
107-
"""Base class to inherit from when implementing a sparse scene detection algorithm.
108-
109-
This class will be removed in v1.0 and should not be used.
110-
111-
Unlike dense detectors, sparse detectors detect "events" and return a *pair* of frames,
112-
as opposed to just a single cut.
113-
114-
An example of a SparseSceneDetector is the MotionDetector.
115-
116-
:meta private:
117-
"""
118-
119-
def process_frame(
120-
self, frame_num: int, frame_img: numpy.ndarray
121-
) -> ty.List[ty.Tuple[int, int]]:
122-
"""Process Frame: Computes/stores metrics and detects any scene changes.
123-
124-
Prototype method, no actual detection.
125-
126-
Returns:
127-
List of frame pairs representing individual scenes
128-
to be added to the output scene list directly.
129-
"""
130-
return []
131-
132-
def post_process(self, frame_num: int) -> ty.List[ty.Tuple[int, int]]:
133-
"""Post Process: Performs any processing after the last frame has been read.
134-
135-
Prototype method, no actual detection.
136-
137-
Returns:
138-
List of frame pairs representing individual scenes
139-
to be added to the output scene list directly.
140-
"""
141-
return []
142-
143-
144105
class FlashFilter:
145106
"""Filters fast-cuts to enforce minimum scene length."""
146107

scenedetect/scene_manager.py

Lines changed: 4 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def on_new_scene(frame_img: numpy.ndarray, frame_num: int):
101101
SimpleTableRow,
102102
)
103103
from scenedetect.common import CropRegion, CutList, SceneList
104-
from scenedetect.detector import SceneDetector, SparseSceneDetector
104+
from scenedetect.detector import SceneDetector
105105
from scenedetect.frame_timecode import FrameTimecode
106106
from scenedetect.platform import get_and_create_path, get_cv2_imwrite_params, tqdm
107107
from scenedetect.stats_manager import StatsManager
@@ -947,9 +947,7 @@ def __init__(
947947
accessed via the `stats_manager` property of the resulting object to save to disk.
948948
"""
949949
self._cutting_list = []
950-
self._event_list = []
951950
self._detector_list: ty.List[SceneDetector] = []
952-
self._sparse_detector_list = []
953951
# TODO(v1.0): This class should own a StatsManager instead of taking an optional one.
954952
# Expose a new `stats_manager` @property from the SceneManager, and either change the
955953
# `stats_manager` argument to to `store_stats: bool=False`, or lazy-init one.
@@ -1063,19 +1061,14 @@ def add_detector(self, detector: SceneDetector) -> None:
10631061
detector (SceneDetector): Scene detector to add to the SceneManager.
10641062
"""
10651063
if self._stats_manager is None and detector.stats_manager_required():
1066-
# Make sure the lists are empty so that the detectors don't get
1067-
# out of sync (require an explicit statsmanager instead)
1068-
assert not self._detector_list and not self._sparse_detector_list
1064+
assert not self._detector_list
10691065
self._stats_manager = StatsManager()
10701066

10711067
detector.stats_manager = self._stats_manager
10721068
if self._stats_manager is not None:
10731069
self._stats_manager.register_metrics(detector.get_metrics())
10741070

1075-
if not issubclass(type(detector), SparseSceneDetector):
1076-
self._detector_list.append(detector)
1077-
else:
1078-
self._sparse_detector_list.append(detector)
1071+
self._detector_list.append(detector)
10791072

10801073
self._frame_buffer_size = max(detector.event_buffer_length, self._frame_buffer_size)
10811074

@@ -1092,7 +1085,6 @@ def clear(self) -> None:
10921085
cached frame metrics that were computed and saved in the previous call to detect_scenes.
10931086
"""
10941087
self._cutting_list.clear()
1095-
self._event_list.clear()
10961088
self._last_pos = None
10971089
self._start_pos = None
10981090
self._frame_size = None
@@ -1101,7 +1093,6 @@ def clear(self) -> None:
11011093
def clear_detectors(self) -> None:
11021094
"""Remove all scene detectors added to the SceneManager via add_detector()."""
11031095
self._detector_list.clear()
1104-
self._sparse_detector_list.clear()
11051096

11061097
def get_scene_list(
11071098
self, base_timecode: ty.Optional[FrameTimecode] = None, start_in_scene: bool = False
@@ -1134,7 +1125,7 @@ def get_scene_list(
11341125
# unless start_in_scene is True.
11351126
if not cut_list and not start_in_scene:
11361127
scene_list = []
1137-
return sorted(self._get_event_list() + scene_list)
1128+
return sorted(scene_list)
11381129

11391130
def _get_cutting_list(self) -> ty.List[int]:
11401131
"""Return a sorted list of unique frame numbers of any detected scene cuts."""
@@ -1144,15 +1135,6 @@ def _get_cutting_list(self) -> ty.List[int]:
11441135
# Ensure all cuts are unique by using a set to remove all duplicates.
11451136
return [self._base_timecode + cut for cut in sorted(set(self._cutting_list))]
11461137

1147-
def _get_event_list(self) -> SceneList:
1148-
if not self._event_list:
1149-
return []
1150-
assert self._base_timecode is not None
1151-
return [
1152-
(self._base_timecode + start, self._base_timecode + end)
1153-
for start, end in self._event_list
1154-
]
1155-
11561138
def _process_frame(
11571139
self,
11581140
frame_num: int,
@@ -1177,13 +1159,6 @@ def _process_frame(
11771159
for cut_frame_num in cuts:
11781160
buffer_index = cut_frame_num - (frame_num + 1)
11791161
callback(self._frame_buffer[buffer_index], cut_frame_num)
1180-
for detector in self._sparse_detector_list:
1181-
events = detector.process_frame(frame_num, frame_im)
1182-
self._event_list += events
1183-
if callback:
1184-
for event_start, _ in events:
1185-
buffer_index = event_start - (frame_num + 1)
1186-
callback(self._frame_buffer[buffer_index], event_start)
11871162
return new_cuts
11881163

11891164
def _post_process(self, frame_num: int) -> None:
@@ -1452,8 +1427,6 @@ def get_cut_list(
14521427
the scene list, noting that each scene is contiguous starting from the first frame
14531428
and ending at the last frame detected.
14541429
1455-
If only sparse detectors are used (e.g. MotionDetector), this will always be empty.
1456-
14571430
Arguments:
14581431
base_timecode: [DEPRECATED] DO NOT USE. For backwards compatibility only.
14591432
show_warning: If set to False, suppresses the error from being warned. In v0.7,
@@ -1470,24 +1443,3 @@ def get_cut_list(
14701443
if show_warning:
14711444
logger.error("`get_cut_list()` is deprecated and will be removed in a future release.")
14721445
return self._get_cutting_list()
1473-
1474-
def get_event_list(self, base_timecode: ty.Optional[FrameTimecode] = None) -> SceneList:
1475-
"""[DEPRECATED] DO NOT USE.
1476-
1477-
Get a list of start/end timecodes of sparse detection events.
1478-
1479-
Unlike get_scene_list, the event list returns a list of FrameTimecodes representing
1480-
the point in the input video where a new scene was detected only by sparse detectors,
1481-
otherwise it is the same.
1482-
1483-
Arguments:
1484-
base_timecode: [DEPRECATED] DO NOT USE. For backwards compatibility only.
1485-
1486-
Returns:
1487-
List of pairs of FrameTimecode objects denoting the detected scenes.
1488-
1489-
:meta private:
1490-
"""
1491-
# TODO(v0.7): Use the warnings module to turn this into a warning.
1492-
logger.error("`get_event_list()` is deprecated and will be removed in a future release.")
1493-
return self._get_event_list()

website/pages/changelog.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -658,17 +658,20 @@ Development
658658
### API Changes
659659

660660
#### Breaking
661-
- Refactoring to make code less verbose:
662-
- `scenedetect.scene_detector` is now `scenedetect.detector`
663-
- `scenedetect.frame_timecode` is now `scenedetect.common`
664-
- `FrameTimecode` fields `frame_num` and `framerate` are now read-only properties, construct a new `FrameTimecode` to change them
665-
- Remove `FrameTimecode.previous_frame()` method
666-
- Remove `SceneDetector.is_processing_required()` method, already had no effect in v0.6 as part of deprecation
667-
- `SceneDetector` instances can now assume they always have frame data to process when `process_frame` is called
668-
- Remove `scenedetect.video_manager` module ([use `scenedetect.open_video()` function](https://www.scenedetect.com/docs/head/api.html#scenedetect.open_video) instead)
661+
662+
* Remove deprecated `scenedetect.video_manager` module ([use `scenedetect.open_video()` function](https://www.scenedetect.com/docs/head/api.html#scenedetect.open_video) instead)
669663
* Deprecated `video_manager` parameter has been removed from many functions and constructors, use `video` parameter instead when required
664+
* Refactoring to make code less verbose:
665+
* `scenedetect.scene_detector` is now `scenedetect.detector`
666+
* `scenedetect.frame_timecode` is now `scenedetect.common`
667+
* `FrameTimecode` fields `frame_num` and `framerate` are now read-only properties, construct a new `FrameTimecode` to change them
668+
* Remove `FrameTimecode.previous_frame()` method
669+
* Remove `SceneDetector.is_processing_required()` method, already had no effect in v0.6 as part of deprecation
670+
* `SceneDetector` instances can now assume they always have frame data to process when `process_frame` is called
671+
* Remove deprecated `SparseSceneDetector` interface
672+
* Remove deprecated `SceneManager.get_event_list()` method
670673

671674
#### Deprecation
672675

673-
- `scenedetect.scene_detector` module is now deprecated, use `scenedetect.detector` (or `scenedetect`) instead
674-
676+
* `scenedetect.scene_detector` module is now deprecated, import from `scenedetect` or `scenedetect.detector` instead
677+
* `scenedetect.frame_timecode` module is now deprecated, import from `scenedetect` or `scenedetect.common` instead

0 commit comments

Comments
 (0)