Kims12 commited on
Commit
e3952dc
Β·
verified Β·
1 Parent(s): 8e92fe3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -79
app.py CHANGED
@@ -35,8 +35,9 @@ def generate_thumbnail(video_clip, time_point):
35
  frame = video_clip.get_frame(time_point)
36
  thumbnail_img = Image.fromarray(frame)
37
  return thumbnail_img
38
- except:
39
- # λ§Œμ•½ time_pointκ°€ μž¬μƒμ‹œκ°„ λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜λ©΄ 첫 ν”„λ ˆμž„μ„ μΈλ„€μΌλ‘œ
 
40
  frame = video_clip.get_frame(0)
41
  thumbnail_img = Image.fromarray(frame)
42
  return thumbnail_img
@@ -52,25 +53,28 @@ def process_video(video,
52
  전체 GIF λ³€ν™˜ 과정을 μˆ˜ν–‰ν•˜λŠ” ν•¨μˆ˜
53
  """
54
  global global_logs
55
- global_logs = [] # 호좜 μ‹œλ§ˆλ‹€ 둜그λ₯Ό μ΄ˆκΈ°ν™”
56
 
57
- # 둜그 1: μ—…λ‘œλ“œλœ 파일 확인
58
  add_log("[LOG 1] λΉ„λ””μ˜€ μ—…λ‘œλ“œ 및 처리 μ‹œμž‘")
59
 
60
- # λΉ„λ””μ˜€ 뢈러였기
 
 
61
  add_log("[LOG 2] λΉ„λ””μ˜€ λ‘œλ“œ 쀑...")
62
- input_video = mp.VideoFileClip(video.name)
 
 
 
 
63
 
64
- # μž¬μƒμ‹œκ°„ 좜λ ₯
65
  duration = input_video.duration
66
  add_log(f"[LOG 3] μ—…λ‘œλ“œλœ μ˜μƒμ˜ μž¬μƒμ‹œκ°„: {duration:.2f}초")
67
 
68
- # μ‹œμž‘/끝 μ‹œκ°„ parse
69
  add_log("[LOG 4] μ‹œμž‘/끝 μ‹œκ°„ νŒŒμ‹± 쀑...")
70
  start_sec = parse_time_to_seconds(start_time_str)
71
  end_sec = parse_time_to_seconds(end_time_str)
72
 
73
- # 잘λͺ»λœ μž…λ ₯ ν˜Ήμ€ λ²”μœ„ λ²—μ–΄λ‚˜λ©΄ μžλ™ 보정
74
  if start_sec < 0:
75
  start_sec = 0
76
  if end_sec <= 0 or end_sec > duration:
@@ -81,44 +85,43 @@ def process_video(video,
81
 
82
  add_log(f"[LOG 5] 적용된 μ‹œμž‘ μ‹œκ°„: {start_sec}초, μ’…λ£Œ μ‹œκ°„: {end_sec}초")
83
 
84
- # ν•΄λ‹Ή ꡬ간 자λ₯΄κΈ°(subclip)
85
  add_log("[LOG 6] μ˜μƒ 자λ₯΄κΈ° μž‘μ—… μ§„ν–‰...")
86
  clip = input_video.subclip(start_sec, end_sec)
87
 
88
- # 속도 쑰절
89
  if abs(speed_factor - 1.0) > 1e-3:
90
  add_log(f"[LOG 7] 속도 {speed_factor}배둜 쑰절 쀑...")
91
  clip = clip.fx(mp.vfx.speedx, speed_factor)
92
 
93
- # 해상도 쑰절 (κΈ°λ³Έ 1.0 = 원본)
94
  if abs(resolution_factor - 1.0) > 1e-3:
95
  add_log(f"[LOG 8] 해상도 {resolution_factor*100:.1f}%둜 쑰절 쀑...")
96
  clip = clip.resize(resolution_factor)
97
 
98
- # ν”„λ ˆμž„ 레이트 쑰절 (κΈ°λ³Έ 원본 fps)
99
  original_fps = clip.fps
100
  target_fps = original_fps * frame_rate_factor
101
  add_log(f"[LOG 9] ν”„λ ˆμž„ 레이트λ₯Ό {target_fps:.2f}둜 쑰절 쀑... (원본 {original_fps} FPS)")
102
  clip = clip.set_fps(target_fps)
103
 
104
- # 반볡 회수 (μ΅œλŒ€ 10회)
105
  repeat_count = min(max(int(repeat_count), 1), 10)
106
  add_log(f"[LOG 10] 반볡 회수: {repeat_count}회")
107
 
108
  repeated_clips = [clip] * repeat_count
109
  final_clip = mp.concatenate_videoclips(repeated_clips)
110
 
111
- # GIF 생성
112
  add_log("[LOG 11] GIF 생성 쀑...")
113
- # μž„μ‹œ 파일 이름 생성
114
  output_filename = f"temp_{uuid.uuid4().hex}.gif"
115
 
116
- final_clip.write_gif(output_filename, fps=target_fps)
117
-
118
- add_log("[LOG 12] GIF 생성 μ™„λ£Œ! 파일λͺ…: " + output_filename)
 
 
 
119
 
120
- # GIF 미리보기용 이미지 λ°˜ν™˜ (첫 ν”„λ ˆμž„)
121
- gif_preview = Image.open(output_filename)
 
 
 
122
 
123
  return gif_preview, output_filename, "\n".join(global_logs)
124
 
@@ -126,12 +129,18 @@ def update_thumbnails(video, start_time_str, end_time_str):
126
  """
127
  μ‹œμž‘/끝 썸넀일을 μ—…λ°μ΄νŠΈν•˜κΈ° μœ„ν•œ ν•¨μˆ˜
128
  """
129
- input_video = mp.VideoFileClip(video.name)
 
 
 
 
 
 
 
130
  duration = input_video.duration
131
 
132
  start_sec = parse_time_to_seconds(start_time_str)
133
  end_sec = parse_time_to_seconds(end_time_str)
134
- # λ²”μœ„ 보정
135
  if start_sec < 0:
136
  start_sec = 0
137
  if end_sec <= 0 or end_sec > duration:
@@ -152,76 +161,46 @@ with gr.Blocks() as demo:
152
  gr.Markdown("## λ™μ˜μƒμ„ GIF둜 λ³€ν™˜ν•˜κΈ° 데λͺ¨")
153
 
154
  with gr.Tab("GIF λ³€ν™˜"):
155
- # 1. μ—…λ‘œλ“œ μž…λ ₯μ°½ (μˆ˜μ •: type 인수λ₯Ό 제거)
156
  video_input = gr.Video(label="λ™μ˜μƒ μ—…λ‘œλ“œ")
157
-
158
- # 4. μ‹œμž‘/끝 λΆ€λΆ„ μ‹œκ°„ μž…λ ₯
159
  start_time = gr.Textbox(label="μ‹œμž‘ μ‹œκ°„ (예: 00:00:05)", value="00:00:00")
160
  end_time = gr.Textbox(label="μ’…λ£Œ μ‹œκ°„ (예: 00:00:10)", value="00:00:05")
161
-
162
- # 미리보기 썸넀일 (μ‹œμž‘, μ’…λ£Œ)
163
  start_thumb_output = gr.Image(label="μ‹œμž‘ 썸넀일 미리보기")
164
  end_thumb_output = gr.Image(label="μ’…λ£Œ 썸넀일 미리보기")
165
-
166
- # 6. 해상도 쑰절 μŠ¬λΌμ΄λ”(κΈ°λ³Έ 1.0)
167
  resolution_slider = gr.Slider(label="해상도 λΉ„μœ¨ 쑰절(0.1 ~ 1.0)", minimum=0.1, maximum=1.0, step=0.1, value=1.0)
168
-
169
- # 7. ν”„λ ˆμž„ 속도 쑰절 μŠ¬λΌμ΄λ”(κΈ°λ³Έ 1.0)
170
  fps_slider = gr.Slider(label="ν”„λ ˆμž„ 레이트 배율 쑰절(0.1 ~ 2.0)", minimum=0.1, maximum=2.0, step=0.1, value=1.0)
171
-
172
- # 8. 속도 쑰절 μŠ¬λΌμ΄λ”(κΈ°λ³Έ 1λ°°)
173
  speed_slider = gr.Slider(label="μž¬μƒ 속도 쑰절(0.5 ~ 2.0)", minimum=0.5, maximum=2.0, step=0.1, value=1.0)
174
-
175
- # 9. 반볡 횟수
176
  repeat_slider = gr.Slider(label="GIF 반볡 횟수(1 ~ 10)", minimum=1, maximum=10, step=1, value=1)
177
-
178
- # 10. GIF 생성 λ²„νŠΌ
179
  generate_button = gr.Button("GIF μƒμ„±ν•˜κΈ°")
180
-
181
- # 11, 12. κ²°κ³Ό 미리보기(이미지), λ‹€μš΄λ‘œλ“œ(링크)
182
  gif_preview_output = gr.Image(label="μ™„μ„±λœ GIF 미리보기")
183
  download_output = gr.File(label="GIF λ‹€μš΄λ‘œλ“œ 링크")
184
-
185
- # 둜그 좜λ ₯
186
  logs_output = gr.Textbox(label="둜그 좜λ ₯", lines=10)
187
 
188
- # 썸넀일 μ—…λ°μ΄νŠΈ 이벀트
189
- start_time.change(
190
- fn=update_thumbnails,
191
- inputs=[video_input, start_time, end_time],
192
- outputs=[start_thumb_output, end_thumb_output]
193
- )
194
- end_time.change(
195
- fn=update_thumbnails,
196
- inputs=[video_input, start_time, end_time],
197
- outputs=[start_thumb_output, end_thumb_output]
198
- )
199
-
200
- video_input.change(
201
- fn=update_thumbnails,
202
- inputs=[video_input, start_time, end_time],
203
- outputs=[start_thumb_output, end_thumb_output]
204
- )
205
-
206
- generate_button.click(
207
- fn=process_video,
208
- inputs=[
209
- video_input,
210
- start_time,
211
- end_time,
212
- resolution_slider,
213
- fps_slider,
214
- speed_slider,
215
- repeat_slider
216
- ],
217
- outputs=[
218
- gif_preview_output,
219
- download_output,
220
- logs_output
221
- ]
222
- )
223
-
224
- gr.Markdown("### [μ‚¬μš© κ°€μ΄λ“œ]\n1. λ™μ˜μƒμ„ μ—…λ‘œλ“œν•˜μ„Έμš”.\n2. μ‹œμž‘/끝 μ‹œκ°„μ„ 적절히 μž…λ ₯ν•˜μ„Έμš”.\n3. 해상도, ν”„λ ˆμž„ 속도, μž¬μƒ 속도, 반볡 횟수λ₯Ό μ‘°μ ˆν•œ λ’€ `GIF μƒμ„±ν•˜κΈ°` λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ GIFκ°€ μƒμ„±λ©λ‹ˆλ‹€.\n4. κ²°κ³Ό 미리보기와 λ‹€μš΄λ‘œλ“œ 링크λ₯Ό 톡해 GIFλ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.")
225
 
226
  if __name__ == "__main__":
227
  demo.launch()
 
35
  frame = video_clip.get_frame(time_point)
36
  thumbnail_img = Image.fromarray(frame)
37
  return thumbnail_img
38
+ except Exception as e:
39
+ add_log(f"[ERROR] 썸넀일 생성 μ‹€νŒ¨: {e}")
40
+ # time_pointκ°€ λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜λ©΄ 첫 ν”„λ ˆμž„μ„ λ°˜ν™˜
41
  frame = video_clip.get_frame(0)
42
  thumbnail_img = Image.fromarray(frame)
43
  return thumbnail_img
 
53
  전체 GIF λ³€ν™˜ 과정을 μˆ˜ν–‰ν•˜λŠ” ν•¨μˆ˜
54
  """
55
  global global_logs
56
+ global_logs = [] # 호좜 μ‹œλ§ˆλ‹€ 둜그 μ΄ˆκΈ°ν™”
57
 
 
58
  add_log("[LOG 1] λΉ„λ””μ˜€ μ—…λ‘œλ“œ 및 처리 μ‹œμž‘")
59
 
60
+ # video νŒŒλΌλ―Έν„°μ—μ„œ 파일 경둜 μΆ”μΆœ
61
+ video_path = video if isinstance(video, str) else video.name
62
+
63
  add_log("[LOG 2] λΉ„λ””μ˜€ λ‘œλ“œ 쀑...")
64
+ try:
65
+ input_video = mp.VideoFileClip(video_path)
66
+ except Exception as e:
67
+ add_log(f"[ERROR] λΉ„λ””μ˜€ λ‘œλ“œ μ‹€νŒ¨: {e}")
68
+ return None, None, "\n".join(global_logs)
69
 
 
70
  duration = input_video.duration
71
  add_log(f"[LOG 3] μ—…λ‘œλ“œλœ μ˜μƒμ˜ μž¬μƒμ‹œκ°„: {duration:.2f}초")
72
 
 
73
  add_log("[LOG 4] μ‹œμž‘/끝 μ‹œκ°„ νŒŒμ‹± 쀑...")
74
  start_sec = parse_time_to_seconds(start_time_str)
75
  end_sec = parse_time_to_seconds(end_time_str)
76
 
77
+ # λ²”μœ„ 보정
78
  if start_sec < 0:
79
  start_sec = 0
80
  if end_sec <= 0 or end_sec > duration:
 
85
 
86
  add_log(f"[LOG 5] 적용된 μ‹œμž‘ μ‹œκ°„: {start_sec}초, μ’…λ£Œ μ‹œκ°„: {end_sec}초")
87
 
 
88
  add_log("[LOG 6] μ˜μƒ 자λ₯΄κΈ° μž‘μ—… μ§„ν–‰...")
89
  clip = input_video.subclip(start_sec, end_sec)
90
 
 
91
  if abs(speed_factor - 1.0) > 1e-3:
92
  add_log(f"[LOG 7] 속도 {speed_factor}배둜 쑰절 쀑...")
93
  clip = clip.fx(mp.vfx.speedx, speed_factor)
94
 
 
95
  if abs(resolution_factor - 1.0) > 1e-3:
96
  add_log(f"[LOG 8] 해상도 {resolution_factor*100:.1f}%둜 쑰절 쀑...")
97
  clip = clip.resize(resolution_factor)
98
 
 
99
  original_fps = clip.fps
100
  target_fps = original_fps * frame_rate_factor
101
  add_log(f"[LOG 9] ν”„λ ˆμž„ 레이트λ₯Ό {target_fps:.2f}둜 쑰절 쀑... (원본 {original_fps} FPS)")
102
  clip = clip.set_fps(target_fps)
103
 
 
104
  repeat_count = min(max(int(repeat_count), 1), 10)
105
  add_log(f"[LOG 10] 반볡 회수: {repeat_count}회")
106
 
107
  repeated_clips = [clip] * repeat_count
108
  final_clip = mp.concatenate_videoclips(repeated_clips)
109
 
 
110
  add_log("[LOG 11] GIF 생성 쀑...")
 
111
  output_filename = f"temp_{uuid.uuid4().hex}.gif"
112
 
113
+ try:
114
+ final_clip.write_gif(output_filename, fps=target_fps)
115
+ add_log("[LOG 12] GIF 생성 μ™„λ£Œ! 파일λͺ…: " + output_filename)
116
+ except Exception as e:
117
+ add_log(f"[ERROR] GIF 생성 μ‹€νŒ¨: {e}")
118
+ return None, None, "\n".join(global_logs)
119
 
120
+ try:
121
+ gif_preview = Image.open(output_filename)
122
+ except Exception as e:
123
+ add_log(f"[ERROR] GIF 미리보기 이미지 생성 μ‹€νŒ¨: {e}")
124
+ gif_preview = None
125
 
126
  return gif_preview, output_filename, "\n".join(global_logs)
127
 
 
129
  """
130
  μ‹œμž‘/끝 썸넀일을 μ—…λ°μ΄νŠΈν•˜κΈ° μœ„ν•œ ν•¨μˆ˜
131
  """
132
+ video_path = video if isinstance(video, str) else video.name
133
+
134
+ try:
135
+ input_video = mp.VideoFileClip(video_path)
136
+ except Exception as e:
137
+ add_log(f"[ERROR] λΉ„λ””μ˜€ λ‘œλ“œ μ‹€νŒ¨: {e}")
138
+ return None, None
139
+
140
  duration = input_video.duration
141
 
142
  start_sec = parse_time_to_seconds(start_time_str)
143
  end_sec = parse_time_to_seconds(end_time_str)
 
144
  if start_sec < 0:
145
  start_sec = 0
146
  if end_sec <= 0 or end_sec > duration:
 
161
  gr.Markdown("## λ™μ˜μƒμ„ GIF둜 λ³€ν™˜ν•˜κΈ° 데λͺ¨")
162
 
163
  with gr.Tab("GIF λ³€ν™˜"):
164
+ # λ™μ˜μƒ μ—…λ‘œλ“œ
165
  video_input = gr.Video(label="λ™μ˜μƒ μ—…λ‘œλ“œ")
166
+ # μ‹œμž‘/끝 μ‹œκ°„ μž…λ ₯
 
167
  start_time = gr.Textbox(label="μ‹œμž‘ μ‹œκ°„ (예: 00:00:05)", value="00:00:00")
168
  end_time = gr.Textbox(label="μ’…λ£Œ μ‹œκ°„ (예: 00:00:10)", value="00:00:05")
169
+ # 썸넀일 미리보기
 
170
  start_thumb_output = gr.Image(label="μ‹œμž‘ 썸넀일 미리보기")
171
  end_thumb_output = gr.Image(label="μ’…λ£Œ 썸넀일 미리보기")
172
+ # 해상도, ν”„λ ˆμž„ 레이트, μž¬μƒ 속도, 반볡 횟수 쑰절
 
173
  resolution_slider = gr.Slider(label="해상도 λΉ„μœ¨ 쑰절(0.1 ~ 1.0)", minimum=0.1, maximum=1.0, step=0.1, value=1.0)
 
 
174
  fps_slider = gr.Slider(label="ν”„λ ˆμž„ 레이트 배율 쑰절(0.1 ~ 2.0)", minimum=0.1, maximum=2.0, step=0.1, value=1.0)
 
 
175
  speed_slider = gr.Slider(label="μž¬μƒ 속도 쑰절(0.5 ~ 2.0)", minimum=0.5, maximum=2.0, step=0.1, value=1.0)
 
 
176
  repeat_slider = gr.Slider(label="GIF 반볡 횟수(1 ~ 10)", minimum=1, maximum=10, step=1, value=1)
177
+ # GIF 생성 λ²„νŠΌ 및 κ²°κ³Ό 좜λ ₯
 
178
  generate_button = gr.Button("GIF μƒμ„±ν•˜κΈ°")
 
 
179
  gif_preview_output = gr.Image(label="μ™„μ„±λœ GIF 미리보기")
180
  download_output = gr.File(label="GIF λ‹€μš΄λ‘œλ“œ 링크")
 
 
181
  logs_output = gr.Textbox(label="둜그 좜λ ₯", lines=10)
182
 
183
+ # 썸넀일 μ—…λ°μ΄νŠΈ 이벀트 (μž…λ ₯ μ‹œκ°„μ΄λ‚˜ λ™μ˜μƒμ΄ 변경될 λ•Œ)
184
+ start_time.change(fn=update_thumbnails,
185
+ inputs=[video_input, start_time, end_time],
186
+ outputs=[start_thumb_output, end_thumb_output])
187
+ end_time.change(fn=update_thumbnails,
188
+ inputs=[video_input, start_time, end_time],
189
+ outputs=[start_thumb_output, end_thumb_output])
190
+ video_input.change(fn=update_thumbnails,
191
+ inputs=[video_input, start_time, end_time],
192
+ outputs=[start_thumb_output, end_thumb_output])
193
+ # GIF 생성 λ²„νŠΌ 이벀트
194
+ generate_button.click(fn=process_video,
195
+ inputs=[video_input, start_time, end_time,
196
+ resolution_slider, fps_slider, speed_slider, repeat_slider],
197
+ outputs=[gif_preview_output, download_output, logs_output])
198
+
199
+ gr.Markdown("### [μ‚¬μš© κ°€μ΄λ“œ]\n"
200
+ "1. λ™μ˜μƒμ„ μ—…λ‘œλ“œν•˜μ„Έμš”.\n"
201
+ "2. μ‹œμž‘/끝 μ‹œκ°„μ„ 적절히 μž…λ ₯ν•˜μ„Έμš”.\n"
202
+ "3. 해상도, ν”„λ ˆμž„ 속도, μž¬μƒ 속도, 반볡 횟수λ₯Ό μ‘°μ ˆν•œ λ’€ `GIF μƒμ„±ν•˜κΈ°` λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ GIFκ°€ μƒμ„±λ©λ‹ˆλ‹€.\n"
203
+ "4. κ²°κ³Ό 미리보기와 λ‹€μš΄λ‘œλ“œ 링크λ₯Ό 톡해 GIFλ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
  if __name__ == "__main__":
206
  demo.launch()