import gradio as gr from moviepy.editor import VideoFileClip from PIL import Image import numpy as np import os import uuid FRECUENCIA = 5 # segundos entre capturas DURACION_MAXIMA = 30 # tope de duración a procesar (segundos) os.makedirs("frames", exist_ok=True) def extract_frames(video): # 1) Guardar binario a disco video_id = str(uuid.uuid4())[:8] video_filename = f"{video_id}.mp4" video_path = os.path.join("frames", video_filename) with open(video_path, "wb") as f: f.write(video.read()) # 2) Carpeta para frames video_frames_dir = os.path.join("frames", video_id) os.makedirs(video_frames_dir, exist_ok=True) # 3) Procesar video clip = VideoFileClip(video_path) try: duration = int(min(clip.duration or 0, DURACION_MAXIMA)) frame_filepaths = [] for t in range(0, max(duration, 0), FRECUENCIA): frame = clip.get_frame(t) # numpy array (H, W, 3) frame_path = os.path.join(video_frames_dir, f"frame_{t}s.jpg") Image.fromarray(np.uint8(frame)).save(frame_path, quality=90) frame_filepaths.append(frame_path) finally: clip.close() # 4) Devolvemos: # a) Files => Gradio publica y te da URLs /file=... # b) JSON con metadatos meta = { "video_id": video_id, "total_frames": len(frame_filepaths), "frequency_seconds": FRECUENCIA, "processed_seconds": duration } return frame_filepaths, meta iface = gr.Interface( fn=extract_frames, inputs=gr.File(type="binary", label="Upload MP4"), outputs=[ gr.Files(label="Frames"), # => enlaces descargables públicos gr.JSON(label="Metadata") # => info útil ], title="Video Frame Extractor", allow_flagging="never" ) iface.launch()