openfree commited on
Commit
ab3e998
Β·
verified Β·
1 Parent(s): 5c36249

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -91
app.py CHANGED
@@ -27,20 +27,10 @@ def get_video_duration(video_path):
27
  return duration
28
  except Exception as e:
29
  logging.error(f"λΉ„λ””μ˜€ 길이 계산 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
30
- raise
31
-
32
- def extract_frame(video_path, frame_number):
33
- try:
34
- cap = cv2.VideoCapture(video_path)
35
- cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
36
- ret, frame = cap.read()
37
- cap.release()
38
- return frame if ret else None
39
- except Exception as e:
40
- logging.error(f"ν”„λ ˆμž„ {frame_number} μΆ”μΆœ 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
41
- return None
42
 
43
  def extract_frames(video_path, start_time, end_time, max_frames=10000, progress=gr.Progress()):
 
44
  try:
45
  cap = cv2.VideoCapture(video_path)
46
  fps = cap.get(cv2.CAP_PROP_FPS)
@@ -50,78 +40,51 @@ def extract_frames(video_path, start_time, end_time, max_frames=10000, progress=
50
  end_frame = int(end_time * fps) if end_time else total_frames
51
 
52
  frame_interval = max(1, (end_frame - start_frame) // max_frames)
53
- frame_numbers = range(start_frame, min(end_frame, total_frames), frame_interval)
54
-
55
  frames = []
56
- with concurrent.futures.ThreadPoolExecutor(max_workers=os.cpu_count()) as executor:
57
- future_to_frame = {executor.submit(extract_frame, video_path, frame_num): frame_num for frame_num in frame_numbers}
58
- for future in progress.tqdm(concurrent.futures.as_completed(future_to_frame), total=len(frame_numbers), desc="ν”„λ ˆμž„ μΆ”μΆœ 쀑"):
59
- frame = future.result()
60
- if frame is not None:
61
- frames.append(frame)
62
- if len(frames) >= max_frames:
63
- break
 
64
 
65
  cap.release()
66
  logging.info(f"총 {len(frames)}개의 ν”„λ ˆμž„μ΄ μΆ”μΆœλ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
67
  return frames
68
  except Exception as e:
69
  logging.error(f"ν”„λ ˆμž„ μΆ”μΆœ 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
70
- raise
71
 
72
  def create_grid(frames, grid_size=(10, 10)):
73
- try:
74
- rows, cols = grid_size
75
- n_frames = len(frames)
76
- frames = frames[:rows*cols] # Limit to grid size
77
-
78
- frame_height, frame_width = frames[0].shape[:2]
79
- grid = np.zeros((frame_height * rows, frame_width * cols, 3), dtype=np.uint8)
80
-
81
- for i, frame in enumerate(frames):
82
- row = i // cols
83
- col = i % cols
84
- grid[row*frame_height:(row+1)*frame_height, col*frame_width:(col+1)*frame_width] = frame
85
-
86
- return grid
87
- except Exception as e:
88
- logging.error(f"κ·Έλ¦¬λ“œ 생성 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
89
- raise
90
 
91
  def save_frames(frames, output_dir, progress=gr.Progress()):
92
- try:
93
- os.makedirs(output_dir, exist_ok=True)
94
- for i, frame in progress.tqdm(enumerate(frames), desc="ν”„λ ˆμž„ μ €μž₯ 쀑", total=len(frames)):
95
- cv2.imwrite(os.path.join(output_dir, f"frame_{i:04d}.jpg"), frame)
96
- logging.info(f"{len(frames)}개의 ν”„λ ˆμž„μ΄ {output_dir}에 μ €μž₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
97
- except Exception as e:
98
- logging.error(f"ν”„λ ˆμž„ μ €μž₯ 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
99
- raise
100
 
101
  def create_zip(output_dir, progress=gr.Progress()):
102
- try:
103
- zip_path = os.path.join(output_dir, "frames.zip")
104
- with zipfile.ZipFile(zip_path, 'w') as zipf:
105
- files = [f for f in os.listdir(output_dir) if f.endswith('.jpg')]
106
- for file in progress.tqdm(files, desc="ZIP 파일 생성 쀑"):
107
- zipf.write(os.path.join(output_dir, file), file)
108
- logging.info(f"ZIP 파일이 μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€: {zip_path}")
109
- return zip_path
110
- except Exception as e:
111
- logging.error(f"ZIP 파일 생성 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
112
- raise
113
-
114
- def update_slider(video):
115
- try:
116
- if video is None:
117
- return gr.Slider(minimum=0, maximum=100, value=0, step=0.1, label="CUT μ‹œμž‘ μ‹œκ°„ (초)"), gr.Slider(minimum=0, maximum=100, value=100, step=0.1, label="CUT μ’…λ£Œ μ‹œκ°„ (초)")
118
- duration = get_video_duration(video.name)
119
- logging.info(f"λΉ„λ””μ˜€ 길이: {duration}초")
120
- 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 μ’…λ£Œ μ‹œκ°„ (초)")
121
- except Exception as e:
122
- logging.error(f"μŠ¬λΌμ΄λ” μ—…λ°μ΄νŠΈ 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
123
- raise
124
-
125
 
126
  def process_video(video, start_time, end_time, progress=gr.Progress()):
127
  logging.info("process_video ν•¨μˆ˜ μ‹œμž‘")
@@ -130,16 +93,16 @@ def process_video(video, start_time, end_time, progress=gr.Progress()):
130
  logging.warning("λΉ„λ””μ˜€ 파일이 μ—†μŠ΅λ‹ˆλ‹€.")
131
  return None, None, "λΉ„λ””μ˜€ νŒŒμΌμ„ μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”."
132
 
133
- logging.info(f"λΉ„λ””μ˜€ 파일: {video.name}, μ‹œμž‘ μ‹œκ°„: {start_time}, μ’…λ£Œ μ‹œκ°„: {end_time}")
134
 
135
- file_size = os.path.getsize(video.name)
136
  if file_size > 2 * 1024 * 1024 * 1024: # 2GB
137
  logging.warning("파일 크기가 2GBλ₯Ό μ΄ˆκ³Όν•©λ‹ˆλ‹€.")
138
  return None, None, "파일 크기가 2GBλ₯Ό μ΄ˆκ³Όν•©λ‹ˆλ‹€. 더 μž‘μ€ νŒŒμΌμ„ μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”."
139
 
140
  with tempfile.TemporaryDirectory() as temp_dir:
141
  logging.info("ν”„λ ˆμž„ μΆ”μΆœ μ‹œμž‘")
142
- frames = extract_frames(video.name, start_time, end_time, max_frames=10000, progress=progress)
143
  if not frames:
144
  logging.error("ν”„λ ˆμž„ μΆ”μΆœ μ‹€νŒ¨")
145
  return None, None, "ν”„λ ˆμž„ μΆ”μΆœμ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€. λΉ„λ””μ˜€ νŒŒμΌμ„ ν™•μΈν•΄μ£Όμ„Έμš”."
@@ -158,7 +121,18 @@ def process_video(video, start_time, end_time, progress=gr.Progress()):
158
  logging.error(f"λΉ„λ””μ˜€ 처리 쀑 였λ₯˜ λ°œμƒ: {str(e)}", exc_info=True)
159
  return None, None, f"였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"
160
 
161
- # Gradio μΈν„°νŽ˜μ΄μŠ€ μ„€μ •
 
 
 
 
 
 
 
 
 
 
 
162
  with gr.Blocks(theme="Nymbo/Nymbo_Theme") as iface:
163
  gr.Markdown("# λΉ„λ””μ˜€ to 이미지(ν”„λ ˆμž„)")
164
  gr.Markdown("μ›ν•˜λŠ” κ΅¬κ°„μ˜ ν”„λ ˆμž„μ„ μΆ”μΆœν•˜μ—¬ κ·Έλ¦¬λ“œλ‘œ ν‘œμ‹œν•˜κ³ , κ°œλ³„ 이미지λ₯Ό ZIP 파일둜 λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.")
@@ -168,8 +142,8 @@ with gr.Blocks(theme="Nymbo/Nymbo_Theme") as iface:
168
  video_input = gr.Video(label="Upload and Play Video")
169
 
170
  with gr.Row():
171
- start_slider = gr.Slider(minimum=0, maximum=10000, value=0, step=1, label="CUT μ‹œμž‘ μ‹œκ°„ (초)")
172
- end_slider = gr.Slider(minimum=0, maximum=10000, value=10000, step=1, label="CUT μ’…λ£Œ μ‹œκ°„ (초)")
173
 
174
  with gr.Row():
175
  process_button = gr.Button("ν”„λ ˆμž„ μΆ”μΆœ")
@@ -180,21 +154,8 @@ with gr.Blocks(theme="Nymbo/Nymbo_Theme") as iface:
180
 
181
  message_output = gr.Textbox(label="λ©”μ‹œμ§€")
182
 
183
- def on_video_change(video):
184
- logging.info("λΉ„λ””μ˜€ 파일이 λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
185
- if video is None:
186
- return gr.Slider(minimum=0, maximum=100, value=0, step=0.1), gr.Slider(minimum=0, maximum=100, value=100, step=0.1)
187
- duration = get_video_duration(video.name)
188
- logging.info(f"λΉ„λ””μ˜€ 길이: {duration}초")
189
- return gr.Slider(minimum=0, maximum=duration, value=0, step=0.1), gr.Slider(minimum=0, maximum=duration, value=duration, step=0.1)
190
-
191
  video_input.change(on_video_change, inputs=[video_input], outputs=[start_slider, end_slider])
192
-
193
- def on_process_click(video, start_time, end_time):
194
- logging.info("ν”„λ ˆμž„ μΆ”μΆœ λ²„νŠΌμ΄ ν΄λ¦­λ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
195
- return process_video(video, start_time, end_time)
196
-
197
- process_button.click(on_process_click, inputs=[video_input, start_slider, end_slider], outputs=[image_output, file_output, message_output])
198
 
199
  if __name__ == "__main__":
200
  logging.info("μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹œμž‘")
 
27
  return duration
28
  except Exception as e:
29
  logging.error(f"λΉ„λ””μ˜€ 길이 계산 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
30
+ return 0
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  def extract_frames(video_path, start_time, end_time, max_frames=10000, progress=gr.Progress()):
33
+ logging.info(f"ν”„λ ˆμž„ μΆ”μΆœ μ‹œμž‘: {video_path}, μ‹œμž‘ μ‹œκ°„: {start_time}, μ’…λ£Œ μ‹œκ°„: {end_time}")
34
  try:
35
  cap = cv2.VideoCapture(video_path)
36
  fps = cap.get(cv2.CAP_PROP_FPS)
 
40
  end_frame = int(end_time * fps) if end_time else total_frames
41
 
42
  frame_interval = max(1, (end_frame - start_frame) // max_frames)
 
 
43
  frames = []
44
+
45
+ for i in progress.tqdm(range(start_frame, min(end_frame, total_frames), frame_interval)):
46
+ cap.set(cv2.CAP_PROP_POS_FRAMES, i)
47
+ ret, frame = cap.read()
48
+ if not ret:
49
+ break
50
+ frames.append(frame)
51
+ if len(frames) >= max_frames:
52
+ break
53
 
54
  cap.release()
55
  logging.info(f"총 {len(frames)}개의 ν”„λ ˆμž„μ΄ μΆ”μΆœλ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
56
  return frames
57
  except Exception as e:
58
  logging.error(f"ν”„λ ˆμž„ μΆ”μΆœ 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
59
+ return []
60
 
61
  def create_grid(frames, grid_size=(10, 10)):
62
+ rows, cols = grid_size
63
+ n_frames = len(frames)
64
+ frames = frames[:rows*cols] # Limit to grid size
65
+
66
+ frame_height, frame_width = frames[0].shape[:2]
67
+ grid = np.zeros((frame_height * rows, frame_width * cols, 3), dtype=np.uint8)
68
+
69
+ for i, frame in enumerate(frames):
70
+ row = i // cols
71
+ col = i % cols
72
+ grid[row*frame_height:(row+1)*frame_height, col*frame_width:(col+1)*frame_width] = frame
73
+
74
+ return grid
 
 
 
 
75
 
76
  def save_frames(frames, output_dir, progress=gr.Progress()):
77
+ os.makedirs(output_dir, exist_ok=True)
78
+ for i, frame in progress.tqdm(enumerate(frames), desc="ν”„λ ˆμž„ μ €μž₯ 쀑", total=len(frames)):
79
+ cv2.imwrite(os.path.join(output_dir, f"frame_{i:04d}.jpg"), frame)
 
 
 
 
 
80
 
81
  def create_zip(output_dir, progress=gr.Progress()):
82
+ zip_path = os.path.join(output_dir, "frames.zip")
83
+ with zipfile.ZipFile(zip_path, 'w') as zipf:
84
+ files = [f for f in os.listdir(output_dir) if f.endswith('.jpg')]
85
+ for file in progress.tqdm(files, desc="ZIP 파일 생성 쀑"):
86
+ zipf.write(os.path.join(output_dir, file), file)
87
+ return zip_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
  def process_video(video, start_time, end_time, progress=gr.Progress()):
90
  logging.info("process_video ν•¨μˆ˜ μ‹œμž‘")
 
93
  logging.warning("λΉ„λ””μ˜€ 파일이 μ—†μŠ΅λ‹ˆλ‹€.")
94
  return None, None, "λΉ„λ””μ˜€ νŒŒμΌμ„ μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”."
95
 
96
+ logging.info(f"λΉ„λ””μ˜€ 파일: {video}, μ‹œμž‘ μ‹œκ°„: {start_time}, μ’…λ£Œ μ‹œκ°„: {end_time}")
97
 
98
+ file_size = os.path.getsize(video)
99
  if file_size > 2 * 1024 * 1024 * 1024: # 2GB
100
  logging.warning("파일 크기가 2GBλ₯Ό μ΄ˆκ³Όν•©λ‹ˆλ‹€.")
101
  return None, None, "파일 크기가 2GBλ₯Ό μ΄ˆκ³Όν•©λ‹ˆλ‹€. 더 μž‘μ€ νŒŒμΌμ„ μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”."
102
 
103
  with tempfile.TemporaryDirectory() as temp_dir:
104
  logging.info("ν”„λ ˆμž„ μΆ”μΆœ μ‹œμž‘")
105
+ frames = extract_frames(video, start_time, end_time, max_frames=10000, progress=progress)
106
  if not frames:
107
  logging.error("ν”„λ ˆμž„ μΆ”μΆœ μ‹€νŒ¨")
108
  return None, None, "ν”„λ ˆμž„ μΆ”μΆœμ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€. λΉ„λ””μ˜€ νŒŒμΌμ„ ν™•μΈν•΄μ£Όμ„Έμš”."
 
121
  logging.error(f"λΉ„λ””μ˜€ 처리 쀑 였λ₯˜ λ°œμƒ: {str(e)}", exc_info=True)
122
  return None, None, f"였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"
123
 
124
+ def on_video_change(video):
125
+ logging.info("λΉ„λ””μ˜€ 파일이 λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
126
+ if video is None:
127
+ return gr.Slider(minimum=0, maximum=100, value=0, step=0.1), gr.Slider(minimum=0, maximum=100, value=100, step=0.1)
128
+ try:
129
+ duration = get_video_duration(video)
130
+ logging.info(f"λΉ„λ””μ˜€ 길이: {duration}초")
131
+ return gr.Slider(minimum=0, maximum=duration, value=0, step=0.1), gr.Slider(minimum=0, maximum=duration, value=duration, step=0.1)
132
+ except Exception as e:
133
+ logging.error(f"λΉ„λ””μ˜€ 정보 νšλ“ 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
134
+ return gr.Slider(minimum=0, maximum=100, value=0, step=0.1), gr.Slider(minimum=0, maximum=100, value=100, step=0.1)
135
+
136
  with gr.Blocks(theme="Nymbo/Nymbo_Theme") as iface:
137
  gr.Markdown("# λΉ„λ””μ˜€ to 이미지(ν”„λ ˆμž„)")
138
  gr.Markdown("μ›ν•˜λŠ” κ΅¬κ°„μ˜ ν”„λ ˆμž„μ„ μΆ”μΆœν•˜μ—¬ κ·Έλ¦¬λ“œλ‘œ ν‘œμ‹œν•˜κ³ , κ°œλ³„ 이미지λ₯Ό ZIP 파일둜 λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.")
 
142
  video_input = gr.Video(label="Upload and Play Video")
143
 
144
  with gr.Row():
145
+ start_slider = gr.Slider(minimum=0, maximum=100, value=0, step=0.1, label="CUT μ‹œμž‘ μ‹œκ°„ (초)")
146
+ end_slider = gr.Slider(minimum=0, maximum=100, value=100, step=0.1, label="CUT μ’…λ£Œ μ‹œκ°„ (초)")
147
 
148
  with gr.Row():
149
  process_button = gr.Button("ν”„λ ˆμž„ μΆ”μΆœ")
 
154
 
155
  message_output = gr.Textbox(label="λ©”μ‹œμ§€")
156
 
 
 
 
 
 
 
 
 
157
  video_input.change(on_video_change, inputs=[video_input], outputs=[start_slider, end_slider])
158
+ process_button.click(process_video, inputs=[video_input, start_slider, end_slider], outputs=[image_output, file_output, message_output])
 
 
 
 
 
159
 
160
  if __name__ == "__main__":
161
  logging.info("μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹œμž‘")