#!/usr/bin/env python3 """ JumpCutter Wrapper Script for AIGCPanel This script wraps the jumpcutter Python library to integrate with AIGCPanel's video processing workflow. """ import argparse import os import sys import json import tempfile from pathlib import Path # Add jumpcutter to path if it exists in a subdirectory script_dir = Path(__file__).parent jumpcutter_path = script_dir / "jumpcutter" if jumpcutter_path.exists(): sys.path.insert(0, str(jumpcutter_path)) # Try to import jumpcutter try: from jumpcutter.clip import Clip except ImportError as e: print(f"Error importing jumpcutter: {e}", file=sys.stderr) print("Please ensure jumpcutter is installed or the jumpcutter directory contains the required files", file=sys.stderr) sys.exit(1) def main(): parser = argparse.ArgumentParser(description="JumpCutter wrapper for AIGCPanel") # Required arguments parser.add_argument("--input", "-i", required=True, help="Path to input video file") parser.add_argument("--output", "-o", required=True, help="Path to output video file") # JumpCutter specific arguments parser.add_argument("--cut", "-c", choices=["silent", "voiced", "both"], default="silent", help="Parts to cut: silent, voiced, or both") parser.add_argument("--magnitude-threshold-ratio", "-m", type=float, default=0.02, help="Audio signal magnitude threshold ratio") parser.add_argument("--duration-threshold", "-d", type=float, default=0.5, help="Minimum duration of silence in seconds") parser.add_argument("--failure-tolerance-ratio", "-f", type=float, default=0.1, help="Failure tolerance ratio") parser.add_argument("--space-on-edges", "-s", type=float, default=0.1, help="Space to leave on edges in seconds") parser.add_argument("--silence-part-speed", "-x", type=int, help="Speed up silent parts instead of cutting") parser.add_argument("--min-loud-part-duration", "-l", type=int, default=-1, help="Minimum duration of loud parts in seconds") parser.add_argument("--codec", type=str, help="Video codec") parser.add_argument("--bitrate", type=str, help="Video bitrate") args = parser.parse_args() try: # Validate input file exists if not os.path.exists(args.input): print(f"Error: Input file does not exist: {args.input}", file=sys.stderr) return 1 # Ensure output directory exists output_dir = os.path.dirname(os.path.abspath(args.output)) os.makedirs(output_dir, exist_ok=True) # Create Clip object and process clip = Clip( args.input, min_loud_part_duration=args.min_loud_part_duration, silence_part_speed=args.silence_part_speed ) cuts = [args.cut] if args.cut != "both" else ["silent", "voiced"] print(f"Processing video: {args.input}") print(f"Output: {args.output}") print(f"Cut mode: {args.cut}") print(f"Magnitude threshold ratio: {args.magnitude_threshold_ratio}") print(f"Duration threshold: {args.duration_threshold}s") print(f"Failure tolerance ratio: {args.failure_tolerance_ratio}") print(f"Space on edges: {args.space_on_edges}s") if args.silence_part_speed: print(f"Silence part speed: {args.silence_part_speed}x") if args.min_loud_part_duration > -1: print(f"Min loud part duration: {args.min_loud_part_duration}s") # Process the video outputs = clip.jumpcut( cuts, args.magnitude_threshold_ratio, args.duration_threshold, args.failure_tolerance_ratio, args.space_on_edges ) # Save the results for cut_type, jumpcutted_clip in outputs.items(): if len(outputs) == 2: output_path = f"{os.path.splitext(args.output)[0]}_{cut_type}_parts_cut{os.path.splitext(args.output)[1]}" else: output_path = args.output kwargs = {} if args.codec: kwargs['codec'] = args.codec if args.bitrate: kwargs['bitrate'] = args.bitrate print(f"Saving processed video: {output_path}") jumpcutted_clip.write_videofile(output_path, **kwargs) # Create output stats file stats_file = f"{os.path.splitext(args.output)[0]}_stats.json" stats = { "input": args.input, "output": args.output, "cut_mode": args.cut, "params": { "magnitude_threshold_ratio": args.magnitude_threshold_ratio, "duration_threshold": args.duration_threshold, "failure_tolerance_ratio": args.failure_tolerance_ratio, "space_on_edges": args.space_on_edges, "silence_part_speed": args.silence_part_speed, "min_loud_part_duration": args.min_loud_part_duration, "codec": args.codec, "bitrate": args.bitrate } } with open(stats_file, 'w') as f: json.dump(stats, f, indent=2) print(f"Processing complete: {args.output}") return 0 except Exception as e: print(f"Error processing video: {e}", file=sys.stderr) return 1 if __name__ == "__main__": sys.exit(main())