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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -40
app.py CHANGED
@@ -13,6 +13,10 @@ import logging
13
  # λ‘œκΉ… μ„€μ •
14
  logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
15
 
 
 
 
 
16
  def get_video_duration(video_path):
17
  try:
18
  cap = cv2.VideoCapture(video_path)
@@ -118,73 +122,51 @@ def update_slider(video):
118
  logging.error(f"μŠ¬λΌμ΄λ” μ—…λ°μ΄νŠΈ 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
119
  raise
120
 
 
121
  def process_video(video, start_time, end_time, progress=gr.Progress()):
 
122
  try:
123
- logging.info("λΉ„λ””μ˜€ 처리 μ‹œμž‘")
124
  if video is None:
 
125
  return None, None, "λΉ„λ””μ˜€ νŒŒμΌμ„ μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”."
126
 
 
 
127
  file_size = os.path.getsize(video.name)
128
- if file_size > 2 * 1024 * 1024 * 1024: # 2GB in bytes
 
129
  return None, None, "파일 크기가 2GBλ₯Ό μ΄ˆκ³Όν•©λ‹ˆλ‹€. 더 μž‘μ€ νŒŒμΌμ„ μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”."
130
 
131
  with tempfile.TemporaryDirectory() as temp_dir:
 
132
  frames = extract_frames(video.name, start_time, end_time, max_frames=10000, progress=progress)
133
  if not frames:
 
134
  return None, None, "ν”„λ ˆμž„ μΆ”μΆœμ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€. λΉ„λ””μ˜€ νŒŒμΌμ„ ν™•μΈν•΄μ£Όμ„Έμš”."
135
 
 
136
  save_frames(frames, temp_dir, progress=progress)
137
  grid = create_grid(frames)
138
  zip_path = create_zip(temp_dir, progress=progress)
139
 
140
- # κ²°κ³Ό νŒŒμΌμ„ μž„μ‹œ 디렉토리 λ°–μœΌλ‘œ 볡사
141
  final_zip_path = "frames.zip"
142
  shutil.copy(zip_path, final_zip_path)
143
 
144
  logging.info("λΉ„λ””μ˜€ 처리 μ™„λ£Œ")
145
- return Image.fromarray(cv2.cvtColor(grid, cv2.COLOR_BGR2RGB)), final_zip_path, f"ν”„λ ˆμž„ μΆ”μΆœμ΄ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€. 총 {len(frames)}개의 ν”„λ ˆμž„μ΄ μΆ”μΆœλ˜μ—ˆμŠ΅λ‹ˆλ‹€."
146
  except Exception as e:
147
- logging.error(f"λΉ„λ””μ˜€ 처리 쀑 였λ₯˜ λ°œμƒ: {str(e)}")
148
  return None, None, f"였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"
149
 
150
- css = """
151
- footer {
152
- visibility: hidden;
153
- }
154
- #video-time {
155
- font-size: 1.2em;
156
- font-weight: bold;
157
- margin-top: 10px;
158
- }
159
- """
160
-
161
- js = """
162
- function updateVideoTime(videoElement) {
163
- const timeDisplay = document.getElementById('video-time');
164
- videoElement.addEventListener('timeupdate', () => {
165
- const currentTime = videoElement.currentTime.toFixed(2);
166
- timeDisplay.textContent = `ν˜„μž¬ μž¬μƒ μ‹œκ°„: ${currentTime}초`;
167
- });
168
- }
169
- document.addEventListener('DOMContentLoaded', () => {
170
- const videoElement = document.querySelector('video');
171
- if (videoElement) {
172
- updateVideoTime(videoElement);
173
- }
174
- });
175
- """
176
-
177
- with gr.Blocks(theme="Nymbo/Nymbo_Theme", css=css, js=js) as iface:
178
  gr.Markdown("# λΉ„λ””μ˜€ to 이미지(ν”„λ ˆμž„)")
179
  gr.Markdown("μ›ν•˜λŠ” κ΅¬κ°„μ˜ ν”„λ ˆμž„μ„ μΆ”μΆœν•˜μ—¬ κ·Έλ¦¬λ“œλ‘œ ν‘œμ‹œν•˜κ³ , κ°œλ³„ 이미지λ₯Ό ZIP 파일둜 λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.")
180
- gr.Markdown("μ΅œλŒ€ 2GB 크기의 λΉ„λ””μ˜€ νŒŒμΌμ„ μ—…λ‘œλ“œν•  수 있으며, μ΅œλŒ€ 10000개의 ν”„λ ˆμž„μ„ μΆ”μΆœν•©λ‹ˆλ‹€.")
181
 
182
  with gr.Row():
183
  video_input = gr.Video(label="Upload and Play Video")
184
 
185
- with gr.Row():
186
- gr.HTML("<div id='video-time'>ν˜„μž¬ μž¬μƒ μ‹œκ°„: 0.00초</div>")
187
-
188
  with gr.Row():
189
  start_slider = gr.Slider(minimum=0, maximum=10000, value=0, step=1, label="CUT μ‹œμž‘ μ‹œκ°„ (초)")
190
  end_slider = gr.Slider(minimum=0, maximum=10000, value=10000, step=1, label="CUT μ’…λ£Œ μ‹œκ°„ (초)")
@@ -198,8 +180,23 @@ with gr.Blocks(theme="Nymbo/Nymbo_Theme", css=css, js=js) as iface:
198
 
199
  message_output = gr.Textbox(label="λ©”μ‹œμ§€")
200
 
201
- video_input.change(update_slider, inputs=[video_input], outputs=[start_slider, end_slider])
202
- process_button.click(process_video, inputs=[video_input, start_slider, end_slider], outputs=[image_output, file_output, message_output])
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
204
  if __name__ == "__main__":
205
- iface.launch(share=True)
 
 
 
13
  # λ‘œκΉ… μ„€μ •
14
  logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
15
 
16
+ # GPU μ‚¬μš© κ°€λŠ₯ μ—¬λΆ€ 확인
17
+ USE_GPU = cv2.cuda.getCudaEnabledDeviceCount() > 0
18
+ logging.info(f"GPU μ‚¬μš© κ°€λŠ₯: {USE_GPU}")
19
+
20
  def get_video_duration(video_path):
21
  try:
22
  cap = cv2.VideoCapture(video_path)
 
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 ν•¨μˆ˜ μ‹œμž‘")
128
  try:
 
129
  if video is None:
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, "ν”„λ ˆμž„ μΆ”μΆœμ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€. λΉ„λ””μ˜€ νŒŒμΌμ„ ν™•μΈν•΄μ£Όμ„Έμš”."
146
 
147
+ logging.info(f"μΆ”μΆœλœ ν”„λ ˆμž„ 수: {len(frames)}")
148
  save_frames(frames, temp_dir, progress=progress)
149
  grid = create_grid(frames)
150
  zip_path = create_zip(temp_dir, progress=progress)
151
 
 
152
  final_zip_path = "frames.zip"
153
  shutil.copy(zip_path, final_zip_path)
154
 
155
  logging.info("λΉ„λ””μ˜€ 처리 μ™„λ£Œ")
156
+ return Image.fromarray(cv2.cvtColor(grid, cv2.COLOR_BGR2RGB)), final_zip_path, f"ν”„λ ˆμž„ μΆ”μΆœμ΄ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€. 총 {len(frames)}개의 ν”„λ ˆμž„μ΄ μΆ”μΆœλ˜μ—ˆμŠ΅λ‹ˆλ‹€. ({'GPU' if USE_GPU else 'CPU'} μ‚¬μš©)"
157
  except Exception as e:
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 파일둜 λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.")
165
+ gr.Markdown(f"μ΅œλŒ€ 2GB 크기의 λΉ„λ””μ˜€ νŒŒμΌμ„ μ—…λ‘œλ“œν•  수 있으며, μ΅œλŒ€ 10000개의 ν”„λ ˆμž„μ„ μΆ”μΆœν•©λ‹ˆλ‹€. ({'GPU' if USE_GPU else 'CPU'} μ‚¬μš©)")
166
 
167
  with gr.Row():
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 μ’…λ£Œ μ‹œκ°„ (초)")
 
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("μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹œμž‘")
201
+ iface.launch(share=True)
202
+ logging.info("μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ’…λ£Œ")