Kims12 commited on
Commit
382dbbf
ยท
verified ยท
1 Parent(s): b2ee4ad

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -120
app.py CHANGED
@@ -13,7 +13,6 @@ def add_log(message: str):
13
  """
14
  ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•˜๋Š” ํ•จ์ˆ˜
15
  """
16
- global global_logs
17
  global_logs.append(message)
18
  print(message)
19
 
@@ -38,7 +37,6 @@ def generate_thumbnail(video_clip, time_point):
38
  return thumbnail_img
39
  except Exception as e:
40
  add_log(f"[ERROR] ์ธ๋„ค์ผ ์ƒ์„ฑ ์‹คํŒจ: {e}")
41
- # ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด ์ฒซ ํ”„๋ ˆ์ž„
42
  frame = video_clip.get_frame(0)
43
  thumbnail_img = Image.fromarray(frame)
44
  return thumbnail_img
@@ -66,7 +64,7 @@ def adjust_aspect_ratio(clip, option):
66
  width, height = clip.size
67
  current_ratio = width / height
68
 
69
- # ์˜์ƒ์ด ๋„ˆ๋ฌด ๋„“์œผ๋ฉด ์ขŒ์šฐ ํฌ๋กญ, ๋„ˆ๋ฌด ๋†’์œผ๋ฉด ์ƒํ•˜ ํฌ๋กญ
70
  if current_ratio > target_ratio:
71
  new_width = int(height * target_ratio)
72
  new_height = height
@@ -74,23 +72,16 @@ def adjust_aspect_ratio(clip, option):
74
  new_width = width
75
  new_height = int(width / target_ratio)
76
 
77
- return clip.crop(
78
- x_center=width / 2,
79
- y_center=height / 2,
80
- width=new_width,
81
- height=new_height
82
- )
83
 
84
- def process_video(
85
- video,
86
- start_time_str,
87
- end_time_str,
88
- platform_option,
89
- frame_rate_factor,
90
- speed_factor,
91
- repeat_count,
92
- resolution_scale
93
- ):
94
  """
95
  ๋™์˜์ƒ์„ GIF๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
96
  """
@@ -99,7 +90,7 @@ def process_video(
99
 
100
  add_log("[LOG 1] ๋น„๋””์˜ค ์—…๋กœ๋“œ ๋ฐ ์ฒ˜๋ฆฌ ์‹œ์ž‘")
101
 
102
- # video ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ํŒŒ์ผ ๊ฒฝ๋กœ ์ถ”์ถœ
103
  video_path = video if isinstance(video, str) else video.name
104
 
105
  add_log("[LOG 2] ๋น„๋””์˜ค ๋กœ๋“œ ์ค‘...")
@@ -116,7 +107,7 @@ def process_video(
116
  start_sec = parse_time_to_seconds(start_time_str)
117
  end_sec = parse_time_to_seconds(end_time_str)
118
 
119
- # ๋ฒ”์œ„ ๋ณด์ •
120
  if start_sec < 0:
121
  start_sec = 0
122
  if end_sec <= 0 or end_sec > duration:
@@ -127,7 +118,6 @@ def process_video(
127
 
128
  add_log(f"[LOG 5] ์ ์šฉ๋œ ์‹œ์ž‘ ์‹œ๊ฐ„: {start_sec}์ดˆ, ์ข…๋ฃŒ ์‹œ๊ฐ„: {end_sec}์ดˆ")
129
 
130
- # ์˜์ƒ ์ž๋ฅด๊ธฐ
131
  add_log("[LOG 6] ์˜์ƒ ์ž๋ฅด๊ธฐ ์ž‘์—… ์ง„ํ–‰...")
132
  clip = input_video.subclip(start_sec, end_sec)
133
 
@@ -135,44 +125,34 @@ def process_video(
135
  add_log(f"[LOG 7] ํ”Œ๋žซํผ ๋น„์œจ ์กฐ์ •: {platform_option}")
136
  clip = adjust_aspect_ratio(clip, platform_option)
137
 
138
- # ์ถœ๋ ฅ ํ•ด์ƒ๋„ ์ถ•์†Œ
139
  if abs(resolution_scale - 1.0) > 1e-3:
140
  add_log(f"[LOG 7-1] ์ถœ๋ ฅ ํ•ด์ƒ๋„ ์ถ•์†Œ: {resolution_scale*100:.0f}%")
141
  clip = clip.resize(resolution_scale)
142
 
143
- # ์žฌ์ƒ์†๋„ ์กฐ์ ˆ
144
  if abs(speed_factor - 1.0) > 1e-3:
145
  add_log(f"[LOG 8] ์žฌ์ƒ์†๋„ {speed_factor}๋ฐฐ๋กœ ์กฐ์ ˆ ์ค‘...")
146
  clip = clip.fx(mp.vfx.speedx, speed_factor)
147
 
148
- # ํ”„๋ ˆ์ž„ ๋ ˆ์ดํŠธ ์ถ•์†Œ
149
  original_fps = clip.fps
150
  target_fps = original_fps * frame_rate_factor
151
  add_log(f"[LOG 9] ์ตœ์ข… ์ถœ๋ ฅ FPS: {target_fps:.2f} (์›๋ณธ FPS: {original_fps})")
152
  clip = clip.set_fps(target_fps)
153
 
154
- # ๋ฐ˜๋ณต ํšŸ์ˆ˜
155
  add_log(f"[LOG 10] GIF ๋ฐ˜๋ณต ํšŸ์ˆ˜ ์„ค์ •: {repeat_count} (0์ด๋ฉด ๋ฌดํ•œ๋ฐ˜๋ณต)")
156
- # MoviePy์˜ write_gif์—์„œ loop=N ์€ "N+1๋ฒˆ ์žฌ์ƒ"์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
157
- # ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ repeat_count = ์žฌ์ƒ ํšŸ์ˆ˜ ๋กœ ๋งž์ถ”๊ธฐ ์œ„ํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •
158
- if repeat_count == 0:
159
- loop_param = 0 # 0 => infinite
160
- else:
161
- loop_param = max(repeat_count - 1, 0)
162
-
163
  final_clip = clip
164
 
165
- # GIF ์ƒ์„ฑ
166
  add_log("[LOG 11] GIF ์ƒ์„ฑ ์ค‘...")
167
  output_filename = f"temp_{uuid.uuid4().hex}.gif"
168
  try:
169
- final_clip.write_gif(
170
- output_filename,
171
- fps=target_fps,
172
- program="ImageMagick", # ffmpeg -> ImageMagick ๋กœ ๋ณ€๊ฒฝ
173
- loop=loop_param
174
- )
175
- add_log("[LOG 12] GIF ์ƒ์„ฑ ์™„๋ฃŒ! ํŒŒ์ผ๋ช…: " + output_filename)
176
  except Exception as e:
177
  add_log(f"[ERROR] GIF ์ƒ์„ฑ ์‹คํŒจ: {e}")
178
  return None, None, "\n".join(global_logs)
@@ -217,101 +197,61 @@ with gr.Blocks() as demo:
217
  with gr.Tab("GIF ๋ณ€ํ™˜"):
218
  # ๋™์˜์ƒ ์—…๋กœ๋“œ
219
  video_input = gr.Video(label="๋™์˜์ƒ ์—…๋กœ๋“œ")
220
-
221
  # ์‹œ์ž‘/๋ ์‹œ๊ฐ„ ์ž…๋ ฅ
222
  start_time = gr.Textbox(label="์‹œ์ž‘ ์‹œ๊ฐ„ (์˜ˆ: 00:00:05)", value="00:00:00")
223
  end_time = gr.Textbox(label="์ข…๋ฃŒ ์‹œ๊ฐ„ (์˜ˆ: 00:00:10)", value="00:00:05")
224
-
225
  # ์ธ๋„ค์ผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
226
  start_thumb_output = gr.Image(label="์‹œ์ž‘ ์ธ๋„ค์ผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ")
227
  end_thumb_output = gr.Image(label="์ข…๋ฃŒ ์ธ๋„ค์ผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ")
228
-
229
- # ํ”Œ๋žซํผ๋ณ„ ํ•ด์ƒ๋„(๋น„์œจ) ์„ ํƒ (Radio)
230
  platform_option = gr.Radio(
231
  label="ํ•ด์ƒ๋„/๋น„์œจ ์„ ํƒ",
232
- choices=[
233
- "์›๋ณธ ์œ ์ง€",
234
- "์œ ํŠœ๋ธŒ (16:9)",
235
- "์‡ผ์ธ /๋ฆด์Šค (9:16)",
236
- "์ •์‚ฌ๊ฐํ˜• (1:1)",
237
- "์ธ์Šคํƒ€๊ทธ๋žจ (4:5)",
238
- "ํด๋ž˜์‹ (4:3)"
239
- ],
240
  value="์›๋ณธ ์œ ์ง€"
241
  )
242
-
243
- # ์ถœ๋ ฅ ํ•ด์ƒ๋„ ์ถ•์†Œ (1.0์ด๋ฉด ์›๋ณธ)
244
- resolution_scale_slider = gr.Slider(
245
- label="์ถœ๋ ฅ ํ•ด์ƒ๋„ ์ถ•์†Œ ๋น„์œจ (0.1 ~ 1.0)",
246
- minimum=0.1,
247
- maximum=1.0,
248
- step=0.1,
249
- value=1.0
250
- )
251
-
252
  # ํ”„๋ ˆ์ž„ ๋ ˆ์ดํŠธ, ์žฌ์ƒ ์†๋„, ๋ฐ˜๋ณต ํšŸ์ˆ˜ ์กฐ์ ˆ
253
- frame_rate_slider = gr.Slider(
254
- label="ํ”„๋ ˆ์ž„ ๋ ˆ์ดํŠธ ๋ฐฐ์œจ ์กฐ์ ˆ (0.1 ~ 1.0)",
255
- minimum=0.1,
256
- maximum=1.0,
257
- step=0.1,
258
- value=1.0
259
- )
260
- speed_slider = gr.Slider(
261
- label="์žฌ์ƒ ์†๋„ ์กฐ์ ˆ (0.5 ~ 5.0)",
262
- minimum=0.5,
263
- maximum=5.0,
264
- step=0.1,
265
- value=1.0
266
- )
267
- repeat_slider = gr.Slider(
268
- label="GIF ๋ฐ˜๋ณต ํšŸ์ˆ˜ (0=๋ฌดํ•œ, 1=1ํšŒ, 2=2ํšŒ, ...)",
269
- minimum=0,
270
- maximum=10,
271
- step=1,
272
- value=0
273
- )
274
-
275
  # GIF ์ƒ์„ฑ ๋ฒ„ํŠผ ๋ฐ ๊ฒฐ๊ณผ ์ถœ๋ ฅ
276
  generate_button = gr.Button("GIF ์ƒ์„ฑํ•˜๊ธฐ")
277
  gif_preview_output = gr.Image(label="์™„์„ฑ๋œ GIF ๋ฏธ๋ฆฌ๋ณด๊ธฐ")
278
  download_output = gr.File(label="GIF ๋‹ค์šด๋กœ๋“œ ๋งํฌ")
279
  logs_output = gr.Textbox(label="๋กœ๊ทธ ์ถœ๋ ฅ", lines=10)
280
 
281
- # ์ธ๋„ค์ผ ์—…๋ฐ์ดํŠธ ์ด๋ฒคํŠธ
282
- start_time.change(
283
- fn=update_thumbnails,
284
- inputs=[video_input, start_time, end_time],
285
- outputs=[start_thumb_output, end_thumb_output]
286
- )
287
- end_time.change(
288
- fn=update_thumbnails,
289
- inputs=[video_input, start_time, end_time],
290
- outputs=[start_thumb_output, end_thumb_output]
291
- )
292
- video_input.change(
293
- fn=update_thumbnails,
294
- inputs=[video_input, start_time, end_time],
295
- outputs=[start_thumb_output, end_thumb_output]
296
- )
297
-
298
  # GIF ์ƒ์„ฑ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ
299
  generate_button.click(
300
  fn=process_video,
301
  inputs=[
302
- video_input,
303
- start_time,
304
- end_time,
305
- platform_option,
306
- frame_rate_slider,
307
- speed_slider,
308
- repeat_slider,
309
- resolution_scale_slider
310
  ],
311
  outputs=[
312
- gif_preview_output,
313
- download_output,
314
- logs_output
315
  ]
316
  )
317
 
@@ -319,13 +259,11 @@ with gr.Blocks() as demo:
319
  "### [์‚ฌ์šฉ ๊ฐ€์ด๋“œ]\n"
320
  "1. ๋™์˜์ƒ์„ ์—…๋กœ๋“œํ•˜์„ธ์š”.\n"
321
  "2. ์‹œ์ž‘/๋ ์‹œ๊ฐ„์„ ์ž…๋ ฅํ•˜์„ธ์š”.\n"
322
- "3. ํ”Œ๋žซํผ๋ณ„ ๊ถŒ์žฅ ํ•ด์ƒ๋„/๋น„์œจ, ํ”„๋ ˆ์ž„ ๋ ˆ์ดํŠธ, ์žฌ์ƒ ์†๋„, ๋ฐ˜๋ณต ํšŸ์ˆ˜ ๋“ฑ์„ ์กฐ์ ˆํ•œ ๋’ค\n"
323
- " `GIF ์ƒ์„ฑํ•˜๊ธฐ` ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด GIF๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.\n"
324
- " - **GIF ๋ฐ˜๋ณต ํšŸ์ˆ˜** ์˜ˆ์‹œ:\n"
325
- " - 0 โ†’ ๋ฌดํ•œ๋ฐ˜๋ณต\n"
326
- " - 1 โ†’ 1ํšŒ ์žฌ์ƒ ํ›„ ์ข…๋ฃŒ\n"
327
- " - 2 โ†’ 2ํšŒ ์žฌ์ƒ ํ›„ ์ข…๋ฃŒ\n"
328
- "4. ๊ฒฐ๊ณผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์™€ ๋‹ค์šด๋กœ๋“œ ๋งํฌ๋ฅผ ํ†ตํ•ด GIF๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."
329
  )
330
 
331
  if __name__ == "__main__":
 
13
  """
14
  ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•˜๋Š” ํ•จ์ˆ˜
15
  """
 
16
  global_logs.append(message)
17
  print(message)
18
 
 
37
  return thumbnail_img
38
  except Exception as e:
39
  add_log(f"[ERROR] ์ธ๋„ค์ผ ์ƒ์„ฑ ์‹คํŒจ: {e}")
 
40
  frame = video_clip.get_frame(0)
41
  thumbnail_img = Image.fromarray(frame)
42
  return thumbnail_img
 
64
  width, height = clip.size
65
  current_ratio = width / height
66
 
67
+ # ์˜์ƒ์ด ๋„ˆ๋ฌด ๋„“๋‹ค๋ฉด ๊ฐ€๋กœ๋ฅผ, ๋„ˆ๋ฌด ๋†’๋‹ค๋ฉด ์„ธ๋กœ๋ฅผ ํฌ๋กญ
68
  if current_ratio > target_ratio:
69
  new_width = int(height * target_ratio)
70
  new_height = height
 
72
  new_width = width
73
  new_height = int(width / target_ratio)
74
 
75
+ return clip.crop(x_center=width / 2, y_center=height / 2, width=new_width, height=new_height)
 
 
 
 
 
76
 
77
+ def process_video(video,
78
+ start_time_str,
79
+ end_time_str,
80
+ platform_option, # ํ”Œ๋žซํผ๋ณ„ ๋น„์œจ ์„ ํƒ (Radio)
81
+ frame_rate_factor, # ํ”„๋ ˆ์ž„ ๋ ˆ์ดํŠธ ์ถ•์†Œ ๋ฐฐ์œจ (1.0์ด๋ฉด ์›๋ณธ)
82
+ speed_factor,
83
+ repeat_count,
84
+ resolution_scale): # ์ถœ๋ ฅ ํ•ด์ƒ๋„ ์ถ•์†Œ ๋น„์œจ (1.0์ด๋ฉด ์›๋ณธ)
 
 
85
  """
86
  ๋™์˜์ƒ์„ GIF๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
87
  """
 
90
 
91
  add_log("[LOG 1] ๋น„๋””์˜ค ์—…๋กœ๋“œ ๋ฐ ์ฒ˜๋ฆฌ ์‹œ์ž‘")
92
 
93
+ # video ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ํŒŒ์ผ ๊ฒฝ๋กœ ์ถ”์ถœ (Gradio์—์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์ด ๋ฌธ์ž์—ด์ผ ์ˆ˜ ์žˆ์Œ)
94
  video_path = video if isinstance(video, str) else video.name
95
 
96
  add_log("[LOG 2] ๋น„๋””์˜ค ๋กœ๋“œ ์ค‘...")
 
107
  start_sec = parse_time_to_seconds(start_time_str)
108
  end_sec = parse_time_to_seconds(end_time_str)
109
 
110
+ # ์‹œ๊ฐ„ ๋ฒ”์œ„ ๋ณด์ •
111
  if start_sec < 0:
112
  start_sec = 0
113
  if end_sec <= 0 or end_sec > duration:
 
118
 
119
  add_log(f"[LOG 5] ์ ์šฉ๋œ ์‹œ์ž‘ ์‹œ๊ฐ„: {start_sec}์ดˆ, ์ข…๋ฃŒ ์‹œ๊ฐ„: {end_sec}์ดˆ")
120
 
 
121
  add_log("[LOG 6] ์˜์ƒ ์ž๋ฅด๊ธฐ ์ž‘์—… ์ง„ํ–‰...")
122
  clip = input_video.subclip(start_sec, end_sec)
123
 
 
125
  add_log(f"[LOG 7] ํ”Œ๋žซํผ ๋น„์œจ ์กฐ์ •: {platform_option}")
126
  clip = adjust_aspect_ratio(clip, platform_option)
127
 
128
+ # ์ถœ๋ ฅ ํ•ด์ƒ๋„ ์ถ•์†Œ ์˜ต์…˜
129
  if abs(resolution_scale - 1.0) > 1e-3:
130
  add_log(f"[LOG 7-1] ์ถœ๋ ฅ ํ•ด์ƒ๋„ ์ถ•์†Œ: {resolution_scale*100:.0f}%")
131
  clip = clip.resize(resolution_scale)
132
 
133
+ # ์žฌ์ƒ์†๋„ ์กฐ์ ˆ: speedx๋ฅผ ์ ์šฉํ•˜๋ฉด clip.duration์€ ์ค„์–ด๋“ค์ง€๋งŒ fps๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€๋จ.
134
  if abs(speed_factor - 1.0) > 1e-3:
135
  add_log(f"[LOG 8] ์žฌ์ƒ์†๋„ {speed_factor}๋ฐฐ๋กœ ์กฐ์ ˆ ์ค‘...")
136
  clip = clip.fx(mp.vfx.speedx, speed_factor)
137
 
138
+ # FPS ์กฐ์ ˆ: ์ตœ์ข… ์ถœ๋ ฅ FPS๋Š” ํ”„๋ ˆ์ž„ ๋ ˆ์ดํŠธ ๋ฐฐ์œจ๋งŒ ๋ฐ˜์˜ (speed_factor๋Š” ์ด๋ฏธ duration์— ๋ฐ˜์˜๋จ)
139
  original_fps = clip.fps
140
  target_fps = original_fps * frame_rate_factor
141
  add_log(f"[LOG 9] ์ตœ์ข… ์ถœ๋ ฅ FPS: {target_fps:.2f} (์›๋ณธ FPS: {original_fps})")
142
  clip = clip.set_fps(target_fps)
143
 
144
+ # ๋ฐ˜๋ณต ํšŸ์ˆ˜(0: ๋ฌดํ•œ, 1~10: ์ง€์ • ํšŸ์ˆ˜)
145
  add_log(f"[LOG 10] GIF ๋ฐ˜๋ณต ํšŸ์ˆ˜ ์„ค์ •: {repeat_count} (0์ด๋ฉด ๋ฌดํ•œ๋ฐ˜๋ณต)")
 
 
 
 
 
 
 
146
  final_clip = clip
147
 
 
148
  add_log("[LOG 11] GIF ์ƒ์„ฑ ์ค‘...")
149
  output_filename = f"temp_{uuid.uuid4().hex}.gif"
150
  try:
151
+ # ImageMagick์œผ๋กœ GIF ์ƒ์„ฑ (๊ธฐ๋ณธ๊ฐ’), loop=0 => ๋ฌดํ•œ
152
+ # loop=N => GIF๊ฐ€ ์ด NํšŒ ์žฌ์ƒ (N=1์ด๋ฉด ์žฌ์ƒ ํ›„ ์ •์ง€)
153
+ loop_param = 0 if int(repeat_count) == 0 else int(repeat_count)
154
+ final_clip.write_gif(output_filename, fps=target_fps, loop=loop_param)
155
+ add_log(f"[LOG 12] GIF ์ƒ์„ฑ ์™„๋ฃŒ! ํŒŒ์ผ๋ช…: {output_filename}, loop={loop_param}")
 
 
156
  except Exception as e:
157
  add_log(f"[ERROR] GIF ์ƒ์„ฑ ์‹คํŒจ: {e}")
158
  return None, None, "\n".join(global_logs)
 
197
  with gr.Tab("GIF ๋ณ€ํ™˜"):
198
  # ๋™์˜์ƒ ์—…๋กœ๋“œ
199
  video_input = gr.Video(label="๋™์˜์ƒ ์—…๋กœ๋“œ")
 
200
  # ์‹œ์ž‘/๋ ์‹œ๊ฐ„ ์ž…๋ ฅ
201
  start_time = gr.Textbox(label="์‹œ์ž‘ ์‹œ๊ฐ„ (์˜ˆ: 00:00:05)", value="00:00:00")
202
  end_time = gr.Textbox(label="์ข…๋ฃŒ ์‹œ๊ฐ„ (์˜ˆ: 00:00:10)", value="00:00:05")
 
203
  # ์ธ๋„ค์ผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
204
  start_thumb_output = gr.Image(label="์‹œ์ž‘ ์ธ๋„ค์ผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ")
205
  end_thumb_output = gr.Image(label="์ข…๋ฃŒ ์ธ๋„ค์ผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ")
206
+ # ํ”Œ๋žซํผ๋ณ„ ํ•ด์ƒ๋„(๋น„์œจ) ์„ ํƒ (Radio ๋ฒ„ํŠผ)
 
207
  platform_option = gr.Radio(
208
  label="ํ•ด์ƒ๋„/๋น„์œจ ์„ ํƒ",
209
+ choices=["์›๋ณธ ์œ ์ง€", "์œ ํŠœ๋ธŒ (16:9)", "์‡ผ์ธ /๋ฆด์Šค (9:16)", "์ •์‚ฌ๊ฐํ˜• (1:1)", "์ธ์Šคํƒ€๊ทธ๋žจ (4:5)", "ํด๋ž˜์‹ (4:3)"],
 
 
 
 
 
 
 
210
  value="์›๋ณธ ์œ ์ง€"
211
  )
212
+ # ์ถœ๋ ฅ ํ•ด์ƒ๋„ ์ถ•์†Œ ์˜ต์…˜ (1.0์ด๋ฉด ์›๋ณธ, 0.1 ~ 1.0 ๋ฒ”์œ„)
213
+ resolution_scale_slider = gr.Slider(label="์ถœ๋ ฅ ํ•ด์ƒ๋„ ์ถ•์†Œ ๋น„์œจ (0.1 ~ 1.0)",
214
+ minimum=0.1, maximum=1.0, step=0.1, value=1.0)
 
 
 
 
 
 
 
215
  # ํ”„๋ ˆ์ž„ ๋ ˆ์ดํŠธ, ์žฌ์ƒ ์†๋„, ๋ฐ˜๋ณต ํšŸ์ˆ˜ ์กฐ์ ˆ
216
+ frame_rate_slider = gr.Slider(label="ํ”„๋ ˆ์ž„ ๋ ˆ์ดํŠธ ๋ฐฐ์œจ ์กฐ์ ˆ (0.1 ~ 1.0)",
217
+ minimum=0.1, maximum=1.0, step=0.1, value=1.0)
218
+ speed_slider = gr.Slider(label="์žฌ์ƒ ์†๋„ ์กฐ์ ˆ (0.5 ~ 5.0)",
219
+ minimum=0.5, maximum=5.0, step=0.1, value=1.0)
220
+ repeat_slider = gr.Slider(label="GIF ๋ฐ˜๋ณต ํšŸ์ˆ˜ (0: ๋ฌดํ•œ๋ฐ˜๋ณต, 1~10: ๋ฐ˜๋ณต ํšŸ์ˆ˜)",
221
+ minimum=0, maximum=10, step=1, value=0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  # GIF ์ƒ์„ฑ ๋ฒ„ํŠผ ๋ฐ ๊ฒฐ๊ณผ ์ถœ๋ ฅ
223
  generate_button = gr.Button("GIF ์ƒ์„ฑํ•˜๊ธฐ")
224
  gif_preview_output = gr.Image(label="์™„์„ฑ๋œ GIF ๋ฏธ๋ฆฌ๋ณด๊ธฐ")
225
  download_output = gr.File(label="GIF ๋‹ค์šด๋กœ๋“œ ๋งํฌ")
226
  logs_output = gr.Textbox(label="๋กœ๊ทธ ์ถœ๋ ฅ", lines=10)
227
 
228
+ # ์ธ๋„ค์ผ ์—…๋ฐ์ดํŠธ ์ด๋ฒคํŠธ (๋™์˜์ƒ ๋˜๋Š” ์‹œ๊ฐ„ ์ž…๋ ฅ ๋ณ€๊ฒฝ ์‹œ)
229
+ start_time.change(fn=update_thumbnails,
230
+ inputs=[video_input, start_time, end_time],
231
+ outputs=[start_thumb_output, end_thumb_output])
232
+ end_time.change(fn=update_thumbnails,
233
+ inputs=[video_input, start_time, end_time],
234
+ outputs=[start_thumb_output, end_thumb_output])
235
+ video_input.change(fn=update_thumbnails,
236
+ inputs=[video_input, start_time, end_time],
237
+ outputs=[start_thumb_output, end_thumb_output])
 
 
 
 
 
 
 
238
  # GIF ์ƒ์„ฑ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ
239
  generate_button.click(
240
  fn=process_video,
241
  inputs=[
242
+ video_input, # ๋™์˜์ƒ ์—…๋กœ๋“œ
243
+ start_time, # ์‹œ์ž‘ ์‹œ๊ฐ„
244
+ end_time, # ์ข…๋ฃŒ ์‹œ๊ฐ„
245
+ platform_option, # ํ”Œ๋žซํผ๋ณ„ ๋น„์œจ
246
+ frame_rate_slider, # ํ”„๋ ˆ์ž„ ๋ ˆ์ดํŠธ ๋ฐฐ์œจ
247
+ speed_slider, # ์žฌ์ƒ ์†๋„
248
+ repeat_slider, # ๋ฐ˜๋ณต ํšŸ์ˆ˜
249
+ resolution_scale_slider # ํ•ด์ƒ๋„ ์ถ•์†Œ ๋น„์œจ
250
  ],
251
  outputs=[
252
+ gif_preview_output, # ์™„์„ฑ๋œ GIF ๋ฏธ๋ฆฌ๋ณด๊ธฐ
253
+ download_output, # GIF ๋‹ค์šด๋กœ๋“œ ๋งํฌ
254
+ logs_output # ๋กœ๊ทธ ์ถœ๋ ฅ
255
  ]
256
  )
257
 
 
259
  "### [์‚ฌ์šฉ ๊ฐ€์ด๋“œ]\n"
260
  "1. ๋™์˜์ƒ์„ ์—…๋กœ๋“œํ•˜์„ธ์š”.\n"
261
  "2. ์‹œ์ž‘/๋ ์‹œ๊ฐ„์„ ์ž…๋ ฅํ•˜์„ธ์š”.\n"
262
+ "3. ํ”Œ๋žซํผ๋ณ„ ๊ถŒ์žฅ ํ•ด์ƒ๋„/๋น„์œจ(์›๋ณธ ์œ ์ง€, ์œ ํŠœ๋ธŒ, ์‡ผ์ธ /๋ฆด์Šค, ์ •์‚ฌ๊ฐํ˜•, ์ธ์Šคํƒ€๊ทธ๋žจ, ํด๋ž˜์‹)๊ณผ ์ถœ๋ ฅ ํ•ด์ƒ๋„ ์ถ•์†Œ ๋น„์œจ์„ ์„ ํƒํ•˜๊ณ ,\n"
263
+ " ํ”„๋ ˆ์ž„ ๋ ˆ์ดํŠธ ๋ฐฐ์œจ, ์žฌ์ƒ ์†๋„, ๋ฐ˜๋ณต ํšŸ์ˆ˜๋ฅผ ์กฐ์ ˆํ•œ ํ›„ `GIF ์ƒ์„ฑํ•˜๊ธฐ` ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด GIF๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.\n"
264
+ " - ๋ฐ˜๋ณต ํšŸ์ˆ˜(0: ๋ฌดํ•œ๋ฐ˜๋ณต, 1~10: ์ง€์ • ํšŸ์ˆ˜). ์˜ˆ) 1์ด๋ฉด 1ํšŒ ์žฌ์ƒ ํ›„ ๋ฉˆ์ถค, 2์ด๋ฉด 2ํšŒ ์žฌ์ƒ, 0์ด๋ฉด ๋ฌดํ•œ๋ฐ˜๋ณต.\n"
265
+ "4. ๊ฒฐ๊ณผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์™€ ๋‹ค์šด๋กœ๋“œ ๋งํฌ๋ฅผ ํ†ตํ•ด GIF๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.\n"
266
+ "โ€ป ๋ฌดํ•œ๋ฐ˜๋ณต์ด ์•„๋‹Œ ํŠน์ • ๋ฐ˜๋ณต ํšŸ์ˆ˜๋ฅผ ์›ํ•  ๊ฒฝ์šฐ, ImageMagick์ด ์„ค์น˜๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค."
 
 
267
  )
268
 
269
  if __name__ == "__main__":