Skip to content

Commit ef47b0f

Browse files
committed
[scene_manager] Skip processing frames with incorrect resolution
Most detectors fire an assertion when the frame size mismatches, so this avoids crashing in these cases. Log an error with the timecode when a frame hits this case.
1 parent 520112e commit ef47b0f

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

scenedetect/_cli/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,9 @@ def detect_hist_command(ctx: click.Context, threshold: Optional[float], bins: Op
758758
min_scene_len: Optional[str]):
759759
"""Finds fast cuts by differencing YUV histograms.
760760
761+
Uses Y channel after converting each frame to YUV to create a histogram of each frame.
762+
Histograms between frames are compared to determine a score for how similar they are.
763+
761764
Examples:
762765
763766
detect-hist
@@ -781,7 +784,7 @@ def detect_hist_command(ctx: click.Context, threshold: Optional[float], bins: Op
781784
type=click.FloatRange(CONFIG_MAP["detect-hash"]["threshold"].min_val,
782785
CONFIG_MAP["detect-hash"]["threshold"].max_val),
783786
default=None,
784-
help=("How much of a difference between subsequent hash values should trigger a cut.%s" %
787+
help=("Represents maximum difference between hash values before a cut is triggered.%s" %
785788
(USER_CONFIG.get_help_string("detect-hash", "threshold"))))
786789
@click.option(
787790
"--size",

scenedetect/scene_manager.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ def on_new_scene(frame_img: numpy.ndarray, frame_num: int):
111111
MAX_FRAME_QUEUE_LENGTH: int = 4
112112
"""Maximum number of decoded frames which can be buffered while waiting to be processed."""
113113

114+
MAX_FRAME_SIZE_ERRORS: int = 16
115+
"""Maximum number of frame size error messages that can be logged."""
116+
114117
PROGRESS_BAR_DESCRIPTION = ' Detected: %d | Progress'
115118
"""Template to use for progress bar."""
116119

@@ -578,6 +581,9 @@ def __init__(
578581
self._start_pos: FrameTimecode = None
579582
# Position of video on the last frame processed by detect_scenes.
580583
self._last_pos: FrameTimecode = None
584+
# Size of the decoded frames.
585+
self._frame_size: Tuple[int, int] = None
586+
self._frame_size_errors: int = 0
581587
self._base_timecode: Optional[FrameTimecode] = None
582588
self._downscale: int = 1
583589
self._auto_downscale: bool = True
@@ -677,6 +683,7 @@ def clear(self) -> None:
677683
self._event_list.clear()
678684
self._last_pos = None
679685
self._start_pos = None
686+
self._frame_size = None
680687
self.clear_detectors()
681688

682689
def clear_detectors(self) -> None:
@@ -923,6 +930,28 @@ def _decode_thread(
923930
frame_im = video.read()
924931
if frame_im is False:
925932
break
933+
# Verify the decoded frame size against the video container's reported
934+
# resolution, and also verify that consecutive frames have the correct size.
935+
decoded_size = (frame_im.shape[1], frame_im.shape[0])
936+
if self._frame_size is None:
937+
self._frame_size = decoded_size
938+
if video.frame_size != decoded_size:
939+
logger.warn(
940+
f"WARNING: Decoded frame size ({decoded_size}) does not match "
941+
f" video resolution {video.frame_size}, possible corrupt input.")
942+
elif self._frame_size != decoded_size:
943+
self._frame_size_errors += 1
944+
if self._frame_size_errors <= MAX_FRAME_SIZE_ERRORS:
945+
logger.error(
946+
f"ERROR: Frame at {str(video.position)} has incorrect size and "
947+
f"cannot be processed: decoded size = {decoded_size}, "
948+
f"expected = {self._frame_size}. Video may be corrupt.")
949+
if self._frame_size_errors == MAX_FRAME_SIZE_ERRORS:
950+
logger.warn(
951+
f"WARNING: Too many errors emitted, skipping future messages.")
952+
# Skip processing frames that have an incorrect size.
953+
continue
954+
926955
if downscale_factor > 1:
927956
frame_im = cv2.resize(
928957
frame_im, (round(frame_im.shape[1] / downscale_factor),

0 commit comments

Comments
 (0)