Spaces:
Sleeping
Sleeping
File size: 2,914 Bytes
f382c2d 898530d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
import cv2
import zipfile
import os
import tempfile
import gradio as gr
def extract_frames_to_zip(video_path, num_frames=10):
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
raise RuntimeError(f"Could not open video: {video_path}")
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
if frame_count <= 0:
raise RuntimeError("Could not determine frame count.")
num_frames = min(num_frames, frame_count)
if num_frames == 1:
frame_indices = [0]
else:
frame_indices = [
round(i * (frame_count - 1) / (num_frames - 1))
for i in range(num_frames)
]
# Create a temp directory for this run
tmp_dir = tempfile.mkdtemp()
zip_path = os.path.join(tmp_dir, "frames.zip")
with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zf:
for idx, frame_idx in enumerate(frame_indices):
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_idx)
ret, frame = cap.read()
if not ret:
print(f"Warning: Could not read frame at index {frame_idx}")
continue
success, buffer = cv2.imencode(".jpg", frame)
if not success:
print(f"Warning: Could not encode frame at index {frame_idx}")
continue
filename_in_zip = f"frame_{idx:02d}.jpg"
zf.writestr(filename_in_zip, buffer.tobytes())
cap.release()
return zip_path
def gradio_fn(video_file, num_frames):
"""
video_file: path to uploaded video (from Gradio Video input)
num_frames: integer from slider
"""
if video_file is None:
raise gr.Error("Please upload a video first.")
# Gradio passes a dict for Video { 'name': ..., 'data': ... } in some versions,
# but in newer versions it passes a filepath string. Handle both.
if isinstance(video_file, dict):
video_path = video_file.get("name") or video_file.get("data")
else:
video_path = video_file
if not video_path or not os.path.exists(video_path):
raise gr.Error("Uploaded video file not found on the server.")
zip_path = extract_frames_to_zip(video_path, int(num_frames))
return zip_path
with gr.Blocks() as demo:
gr.Markdown("# Video Frame Extractor\nUpload a video and get N evenly spaced frames as a ZIP.")
with gr.Row():
video_input = gr.Video(label="Upload video", sources=["upload"])
num_frames_input = gr.Slider(
minimum=2,
maximum=30,
value=10,
step=1,
label="Number of frames to extract",
)
zip_output = gr.File(label="Download frames ZIP")
run_btn = gr.Button("Extract frames")
run_btn.click(
fn=gradio_fn,
inputs=[video_input, num_frames_input],
outputs=[zip_output],
)
if __name__ == "__main__":
demo.launch() |