#!/opt/homebrew/bin/python3.11 import sys import os import subprocess import json import argparse def get_duration(video_path): result = subprocess.run( ["ffprobe", "-v", "quiet", "-print_format", "json", "-show_format", video_path], capture_output=True, text=True, ) data = json.loads(result.stdout) return float(data["format"]["duration"]) def extract_thumbnails(video_path, uuid, output_dir, count=6): """Extract evenly-spaced thumbnails from video.""" if not os.path.exists(video_path): print(f"Error: Video file not found: {video_path}", file=sys.stderr) return None duration = get_duration(video_path) print(f"Video duration: {duration:.2f}s", file=sys.stderr) # Output directory thumb_dir = os.path.join(output_dir, uuid) os.makedirs(thumb_dir, exist_ok=True) # Calculate timestamps (skip first 10%, skip last 10%) start_ts = duration * 0.1 end_ts = duration * 0.9 interval = (end_ts - start_ts) / (count - 1) if count > 1 else 0 extracted = [] for i in range(count): if count == 1: ts = duration / 2 else: ts = start_ts + (interval * i) output_file = os.path.join(thumb_dir, f"thumb_{i:03d}.jpg") result = subprocess.run( [ "ffmpeg", "-y", "-ss", str(ts), "-i", video_path, "-vframes", "1", "-q:v", "2", "-vf", "scale=320:-1", output_file, ], capture_output=True, ) if result.returncode == 0 and os.path.exists(output_file): extracted.append(output_file) print(f" Extracted: {output_file} at {ts:.1f}s", file=sys.stderr) else: print(f" Failed to extract frame at {ts:.1f}s", file=sys.stderr) return extracted def main(): parser = argparse.ArgumentParser( description="Extract keyframe thumbnails from video" ) parser.add_argument("video_path", help="Path to video file") parser.add_argument("uuid", help="Video UUID") parser.add_argument("-o", "--output", default="thumbnails", help="Output directory") parser.add_argument( "-c", "--count", type=int, default=6, help="Number of thumbnails" ) args = parser.parse_args() result = extract_thumbnails(args.video_path, args.uuid, args.output, args.count) if result: print(json.dumps({"uuid": args.uuid, "count": len(result), "files": result})) else: print(json.dumps({"error": "Failed to extract thumbnails"})) sys.exit(1) if __name__ == "__main__": main()