Spaces:
Sleeping
Sleeping
| 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() | |