Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -34,12 +34,12 @@ class VideoGenerationConfig:
|
|
| 34 |
lora_filename: str = "Wan21_CausVid_14B_T2V_lora_rank32.safetensors"
|
| 35 |
mod_value: int = 32
|
| 36 |
default_height: int = 512
|
| 37 |
-
default_width: int =
|
| 38 |
max_area: float = 480.0 * 832.0
|
| 39 |
slider_min_h: int = 128
|
| 40 |
-
slider_max_h: int =
|
| 41 |
slider_min_w: int = 128
|
| 42 |
-
slider_max_w: int =
|
| 43 |
fixed_fps: int = 24
|
| 44 |
min_frames: int = 8
|
| 45 |
max_frames: int = 81
|
|
@@ -163,7 +163,10 @@ class ModelManager:
|
|
| 163 |
self._pipe.fuse_lora()
|
| 164 |
|
| 165 |
# GPU μ΅μ ν μ€μ
|
| 166 |
-
if
|
|
|
|
|
|
|
|
|
|
| 167 |
self._pipe.enable_model_cpu_offload()
|
| 168 |
else:
|
| 169 |
self._pipe.to("cuda")
|
|
@@ -216,16 +219,29 @@ class VideoGenerator:
|
|
| 216 |
return self.config.default_height, self.config.default_width
|
| 217 |
|
| 218 |
aspect_ratio = orig_h / orig_w
|
| 219 |
-
|
| 220 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
|
| 222 |
calc_h = max(self.config.mod_value, (calc_h // self.config.mod_value) * self.config.mod_value)
|
| 223 |
calc_w = max(self.config.mod_value, (calc_w // self.config.mod_value) * self.config.mod_value)
|
| 224 |
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
|
| 230 |
return new_h, new_w
|
| 231 |
|
|
@@ -254,8 +270,12 @@ class VideoGenerator:
|
|
| 254 |
if hasattr(spaces, 'GPU'): # Spaces νκ²½ 체ν¬
|
| 255 |
if duration > 2.5: # Zero GPUμμλ 2.5μ΄λ‘ μ ν
|
| 256 |
return False, "β±οΈ In Zero GPU environment, duration is limited to 2.5s for stability"
|
| 257 |
-
|
| 258 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
|
| 260 |
# GPU λ©λͺ¨λ¦¬ 체ν¬
|
| 261 |
if torch.cuda.is_available():
|
|
@@ -312,11 +332,11 @@ def get_duration(input_image, prompt, height, width, negative_prompt,
|
|
| 312 |
elif duration_seconds > 1.5:
|
| 313 |
base_duration += 10
|
| 314 |
|
| 315 |
-
# ν΄μλλ³ μΆκ° μκ°
|
| 316 |
pixels = height * width
|
| 317 |
-
if pixels > 400000: #
|
| 318 |
base_duration += 20
|
| 319 |
-
elif pixels > 250000: #
|
| 320 |
base_duration += 10
|
| 321 |
|
| 322 |
# Zero GPU νκ²½μμλ μ΅λ 90μ΄λ‘ μ ν
|
|
@@ -339,7 +359,7 @@ def generate_video(input_image, prompt, height, width,
|
|
| 339 |
|
| 340 |
# Zero GPU νκ²½μμ μΆκ° κ²μ¦
|
| 341 |
if hasattr(spaces, 'GPU'):
|
| 342 |
-
logger.info(f"Zero GPU environment detected. Duration: {duration_seconds}s, Resolution: {height}x{width}")
|
| 343 |
|
| 344 |
# μ
λ ₯ κ²μ¦
|
| 345 |
is_valid, error_msg = video_generator.validate_inputs(
|
|
@@ -584,7 +604,7 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
|
|
| 584 |
<div class="header">
|
| 585 |
<h1>π¬ AI Video Magic Studio</h1>
|
| 586 |
<p>Transform your images into captivating videos with Wan 2.1 + CausVid LoRA</p>
|
| 587 |
-
<div class="gpu-status">π₯οΈ GPU Optimized</div>
|
| 588 |
</div>
|
| 589 |
""")
|
| 590 |
|
|
@@ -594,7 +614,8 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
|
|
| 594 |
<strong>π‘ Zero GPU Performance Tips:</strong>
|
| 595 |
<ul style="margin: 5px 0; padding-left: 20px;">
|
| 596 |
<li>Maximum duration: 2.5 seconds (limited by Zero GPU)</li>
|
| 597 |
-
<li>
|
|
|
|
| 598 |
<li>Use 4-6 steps for optimal speed/quality balance</li>
|
| 599 |
<li>Wait between generations to avoid queue errors</li>
|
| 600 |
</ul>
|
|
@@ -654,14 +675,14 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
|
|
| 654 |
maximum=config.slider_max_h,
|
| 655 |
step=config.mod_value,
|
| 656 |
value=config.default_height,
|
| 657 |
-
label="π Height (
|
| 658 |
)
|
| 659 |
width_slider = gr.Slider(
|
| 660 |
minimum=config.slider_min_w,
|
| 661 |
maximum=config.slider_max_w,
|
| 662 |
step=config.mod_value,
|
| 663 |
value=config.default_width,
|
| 664 |
-
label="π Width (
|
| 665 |
)
|
| 666 |
|
| 667 |
steps_slider = gr.Slider(
|
|
@@ -705,7 +726,7 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
|
|
| 705 |
gr.Examples(
|
| 706 |
examples=[
|
| 707 |
["peng.png", "a penguin playfully dancing in the snow, Antarctica", 512, 512],
|
| 708 |
-
["forg.jpg", "the frog jumps around",
|
| 709 |
],
|
| 710 |
inputs=[input_image, prompt_input, height_slider, width_slider],
|
| 711 |
outputs=[video_output, seed],
|
|
@@ -747,4 +768,4 @@ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
|
|
| 747 |
)
|
| 748 |
|
| 749 |
if __name__ == "__main__":
|
| 750 |
-
demo.queue(max_size=1).launch() #
|
|
|
|
| 34 |
lora_filename: str = "Wan21_CausVid_14B_T2V_lora_rank32.safetensors"
|
| 35 |
mod_value: int = 32
|
| 36 |
default_height: int = 512
|
| 37 |
+
default_width: int = 512 # Zero GPU νκ²½μ μν΄ κΈ°λ³Έκ° μμ
|
| 38 |
max_area: float = 480.0 * 832.0
|
| 39 |
slider_min_h: int = 128
|
| 40 |
+
slider_max_h: int = 832 # Zero GPU νκ²½μ μν΄ μμ
|
| 41 |
slider_min_w: int = 128
|
| 42 |
+
slider_max_w: int = 832 # Zero GPU νκ²½μ μν΄ μμ
|
| 43 |
fixed_fps: int = 24
|
| 44 |
min_frames: int = 8
|
| 45 |
max_frames: int = 81
|
|
|
|
| 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")
|
|
|
|
| 219 |
return self.config.default_height, self.config.default_width
|
| 220 |
|
| 221 |
aspect_ratio = orig_h / orig_w
|
| 222 |
+
|
| 223 |
+
# Zero GPU νκ²½μμλ λ μμ max_area μ¬μ©
|
| 224 |
+
if hasattr(spaces, 'GPU'):
|
| 225 |
+
max_area = 640.0 * 640.0 # 409,600 pixels
|
| 226 |
+
else:
|
| 227 |
+
max_area = self.config.max_area
|
| 228 |
+
|
| 229 |
+
calc_h = round(np.sqrt(max_area * aspect_ratio))
|
| 230 |
+
calc_w = round(np.sqrt(max_area / aspect_ratio))
|
| 231 |
|
| 232 |
calc_h = max(self.config.mod_value, (calc_h // self.config.mod_value) * self.config.mod_value)
|
| 233 |
calc_w = max(self.config.mod_value, (calc_w // self.config.mod_value) * self.config.mod_value)
|
| 234 |
|
| 235 |
+
# Zero GPU νκ²½μμ μΆκ° μ ν
|
| 236 |
+
if hasattr(spaces, 'GPU'):
|
| 237 |
+
max_dim = 832
|
| 238 |
+
new_h = int(np.clip(calc_h, self.config.slider_min_h, min(max_dim, self.config.slider_max_h)))
|
| 239 |
+
new_w = int(np.clip(calc_w, self.config.slider_min_w, min(max_dim, self.config.slider_max_w)))
|
| 240 |
+
else:
|
| 241 |
+
new_h = int(np.clip(calc_h, self.config.slider_min_h,
|
| 242 |
+
(self.config.slider_max_h // self.config.mod_value) * self.config.mod_value))
|
| 243 |
+
new_w = int(np.clip(calc_w, self.config.slider_min_w,
|
| 244 |
+
(self.config.slider_max_w // self.config.mod_value) * self.config.mod_value))
|
| 245 |
|
| 246 |
return new_h, new_w
|
| 247 |
|
|
|
|
| 270 |
if hasattr(spaces, 'GPU'): # Spaces νκ²½ 체ν¬
|
| 271 |
if duration > 2.5: # Zero GPUμμλ 2.5μ΄λ‘ μ ν
|
| 272 |
return False, "β±οΈ In Zero GPU environment, duration is limited to 2.5s for stability"
|
| 273 |
+
# ν½μ
μ κΈ°λ° μ ν (640x640 = 409,600 ν½μ
)
|
| 274 |
+
max_pixels = 640 * 640
|
| 275 |
+
if height * width > max_pixels:
|
| 276 |
+
return False, f"π In Zero GPU environment, total pixels limited to {max_pixels:,} (e.g., 640Γ640, 512Γ832)"
|
| 277 |
+
if height > 832 or width > 832: # ν λ³μ μ΅λ κΈΈμ΄
|
| 278 |
+
return False, "π In Zero GPU environment, maximum dimension is 832 pixels"
|
| 279 |
|
| 280 |
# GPU λ©λͺ¨λ¦¬ 체ν¬
|
| 281 |
if torch.cuda.is_available():
|
|
|
|
| 332 |
elif duration_seconds > 1.5:
|
| 333 |
base_duration += 10
|
| 334 |
|
| 335 |
+
# ν΄μλλ³ μΆκ° μκ° (ν½μ
μ κΈ°λ°)
|
| 336 |
pixels = height * width
|
| 337 |
+
if pixels > 400000: # 640x640 κ·Όμ²
|
| 338 |
base_duration += 20
|
| 339 |
+
elif pixels > 250000: # 512x512 κ·Όμ²
|
| 340 |
base_duration += 10
|
| 341 |
|
| 342 |
# Zero GPU νκ²½μμλ μ΅λ 90μ΄λ‘ μ ν
|
|
|
|
| 359 |
|
| 360 |
# Zero GPU νκ²½μμ μΆκ° κ²μ¦
|
| 361 |
if hasattr(spaces, 'GPU'):
|
| 362 |
+
logger.info(f"Zero GPU environment detected. Duration: {duration_seconds}s, Resolution: {height}x{width}, Pixels: {height*width:,}")
|
| 363 |
|
| 364 |
# μ
λ ₯ κ²μ¦
|
| 365 |
is_valid, error_msg = video_generator.validate_inputs(
|
|
|
|
| 604 |
<div class="header">
|
| 605 |
<h1>π¬ AI Video Magic Studio</h1>
|
| 606 |
<p>Transform your images into captivating videos with Wan 2.1 + CausVid LoRA</p>
|
| 607 |
+
<div class="gpu-status">π₯οΈ Zero GPU Optimized</div>
|
| 608 |
</div>
|
| 609 |
""")
|
| 610 |
|
|
|
|
| 614 |
<strong>π‘ Zero GPU Performance Tips:</strong>
|
| 615 |
<ul style="margin: 5px 0; padding-left: 20px;">
|
| 616 |
<li>Maximum duration: 2.5 seconds (limited by Zero GPU)</li>
|
| 617 |
+
<li>Maximum total pixels: 409,600 (e.g., 640Γ640, 512Γ832, 448Γ896)</li>
|
| 618 |
+
<li>Maximum single dimension: 832 pixels</li>
|
| 619 |
<li>Use 4-6 steps for optimal speed/quality balance</li>
|
| 620 |
<li>Wait between generations to avoid queue errors</li>
|
| 621 |
</ul>
|
|
|
|
| 675 |
maximum=config.slider_max_h,
|
| 676 |
step=config.mod_value,
|
| 677 |
value=config.default_height,
|
| 678 |
+
label="π Height (max 832px in Zero GPU)"
|
| 679 |
)
|
| 680 |
width_slider = gr.Slider(
|
| 681 |
minimum=config.slider_min_w,
|
| 682 |
maximum=config.slider_max_w,
|
| 683 |
step=config.mod_value,
|
| 684 |
value=config.default_width,
|
| 685 |
+
label="π Width (max 832px in Zero GPU)"
|
| 686 |
)
|
| 687 |
|
| 688 |
steps_slider = gr.Slider(
|
|
|
|
| 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],
|
|
|
|
| 768 |
)
|
| 769 |
|
| 770 |
if __name__ == "__main__":
|
| 771 |
+
demo.queue(max_size=1, concurrency_count=1).launch() # λ μ격ν λμμ± μ μ΄
|