Riolit commited on
Commit
f382c2d
·
verified ·
1 Parent(s): 4794db2

Update app.py

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