Skip to content

Commit de5a63b

Browse files
committed
[scene_detector] Make detector interface an ABC and cleanup properties
1 parent be345cc commit de5a63b

File tree

3 files changed

+34
-27
lines changed

3 files changed

+34
-27
lines changed

scenedetect/detector.py

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"""
2626

2727
import typing as ty
28+
from abc import ABC, abstractmethod
2829
from enum import Enum
2930

3031
import numpy
@@ -33,36 +34,18 @@
3334
from scenedetect.stats_manager import StatsManager
3435

3536

36-
class SceneDetector:
37+
class SceneDetector(ABC):
3738
"""Base class to inherit from when implementing a scene detection algorithm.
3839
3940
This API is not yet stable and subject to change.
4041
"""
4142

42-
# TODO(v0.7): Make this a proper abstract base class.
43+
def __init__(self):
44+
self._stats_manager: ty.Optional[StatsManager] = None
4345

44-
# TODO(v0.7): This should be a property.
45-
stats_manager: ty.Optional[StatsManager] = None
46-
"""Optional :class:`StatsManager <scenedetect.stats_manager.StatsManager>` to
47-
use for caching frame metrics to and from."""
48-
49-
def stats_manager_required(self) -> bool:
50-
"""Stats Manager Required: Prototype indicating if detector requires stats.
51-
52-
Returns:
53-
True if a StatsManager is required for the detector, False otherwise.
54-
"""
55-
return False
56-
57-
def get_metrics(self) -> ty.List[str]:
58-
"""Returns a list of all metric names/keys used by this detector.
59-
60-
Returns:
61-
List of strings of frame metric key names that will be used by
62-
the detector when a StatsManager is passed to process_frame.
63-
"""
64-
return []
46+
# Required Methods
6547

48+
@abstractmethod
6649
def process_frame(
6750
self, timecode: FrameTimecode, frame_img: numpy.ndarray
6851
) -> ty.List[FrameTimecode]:
@@ -75,7 +58,8 @@ def process_frame(
7558
Returns:
7659
List of timecodes where scene cuts have been detected, if any.
7760
"""
78-
return []
61+
62+
# Optional Methods
7963

8064
def post_process(self, timecode: int) -> ty.List[FrameTimecode]:
8165
"""Called after there are no more frames to process.
@@ -95,6 +79,30 @@ def event_buffer_length(self) -> int:
9579
"""
9680
return 0
9781

82+
# Frame Stats/Metrics
83+
84+
@property
85+
def stats_manager(self) -> ty.Optional[StatsManager]:
86+
"""Optional :class:`StatsManager <scenedetect.stats_manager.StatsManager>` to use for
87+
storing frame metrics. When this detector is added to a parent
88+
:class:`SceneManager <scenedetect.scene_manager.SceneManager>`, then this is set to the
89+
same :class:`StatsManager <scenedetect.stats_manager.StatsManager>` of the parent - but
90+
only if it has one itself."""
91+
return self._stats_manager
92+
93+
@stats_manager.setter
94+
def stats_manager(self, value: ty.Optional[StatsManager]):
95+
self._stats_manager = value
96+
97+
def get_metrics(self) -> ty.List[str]:
98+
"""Returns a list of all metric names/keys used by this detector.
99+
100+
Returns:
101+
List of strings of frame metric key names that will be used by
102+
the detector when a StatsManager is passed to process_frame.
103+
"""
104+
return []
105+
98106

99107
class FlashFilter:
100108
"""Filters fast-cuts to enforce minimum scene length."""

scenedetect/scene_manager.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,6 @@ def add_detector(self, detector: SceneDetector) -> None:
313313
Arguments:
314314
detector (SceneDetector): Scene detector to add to the SceneManager.
315315
"""
316-
if self._stats_manager is None and detector.stats_manager_required():
317-
assert not self._detector_list
318-
self._stats_manager = StatsManager()
319316

320317
detector.stats_manager = self._stats_manager
321318
if self._stats_manager is not None:

website/pages/changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,8 @@ Although there have been minimal changes to most API examples, there are several
703703
* Remove deprecated `AdaptiveDetector.get_content_val()` method (the same information can be obtained using a `StatsManager`)
704704
* Remove deprecated `AdaptiveDetector` constructor argument `min_delta_hsv` (use `min_content_val` instead)
705705
* Remove `advance` parameter from `VideoStream.read()` (was always set to `True`, callers should handle caching frames now if required)
706+
* Remove `SceneDetector.stats_manager_required` property as it is no longer required
707+
* Remove `SceneDetector` is now a Python abstract class (`abc.ABC`) but all method names remain the same
706708

707709
#### General
708710

0 commit comments

Comments
 (0)