seawolf2357 commited on
Commit
05707ed
ยท
verified ยท
1 Parent(s): 7b6405d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +151 -57
app.py CHANGED
@@ -124,30 +124,46 @@ class ModelManager:
124
  logger.info("Loading model with memory optimizations...")
125
  clear_gpu_memory()
126
 
127
- # ๋ชจ๋ธ ์ปดํฌ๋„ŒํŠธ ๋กœ๋“œ (๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ )
128
- with torch.cuda.amp.autocast(enabled=False):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  image_encoder = CLIPVisionModel.from_pretrained(
130
  config.model_id,
131
  subfolder="image_encoder",
132
- torch_dtype=torch.float16, # float32 ๋Œ€์‹  float16 ์‚ฌ์šฉ
133
  low_cpu_mem_usage=True
134
  )
135
 
136
  vae = AutoencoderKLWan.from_pretrained(
137
  config.model_id,
138
  subfolder="vae",
139
- torch_dtype=torch.float16, # float32 ๋Œ€์‹  float16 ์‚ฌ์šฉ
140
  low_cpu_mem_usage=True
141
  )
142
 
143
- self._pipe = WanImageToVideoPipeline.from_pretrained(
144
- config.model_id,
145
- vae=vae,
146
- image_encoder=image_encoder,
147
- torch_dtype=torch.bfloat16,
148
- low_cpu_mem_usage=True,
149
- use_safetensors=True
150
- )
151
 
152
  # ์Šค์ผ€์ค„๋Ÿฌ ์„ค์ •
153
  self._pipe.scheduler = UniPCMultistepScheduler.from_config(
@@ -155,20 +171,24 @@ class ModelManager:
155
  )
156
 
157
  # LoRA ๋กœ๋“œ
158
- causvid_path = hf_hub_download(
159
- repo_id=config.lora_repo_id, filename=config.lora_filename
160
- )
161
- self._pipe.load_lora_weights(causvid_path, adapter_name="causvid_lora")
162
- self._pipe.set_adapters(["causvid_lora"], adapter_weights=[0.95])
163
- self._pipe.fuse_lora()
 
 
 
 
164
 
165
  # GPU ์ตœ์ ํ™” ์„ค์ •
166
  if hasattr(spaces, 'GPU'): # Zero GPU ํ™˜๊ฒฝ
167
  self._pipe.enable_model_cpu_offload()
168
  logger.info("CPU offload enabled for Zero GPU")
169
- elif config.enable_model_cpu_offload:
170
  self._pipe.enable_model_cpu_offload()
171
- else:
172
  self._pipe.to("cuda")
173
 
174
  if config.enable_vae_slicing:
@@ -284,9 +304,12 @@ class VideoGenerator:
284
  required_memory = (height * width * 3 * 8 * duration * self.config.fixed_fps) / (1024**3)
285
  if free_memory < required_memory * 2:
286
  clear_gpu_memory()
287
- return False, "โš ๏ธ Not enough GPU memory. Try smaller dimensions or shorter duration."
288
- except:
289
- pass # GPU ์ฒดํฌ ์‹คํŒจ์‹œ ๊ณ„์† ์ง„ํ–‰
 
 
 
290
 
291
  return True, None
292
 
@@ -394,26 +417,46 @@ def generate_video(input_image, prompt, height, width,
394
  progress(0.4, desc="๐ŸŽฌ Generating video frames...")
395
 
396
  # ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ ์ธ ์ƒ์„ฑ
397
- with torch.inference_mode(), torch.cuda.amp.autocast(enabled=True):
398
- try:
399
- output_frames_list = pipe(
400
- image=resized_image,
401
- prompt=prompt,
402
- negative_prompt=negative_prompt,
403
- height=target_h,
404
- width=target_w,
405
- num_frames=num_frames,
406
- guidance_scale=float(guidance_scale),
407
- num_inference_steps=int(steps),
408
- generator=torch.Generator(device="cuda").manual_seed(current_seed),
409
- return_dict=True
410
- ).frames[0]
411
- except torch.cuda.OutOfMemoryError:
412
- clear_gpu_memory()
413
- raise gr.Error("๐Ÿ’พ GPU out of memory. Try smaller dimensions or shorter duration.")
414
- except Exception as e:
415
- logger.error(f"Generation error: {e}")
416
- raise gr.Error(f"โŒ Generation failed: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
 
418
  progress(0.9, desc="๐Ÿ’พ Saving video...")
419
  filename = video_generator.generate_unique_filename(current_seed)
@@ -424,11 +467,19 @@ def generate_video(input_image, prompt, height, width,
424
 
425
  progress(1.0, desc="โœจ Complete!")
426
  logger.info(f"Video generated successfully: {num_frames} frames, {target_h}x{target_w}")
 
 
 
 
 
427
  return video_path, current_seed
428
 
 
 
 
429
  except Exception as e:
430
  logger.error(f"Unexpected error: {e}")
431
- raise
432
 
433
  finally:
434
  # ํ•ญ์ƒ ๋ฉ”๋ชจ๋ฆฌ ์ •๋ฆฌ ๋ฐ ๋ฝ ํ•ด์ œ
@@ -588,12 +639,34 @@ body {
588
  font-size: 0.9em;
589
  }
590
 
 
 
 
 
 
 
 
 
 
 
591
  .footer {
592
  text-align: center;
593
  margin-top: 30px;
594
  color: #666;
595
  font-size: 0.9em;
596
  }
 
 
 
 
 
 
 
 
 
 
 
 
597
  """
598
 
599
  # Gradio UI
@@ -622,6 +695,19 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
622
  </div>
623
  """)
624
 
 
 
 
 
 
 
 
 
 
 
 
 
 
625
  with gr.Row(elem_classes="main-content"):
626
  with gr.Column(scale=1):
627
  gr.Markdown("### ๐Ÿ“ธ Input Settings")
@@ -718,21 +804,24 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
718
 
719
  gr.HTML("""
720
  <div class="footer">
721
- <p>๐Ÿ’ก Tip: For best results, use clear images with good lighting</p>
722
  </div>
723
  """)
724
 
725
- # Examples
726
- gr.Examples(
727
- examples=[
728
- ["peng.png", "a penguin playfully dancing in the snow, Antarctica", 512, 512],
729
- ["forg.jpg", "the frog jumps around", 576, 320], # 16:9 aspect ratio within limits
730
- ],
731
- inputs=[input_image, prompt_input, height_slider, width_slider],
732
- outputs=[video_output, seed],
733
- fn=generate_video,
734
- cache_examples=False # ์บ์‹œ ๋น„ํ™œ์„ฑํ™”๋กœ ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ
735
- )
 
 
 
736
 
737
  # ๊ฐœ์„ ์‚ฌํ•ญ ์š”์•ฝ (์ž‘๊ฒŒ)
738
  gr.HTML("""
@@ -768,4 +857,9 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
768
  )
769
 
770
  if __name__ == "__main__":
771
- demo.launch() # ๋” ์—„๊ฒฉํ•œ ๋™์‹œ์„ฑ ์ œ์–ด
 
 
 
 
 
 
124
  logger.info("Loading model with memory optimizations...")
125
  clear_gpu_memory()
126
 
127
+ # ๋ชจ๋ธ ์ปดํฌ๋„ŒํŠธ ๋กœ๋“œ (๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ ) - autocast ์ˆ˜์ •
128
+ if torch.cuda.is_available():
129
+ with torch.amp.autocast('cuda', enabled=False): # ์ˆ˜์ •๋œ ๋ถ€๋ถ„
130
+ image_encoder = CLIPVisionModel.from_pretrained(
131
+ config.model_id,
132
+ subfolder="image_encoder",
133
+ torch_dtype=torch.float16,
134
+ low_cpu_mem_usage=True
135
+ )
136
+
137
+ vae = AutoencoderKLWan.from_pretrained(
138
+ config.model_id,
139
+ subfolder="vae",
140
+ torch_dtype=torch.float16,
141
+ low_cpu_mem_usage=True
142
+ )
143
+ else:
144
+ # CPU ํ™˜๊ฒฝ
145
  image_encoder = CLIPVisionModel.from_pretrained(
146
  config.model_id,
147
  subfolder="image_encoder",
148
+ torch_dtype=torch.float32,
149
  low_cpu_mem_usage=True
150
  )
151
 
152
  vae = AutoencoderKLWan.from_pretrained(
153
  config.model_id,
154
  subfolder="vae",
155
+ torch_dtype=torch.float32,
156
  low_cpu_mem_usage=True
157
  )
158
 
159
+ self._pipe = WanImageToVideoPipeline.from_pretrained(
160
+ config.model_id,
161
+ vae=vae,
162
+ image_encoder=image_encoder,
163
+ torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32,
164
+ low_cpu_mem_usage=True,
165
+ use_safetensors=True
166
+ )
167
 
168
  # ์Šค์ผ€์ค„๋Ÿฌ ์„ค์ •
169
  self._pipe.scheduler = UniPCMultistepScheduler.from_config(
 
171
  )
172
 
173
  # LoRA ๋กœ๋“œ
174
+ try:
175
+ causvid_path = hf_hub_download(
176
+ repo_id=config.lora_repo_id, filename=config.lora_filename
177
+ )
178
+ self._pipe.load_lora_weights(causvid_path, adapter_name="causvid_lora")
179
+ self._pipe.set_adapters(["causvid_lora"], adapter_weights=[0.95])
180
+ self._pipe.fuse_lora()
181
+ logger.info("LoRA weights loaded successfully")
182
+ except Exception as e:
183
+ logger.warning(f"Failed to load LoRA weights: {e}")
184
 
185
  # GPU ์ตœ์ ํ™” ์„ค์ •
186
  if hasattr(spaces, 'GPU'): # Zero GPU ํ™˜๊ฒฝ
187
  self._pipe.enable_model_cpu_offload()
188
  logger.info("CPU offload enabled for Zero GPU")
189
+ elif config.enable_model_cpu_offload and torch.cuda.is_available():
190
  self._pipe.enable_model_cpu_offload()
191
+ elif torch.cuda.is_available():
192
  self._pipe.to("cuda")
193
 
194
  if config.enable_vae_slicing:
 
304
  required_memory = (height * width * 3 * 8 * duration * self.config.fixed_fps) / (1024**3)
305
  if free_memory < required_memory * 2:
306
  clear_gpu_memory()
307
+ # ์žฌํ™•์ธ
308
+ free_memory = torch.cuda.get_device_properties(0).total_memory - torch.cuda.memory_allocated()
309
+ if free_memory < required_memory * 1.5:
310
+ return False, "โš ๏ธ Not enough GPU memory. Try smaller dimensions or shorter duration."
311
+ except Exception as e:
312
+ logger.warning(f"GPU memory check failed: {e}")
313
 
314
  return True, None
315
 
 
417
  progress(0.4, desc="๐ŸŽฌ Generating video frames...")
418
 
419
  # ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ ์ธ ์ƒ์„ฑ
420
+ if torch.cuda.is_available():
421
+ with torch.inference_mode(), torch.amp.autocast('cuda', enabled=True): # ์ˆ˜์ •๋œ ๋ถ€๋ถ„
422
+ try:
423
+ output_frames_list = pipe(
424
+ image=resized_image,
425
+ prompt=prompt,
426
+ negative_prompt=negative_prompt,
427
+ height=target_h,
428
+ width=target_w,
429
+ num_frames=num_frames,
430
+ guidance_scale=float(guidance_scale),
431
+ num_inference_steps=int(steps),
432
+ generator=torch.Generator(device="cuda").manual_seed(current_seed),
433
+ return_dict=True
434
+ ).frames[0]
435
+ except torch.cuda.OutOfMemoryError:
436
+ clear_gpu_memory()
437
+ raise gr.Error("๐Ÿ’พ GPU out of memory. Try smaller dimensions or shorter duration.")
438
+ except Exception as e:
439
+ logger.error(f"Generation error: {e}")
440
+ raise gr.Error(f"โŒ Generation failed: {str(e)}")
441
+ else:
442
+ # CPU ํ™˜๊ฒฝ
443
+ with torch.inference_mode():
444
+ try:
445
+ output_frames_list = pipe(
446
+ image=resized_image,
447
+ prompt=prompt,
448
+ negative_prompt=negative_prompt,
449
+ height=target_h,
450
+ width=target_w,
451
+ num_frames=num_frames,
452
+ guidance_scale=float(guidance_scale),
453
+ num_inference_steps=int(steps),
454
+ generator=torch.Generator().manual_seed(current_seed),
455
+ return_dict=True
456
+ ).frames[0]
457
+ except Exception as e:
458
+ logger.error(f"Generation error: {e}")
459
+ raise gr.Error(f"โŒ Generation failed: {str(e)}")
460
 
461
  progress(0.9, desc="๐Ÿ’พ Saving video...")
462
  filename = video_generator.generate_unique_filename(current_seed)
 
467
 
468
  progress(1.0, desc="โœจ Complete!")
469
  logger.info(f"Video generated successfully: {num_frames} frames, {target_h}x{target_w}")
470
+
471
+ # ์„ฑ๊ณต ์ •๋ณด ๋ฐ˜ํ™˜
472
+ info_text = f"โœ… Generated {num_frames} frames at {target_h}x{target_w} with seed {current_seed}"
473
+ gr.Info(info_text)
474
+
475
  return video_path, current_seed
476
 
477
+ except gr.Error:
478
+ # Gradio ์—๋Ÿฌ๋Š” ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ
479
+ raise
480
  except Exception as e:
481
  logger.error(f"Unexpected error: {e}")
482
+ raise gr.Error(f"โŒ Unexpected error: {str(e)}")
483
 
484
  finally:
485
  # ํ•ญ์ƒ ๋ฉ”๋ชจ๋ฆฌ ์ •๋ฆฌ ๋ฐ ๋ฝ ํ•ด์ œ
 
639
  font-size: 0.9em;
640
  }
641
 
642
+ .info-box {
643
+ background: rgba(52, 152, 219, 0.1);
644
+ border: 1px solid rgba(52, 152, 219, 0.3);
645
+ border-radius: 10px;
646
+ padding: 15px;
647
+ margin: 10px 0;
648
+ color: #2c5282;
649
+ font-size: 0.9em;
650
+ }
651
+
652
  .footer {
653
  text-align: center;
654
  margin-top: 30px;
655
  color: #666;
656
  font-size: 0.9em;
657
  }
658
+
659
+ /* ๋กœ๋”ฉ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ฐœ์„  */
660
+ .progress-bar {
661
+ background: linear-gradient(90deg, #667eea 0%, #764ba2 50%, #667eea 100%);
662
+ background-size: 200% 100%;
663
+ animation: loading 1.5s ease-in-out infinite;
664
+ }
665
+
666
+ @keyframes loading {
667
+ 0% { background-position: 0% 0%; }
668
+ 100% { background-position: 200% 0%; }
669
+ }
670
  """
671
 
672
  # Gradio UI
 
695
  </div>
696
  """)
697
 
698
+ # ์ƒˆ๋กœ์šด ์ •๋ณด ๋ฐ•์Šค ์ถ”๊ฐ€
699
+ gr.HTML("""
700
+ <div class="info-box">
701
+ <strong>๐ŸŽฏ Quick Start Guide:</strong>
702
+ <ol style="margin: 5px 0; padding-left: 20px;">
703
+ <li>Upload your image - AI will calculate optimal dimensions</li>
704
+ <li>Enter a creative prompt or use the default</li>
705
+ <li>Adjust duration (1.5s recommended for best results)</li>
706
+ <li>Click Generate and wait ~60 seconds</li>
707
+ </ol>
708
+ </div>
709
+ """)
710
+
711
  with gr.Row(elem_classes="main-content"):
712
  with gr.Column(scale=1):
713
  gr.Markdown("### ๐Ÿ“ธ Input Settings")
 
804
 
805
  gr.HTML("""
806
  <div class="footer">
807
+ <p>๐Ÿ’ก Tip: For best results, use clear images with good lighting and distinct subjects</p>
808
  </div>
809
  """)
810
 
811
+ # Examples - ํŒŒ์ผ๋ช… ํ™•์ธ ํ•„์š”
812
+ try:
813
+ gr.Examples(
814
+ examples=[
815
+ ["peng.png", "a penguin playfully dancing in the snow, Antarctica", 512, 512],
816
+ ["forg.jpg", "the frog jumps around", 576, 320], # 16:9 aspect ratio within limits
817
+ ],
818
+ inputs=[input_image, prompt_input, height_slider, width_slider],
819
+ outputs=[video_output, seed],
820
+ fn=generate_video,
821
+ cache_examples=False # ์บ์‹œ ๋น„ํ™œ์„ฑํ™”๋กœ ๋ฉ”๋ชจ๋ฆฌ ์ ˆ์•ฝ
822
+ )
823
+ except Exception as e:
824
+ logger.warning(f"Failed to load examples: {e}")
825
 
826
  # ๊ฐœ์„ ์‚ฌํ•ญ ์š”์•ฝ (์ž‘๊ฒŒ)
827
  gr.HTML("""
 
857
  )
858
 
859
  if __name__ == "__main__":
860
+ # ์ดˆ๊ธฐ ๋ฉ”๋ชจ๋ฆฌ ์ •๋ฆฌ
861
+ clear_gpu_memory()
862
+
863
+ # ์•ฑ ์‹คํ–‰
864
+ demo.queue(concurrency_count=1) # ๋™์‹œ ์‹คํ–‰ ์ œํ•œ
865
+ demo.launch()