import os import json from pathlib import Path from scenedetect import VideoManager, SceneManager from scenedetect.detectors import ContentDetector from files.utils.logging import get_logger from config import make_path class SceneDetector: def __init__(self, video_path: str, backend='base', return_scenes=False, min_scene_duration=0.1, threshold=30.0, transition_merge_gap=0.1): self.video_path = video_path self.backend = backend self.return_scenes = return_scenes self.min_scene_duration = min_scene_duration self.threshold = threshold self.transition_merge_gap = transition_merge_gap log_filename = f'{Path(video_path).stem}_log.txt' self.logger = get_logger(name='scene_detect', log_file=log_filename) def detect(self, start_time: float = 0, end_time: float = -1) -> list: try: self.logger.info(f'Detecting scenes for: {self.video_path}') video_manager = VideoManager([self.video_path]) scene_manager = SceneManager() scene_manager.add_detector(ContentDetector(threshold=self.threshold)) video_manager.set_downscale_factor() video_manager.start() scene_manager.detect_scenes(frame_source=video_manager) scene_list = scene_manager.get_scene_list() # Format output to match Sieve style scenes = [] for start, end in scene_list: scenes.append({ "start": round(start.get_seconds(), 2), "end": round(end.get_seconds(), 2) }) self.logger.info(f"{len(scenes)} scenes detected.") return [{"scenes": scenes}] except Exception as e: self.logger.error(f'Scene detection failed: {e}') return [] def detect_and_save(self) -> list: scenes = self.detect() if not scenes: self.logger.warning('No scenes detected. Skipping save.') return [] out_path = make_path('processed/scene-detection', self.video_path, 'scene', 'json') out_path.parent.mkdir(parents=True, exist_ok=True) with open(out_path, 'w', encoding='utf-8') as f: json.dump({'scenes': scenes[0]['scenes']}, f, indent=2) self.logger.info(f'Scene data saved to: {out_path}') return scenes