{"record":{"id":"48133ca6e0e78a49","repo":"docling-project/docling","slug":"min-scene-duration-seconds-must-be-0","errorCode":null,"errorMessage":"min_scene_duration_seconds must be >= 0","messagePattern":"min_scene_duration_seconds must be >= 0","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"docling/utils/video_frame_sampling.py","lineNumber":340,"sourceCode":"    \"\"\"\n\n    def __init__(\n        self,\n        probe_fps: float = 1.0,\n        prominence: float | None = None,\n        cuts_per_minute: float | None = None,\n        min_scene_duration_seconds: float = 2.0,\n        max_frames: int | None = None,\n        probe_size: int = 64,\n        smooth_window: int = 1,\n        sharpness_candidates: int = 5,\n    ):\n        if probe_fps <= 0:\n            raise ValueError(\"probe_fps must be > 0\")\n        if prominence is not None and prominence < 0:\n            raise ValueError(\"prominence must be >= 0\")\n        if min_scene_duration_seconds < 0:\n            raise ValueError(\"min_scene_duration_seconds must be >= 0\")\n        if max_frames is not None and max_frames <= 0:\n            raise ValueError(\"max_frames must be > 0 when set\")\n        self.probe_fps = probe_fps\n        self.prominence = prominence\n        self.cuts_per_minute = cuts_per_minute\n        self.min_scene_duration_seconds = min_scene_duration_seconds\n        self.max_frames = max_frames\n        self.probe_size = probe_size\n        self.smooth_window = smooth_window\n        self.sharpness_candidates = sharpness_candidates\n\n    def _probe_frames(self, video_path: Path) -> list[tuple[float, Image.Image]]:\n        \"\"\"Extract downscaled RGB probe frames at probe_fps in a single decode pass.\"\"\"\n        return _extract_frames_grid(video_path, self.probe_fps, self.probe_size)\n\n    @staticmethod\n    def _mean_abs_diff(a: Image.Image, b: Image.Image) -> float:\n        \"\"\"Normalized mean absolute difference of two images in [0, 1].\"\"\"","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/utils/video_frame_sampling.py#L322-L358","documentation":"ValueError raised by the scene-detection sampler's __init__ in docling/utils/video_frame_sampling.py when min_scene_duration_seconds is negative. This parameter enforces a minimum scene length by suppressing cuts closer than the given duration to the previous one; negative durations have no geometric meaning for ordering cuts on a timeline, so they are rejected at construction time.","triggerScenarios":"Constructing the scene detector with min_scene_duration_seconds=-1 or any negative value, e.g. when a caller tries to express 'no minimum' as -1 instead of 0.0.","commonSituations":"Config conventions where -1 means 'disabled' colliding with an API that uses 0.0 for 'no minimum'; arithmetic slips when computing the minimum from cuts_per_minute targets (e.g. 60 / rate with rate as a negative or inverted value).","solutions":["Use 0.0 to disable the minimum-scene-duration constraint; keep the value positive otherwise (default 2.0).","Translate sentinel config values before construction: min_dur = 0.0 if cfg.min_scene_duration in (-1, None) else cfg.min_scene_duration.","Double-check formulas that derive the duration from cuts-per-minute budgets for sign/order-of-operations errors."],"exampleFix":"# before\nsampler = SceneAwareSampler(min_scene_duration_seconds=cfg.min_scene)  # cfg uses -1 = off\n\n# after\nmin_scene = 0.0 if cfg.min_scene in (-1, None) else cfg.min_scene\nsampler = SceneAwareSampler(min_scene_duration_seconds=min_scene)","handlingStrategy":"validation","validationCode":"min_dur = 0.0 if cfg.min_scene_duration in (-1, None) else cfg.min_scene_duration\nif min_dur < 0:\n    raise ValueError(\"min_scene_duration_seconds cannot be negative\")\nsampler = SceneAwareSampler(min_scene_duration_seconds=min_dur)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use 0.0 to disable minimum scene duration; never a negative number.","Translate -1/'disabled' config sentinels to 0.0 or the default at the config boundary.","Check sign on values derived from cuts-per-minute arithmetic."],"tags":["video","validation","scene-detection","constructor"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}