openfree commited on
Commit
22986f6
Β·
verified Β·
1 Parent(s): e9a7e97

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -31
app.py CHANGED
@@ -8,6 +8,9 @@ import tempfile
8
  import shutil
9
  from tqdm import tqdm
10
 
 
 
 
11
  def get_video_duration(video_path):
12
  cap = cv2.VideoCapture(video_path)
13
  fps = cap.get(cv2.CAP_PROP_FPS)
@@ -17,6 +20,12 @@ def get_video_duration(video_path):
17
  return duration
18
 
19
  def extract_frames(video_path, output_dir, start_time, end_time, max_frames=10000, progress=gr.Progress()):
 
 
 
 
 
 
20
  cap = cv2.VideoCapture(video_path)
21
  fps = cap.get(cv2.CAP_PROP_FPS)
22
  total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
@@ -29,7 +38,7 @@ def extract_frames(video_path, output_dir, start_time, end_time, max_frames=1000
29
 
30
  frame_interval = max(1, (end_frame - start_frame) // max_frames)
31
 
32
- for i in progress.tqdm(range(start_frame, min(end_frame, total_frames), frame_interval), desc="ν”„λ ˆμž„ μΆ”μΆœ 쀑"):
33
  cap.set(cv2.CAP_PROP_POS_FRAMES, i)
34
  ret, frame = cap.read()
35
  if not ret:
@@ -41,6 +50,34 @@ def extract_frames(video_path, output_dir, start_time, end_time, max_frames=1000
41
  cap.release()
42
  return frames
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  def create_grid(frames, grid_size=(10, 10)):
45
  rows, cols = grid_size
46
  n_frames = len(frames)
@@ -75,7 +112,11 @@ def update_slider(video):
75
  duration = get_video_duration(video.name)
76
  return gr.Slider(minimum=0, maximum=duration, value=0, step=0.1, label="CUT μ‹œμž‘ μ‹œκ°„ (초)"), gr.Slider(minimum=0, maximum=duration, value=duration, step=0.1, label="CUT μ’…λ£Œ μ‹œκ°„ (초)")
77
 
78
- def process_video(video, start_time, end_time, progress=gr.Progress()):
 
 
 
 
79
  if video is None:
80
  return None, None, "λΉ„λ””μ˜€ νŒŒμΌμ„ μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”."
81
 
@@ -97,37 +138,12 @@ def process_video(video, start_time, end_time, progress=gr.Progress()):
97
  final_zip_path = "frames.zip"
98
  shutil.copy(zip_path, final_zip_path)
99
 
100
- return Image.fromarray(cv2.cvtColor(grid, cv2.COLOR_BGR2RGB)), final_zip_path, f"ν”„λ ˆμž„ μΆ”μΆœμ΄ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€. 총 {len(frames)}개의 ν”„λ ˆμž„μ΄ μΆ”μΆœλ˜μ—ˆμŠ΅λ‹ˆλ‹€."
 
101
  except Exception as e:
102
  return None, None, f"였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"
103
 
104
- css = """
105
- footer {
106
- visibility: hidden;
107
- }
108
- #video-time {
109
- font-size: 1.2em;
110
- font-weight: bold;
111
- margin-top: 10px;
112
- }
113
- """
114
-
115
- js = """
116
- function updateVideoTime(videoElement) {
117
- const timeDisplay = document.getElementById('video-time');
118
- videoElement.addEventListener('timeupdate', () => {
119
- const currentTime = videoElement.currentTime.toFixed(2);
120
- timeDisplay.textContent = `ν˜„μž¬ μž¬μƒ μ‹œκ°„: ${currentTime}초`;
121
- });
122
- }
123
- document.addEventListener('DOMContentLoaded', () => {
124
- const videoElement = document.querySelector('video');
125
- if (videoElement) {
126
- updateVideoTime(videoElement);
127
- }
128
- });
129
- """
130
-
131
  with gr.Blocks(theme="Nymbo/Nymbo_Theme", css=css, js=js) as iface:
132
  gr.Markdown("# λΉ„λ””μ˜€ to 이미지(ν”„λ ˆμž„)")
133
  gr.Markdown("μ›ν•˜λŠ” κ΅¬κ°„μ˜ ν”„λ ˆμž„μ„ μΆ”μΆœν•˜μ—¬ κ·Έλ¦¬λ“œλ‘œ ν‘œμ‹œν•˜κ³ , κ°œλ³„ 이미지λ₯Ό ZIP ���일둜 λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.")
@@ -143,6 +159,9 @@ with gr.Blocks(theme="Nymbo/Nymbo_Theme", css=css, js=js) as iface:
143
  start_slider = gr.Slider(minimum=0, maximum=10000, value=0, step=1, label="CUT μ‹œμž‘ μ‹œκ°„ (초)")
144
  end_slider = gr.Slider(minimum=0, maximum=10000, value=10000, step=1, label="CUT μ’…λ£Œ μ‹œκ°„ (초)")
145
 
 
 
 
146
  with gr.Row():
147
  process_button = gr.Button("ν”„λ ˆμž„ μΆ”μΆœ")
148
 
@@ -153,7 +172,7 @@ with gr.Blocks(theme="Nymbo/Nymbo_Theme", css=css, js=js) as iface:
153
  message_output = gr.Textbox(label="λ©”μ‹œμ§€")
154
 
155
  video_input.change(update_slider, inputs=[video_input], outputs=[start_slider, end_slider])
156
- process_button.click(process_video, inputs=[video_input, start_slider, end_slider], outputs=[image_output, file_output, message_output])
157
 
158
  if __name__ == "__main__":
159
  iface.launch(share=True)
 
8
  import shutil
9
  from tqdm import tqdm
10
 
11
+ # GPU μ‚¬μš© κ°€λŠ₯ μ—¬λΆ€ 확인
12
+ USE_GPU = cv2.cuda.getCudaEnabledDeviceCount() > 0
13
+
14
  def get_video_duration(video_path):
15
  cap = cv2.VideoCapture(video_path)
16
  fps = cap.get(cv2.CAP_PROP_FPS)
 
20
  return duration
21
 
22
  def extract_frames(video_path, output_dir, start_time, end_time, max_frames=10000, progress=gr.Progress()):
23
+ if USE_GPU:
24
+ return extract_frames_gpu(video_path, output_dir, start_time, end_time, max_frames, progress)
25
+ else:
26
+ return extract_frames_cpu(video_path, output_dir, start_time, end_time, max_frames, progress)
27
+
28
+ def extract_frames_cpu(video_path, output_dir, start_time, end_time, max_frames, progress):
29
  cap = cv2.VideoCapture(video_path)
30
  fps = cap.get(cv2.CAP_PROP_FPS)
31
  total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
 
38
 
39
  frame_interval = max(1, (end_frame - start_frame) // max_frames)
40
 
41
+ for i in progress.tqdm(range(start_frame, min(end_frame, total_frames), frame_interval), desc="ν”„λ ˆμž„ μΆ”μΆœ 쀑 (CPU)"):
42
  cap.set(cv2.CAP_PROP_POS_FRAMES, i)
43
  ret, frame = cap.read()
44
  if not ret:
 
50
  cap.release()
51
  return frames
52
 
53
+ def extract_frames_gpu(video_path, output_dir, start_time, end_time, max_frames, progress):
54
+ stream = cv2.cuda_Stream()
55
+ cap = cv2.cudacodec.createVideoReader(video_path)
56
+
57
+ _, first_frame = cap.nextFrame()
58
+ fps = cap.get(cv2.cudacodec.ColorFormat.FPS)
59
+ total_frames = int(cap.get(cv2.cudacodec.ColorFormat.NUMBER_OF_FRAMES))
60
+
61
+ start_frame = int(start_time * fps)
62
+ end_frame = int(end_time * fps) if end_time else total_frames
63
+
64
+ frames = []
65
+ cap.set(cv2.cudacodec.ColorFormat.POS_FRAMES, start_frame)
66
+
67
+ frame_interval = max(1, (end_frame - start_frame) // max_frames)
68
+
69
+ for i in progress.tqdm(range(start_frame, min(end_frame, total_frames), frame_interval), desc="ν”„λ ˆμž„ μΆ”μΆœ 쀑 (GPU)"):
70
+ cap.set(cv2.cudacodec.ColorFormat.POS_FRAMES, i)
71
+ ret, gpu_frame = cap.nextFrame()
72
+ if not ret:
73
+ break
74
+ cpu_frame = gpu_frame.download()
75
+ frames.append(cpu_frame)
76
+ if len(frames) >= max_frames:
77
+ break
78
+
79
+ return frames
80
+
81
  def create_grid(frames, grid_size=(10, 10)):
82
  rows, cols = grid_size
83
  n_frames = len(frames)
 
112
  duration = get_video_duration(video.name)
113
  return gr.Slider(minimum=0, maximum=duration, value=0, step=0.1, label="CUT μ‹œμž‘ μ‹œκ°„ (초)"), gr.Slider(minimum=0, maximum=duration, value=duration, step=0.1, label="CUT μ’…λ£Œ μ‹œκ°„ (초)")
114
 
115
+
116
+ def process_video(video, start_time, end_time, use_gpu, progress=gr.Progress()):
117
+ global USE_GPU
118
+ USE_GPU = use_gpu and cv2.cuda.getCudaEnabledDeviceCount() > 0
119
+
120
  if video is None:
121
  return None, None, "λΉ„λ””μ˜€ νŒŒμΌμ„ μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”."
122
 
 
138
  final_zip_path = "frames.zip"
139
  shutil.copy(zip_path, final_zip_path)
140
 
141
+ gpu_status = "GPU" if USE_GPU else "CPU"
142
+ return Image.fromarray(cv2.cvtColor(grid, cv2.COLOR_BGR2RGB)), final_zip_path, f"ν”„λ ˆμž„ μΆ”μΆœμ΄ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€ ({gpu_status} μ‚¬μš©). 총 {len(frames)}개의 ν”„λ ˆμž„μ΄ μΆ”μΆœλ˜μ—ˆμŠ΅λ‹ˆλ‹€."
143
  except Exception as e:
144
  return None, None, f"였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"
145
 
146
+ # Gradio μΈν„°νŽ˜μ΄μŠ€ μ„€μ •
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  with gr.Blocks(theme="Nymbo/Nymbo_Theme", css=css, js=js) as iface:
148
  gr.Markdown("# λΉ„λ””μ˜€ to 이미지(ν”„λ ˆμž„)")
149
  gr.Markdown("μ›ν•˜λŠ” κ΅¬κ°„μ˜ ν”„λ ˆμž„μ„ μΆ”μΆœν•˜μ—¬ κ·Έλ¦¬λ“œλ‘œ ν‘œμ‹œν•˜κ³ , κ°œλ³„ 이미지λ₯Ό ZIP ���일둜 λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.")
 
159
  start_slider = gr.Slider(minimum=0, maximum=10000, value=0, step=1, label="CUT μ‹œμž‘ μ‹œκ°„ (초)")
160
  end_slider = gr.Slider(minimum=0, maximum=10000, value=10000, step=1, label="CUT μ’…λ£Œ μ‹œκ°„ (초)")
161
 
162
+ with gr.Row():
163
+ use_gpu_checkbox = gr.Checkbox(label="GPU μ‚¬μš© (κ°€λŠ₯ν•œ 경우)", value=USE_GPU)
164
+
165
  with gr.Row():
166
  process_button = gr.Button("ν”„λ ˆμž„ μΆ”μΆœ")
167
 
 
172
  message_output = gr.Textbox(label="λ©”μ‹œμ§€")
173
 
174
  video_input.change(update_slider, inputs=[video_input], outputs=[start_slider, end_slider])
175
+ process_button.click(process_video, inputs=[video_input, start_slider, end_slider, use_gpu_checkbox], outputs=[image_output, file_output, message_output])
176
 
177
  if __name__ == "__main__":
178
  iface.launch(share=True)