#!/opt/homebrew/bin/python3.11 """ CUT Processor - Scene Detection Uses PySceneDetect for scene detection (local) """ import sys import json import argparse import os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from redis_publisher import RedisPublisher def process_cut(video_path: str, output_path: str, uuid: str = ""): """Process video for scene detection""" publisher = RedisPublisher(uuid) if uuid else None if publisher: publisher.info("cut", "CUT_START") try: from scenedetect import VideoManager, SceneManager from scenedetect.detectors import ContentDetector except ImportError: if publisher: publisher.error("cut", "scenedetect not installed") result = {"frame_count": 0, "fps": 0.0, "scenes": []} if publisher: publisher.complete("cut", "0 scenes") with open(output_path, "w") as f: json.dump(result, f, indent=2) return result if publisher: publisher.info("cut", "CUT_LOADING_VIDEO") # Create video manager and scene manager video_manager = VideoManager([video_path]) scene_manager = SceneManager() # Add content detector (detects scene cuts based on frame differences) # threshold: sensitivity (lower = more sensitive, default 30) # min_scene_len: minimum frames per scene (default 15) scene_manager.add_detector(ContentDetector(threshold=30.0, min_scene_len=15)) # Set downscale factor for faster processing video_manager.set_downscale_factor() if publisher: publisher.info("cut", "CUT_DETECTING") # Start video manager video_manager.start() # Detect scenes scene_manager.detect_scenes(frame_source=video_manager) # Get scene list scene_list = scene_manager.get_scene_list() # Get frame rate fps = video_manager.get_framerate() if publisher: publisher.info("cut", f"fps={fps}") # Get total frame count frame_count = 0 if scene_list: frame_count = scene_list[-1][1].get_frames() # Convert scenes to result format scenes = [] for i, (start, end) in enumerate(scene_list): scene = { "scene_number": i + 1, "start_frame": start.get_frames(), "end_frame": end.get_frames() - 1, # end is exclusive "start_time": start.get_seconds(), "end_time": end.get_seconds() - (1.0 / fps) if fps > 0 else 0, } scenes.append(scene) if publisher: publisher.progress("cut", i + 1, len(scene_list), f"Scene {i + 1}") result = {"frame_count": frame_count, "fps": fps, "scenes": scenes} with open(output_path, "w") as f: json.dump(result, f, indent=2) if publisher: publisher.complete("cut", f"{len(scenes)} scenes") return result if __name__ == "__main__": parser = argparse.ArgumentParser(description="Scene Detection") parser.add_argument("video_path", help="Path to video file") parser.add_argument("output_path", help="Output JSON path") parser.add_argument("--uuid", "-u", help="UUID for Redis progress", default="") args = parser.parse_args() process_cut(args.video_path, args.output_path, args.uuid)