Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion scenedetect/detectors/adaptive_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ def process_frame(self, timecode: FrameTimecode, frame_img: np.ndarray) -> list[
threshold_met: bool = (
adaptive_ratio >= self.adaptive_threshold and target_score >= self.min_content_val
)
min_length_met: bool = (timecode - self._last_cut) >= self.min_scene_len
# Cuts are emitted at `target_timecode` (`window_width` behind `timecode`).
min_length_met: bool = (target_timecode - self._last_cut) >= self.min_scene_len
if threshold_met and min_length_met:
self._last_cut = target_timecode
return [target_timecode]
Expand Down
31 changes: 31 additions & 0 deletions tests/test_detectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import os
from dataclasses import dataclass

import numpy as np
import pytest

from scenedetect import FrameTimecode, SceneDetector, SceneManager, StatsManager, detect
Expand Down Expand Up @@ -261,3 +262,33 @@ def test_min_scene_len_accepts_time_values(detector_type, min_scene_len):
scene_list = test_case.detect()
start_frames = [timecode.frame_num for timecode, _ in scene_list]
assert start_frames == test_case.scene_boundaries


def test_adaptive_detector_min_scene_len_uses_target_frame():
"""AdaptiveDetector applies min_scene_len to the emitted cut, not the current frame.

AdaptiveDetector scores a target frame `window_width` behind the frame currently
being processed. Comparing min_scene_len against the current frame lets a second
peak emit a cut only `window_width` frames after the previous one (issue #408).
"""
window_width = 20
min_scene_len = 24
detector = AdaptiveDetector(
adaptive_threshold=2.0,
window_width=window_width,
min_scene_len=min_scene_len,
min_content_val=15.0,
luma_only=True,
)
fps = 30.0
n_frames = 180
cuts: list[FrameTimecode] = []
for frame_num in range(n_frames):
# Hard cuts at 100 and 104 (4 frames apart) plus a later valid cut at 140.
# The 4-frame pair matches the report: min_scene_len - window_width.
value = 255 if 100 <= frame_num <= 103 or 140 <= frame_num <= 143 else 0
frame = np.full((16, 16, 3), value, dtype=np.uint8)
cuts.extend(detector.process_frame(FrameTimecode(frame_num, fps), frame))

cut_frames = [cut.frame_num for cut in cuts]
assert cut_frames == [100, 140]
1 change: 1 addition & 0 deletions website/pages/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,7 @@ Development

## PySceneDetect 0.7.2 (TBD)

- [bugfix] Fix `AdaptiveDetector` / `detect-adaptive` emitting scenes shorter than `min_scene_len` when `window_width` is large, by applying the minimum-length check to the emitted (target) frame instead of the current frame [#408](https://github.com/Breakthrough/PySceneDetect/issues/408)
- [general] The `scenedetect-core` package introduced in 0.7.1 has been discontinued, and its only release (0.7.1) yanked from PyPI: pip cannot safely support multiple packages that install the same module files, and restructuring the existing packages around a shared core would break in-place upgrades. Existing `scenedetect-core` installs keep working but will not receive updates; continue to install `scenedetect` or `scenedetect-headless` as usual.
- [improvement] `HistogramDetector` (`detect-hist`) default `threshold` changed from 0.05 to 0.20 and default `bins` from 256 to 128, calibrated from the [benchmark sweep](https://www.scenedetect.com/benchmarks/) for significantly better accuracy. Default output for this detector will change [#559](https://github.com/Breakthrough/PySceneDetect/issues/559)
- [improvement] `HashDetector` (`detect-hash`) default `threshold` changed from 0.395 to 0.35 and default `size` from 16 to 8, calibrated from the [benchmark sweep](https://www.scenedetect.com/benchmarks/) for better accuracy. Default output for this detector will change, including the statsfile metric key (now `hash_dist [size=8 lowpass=2]`) [#559](https://github.com/Breakthrough/PySceneDetect/issues/559)
Expand Down
Loading