Spaces:
Running on Zero
Running on Zero
bann commited on
Commit ·
2d2d6b8
1
Parent(s): 8baf391
feat: upgrade default model to Wan 2.2 MoE suite and configure Civitai API key
Browse files
README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
title: Wan 2.
|
| 3 |
emoji: 🎬
|
| 4 |
colorFrom: indigo
|
| 5 |
colorTo: purple
|
|
@@ -8,17 +8,18 @@ sdk_version: 5.20.0
|
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
license: apache-2.0
|
| 11 |
-
short_description: Wan 2.
|
| 12 |
suggested_hardware: zero-a10g
|
| 13 |
---
|
| 14 |
|
| 15 |
-
# Wan 2.
|
| 16 |
|
| 17 |
-
A high-performance AI video generation studio running **Wan 2.
|
| 18 |
|
| 19 |
### Features:
|
| 20 |
-
-
|
|
|
|
| 21 |
- ⚡ **ZeroGPU Acceleration**: Runs with dynamic GPU scheduling on A10G / H100 hardware.
|
| 22 |
-
- 🧩 **Multi-LoRA Engine**: Load
|
| 23 |
- 📐 **300-Hours Civitai Optimization**: Strict multiple-of-16 aspect ratios (832x480, 480x832, 1280x720, etc.) for clean motion.
|
| 24 |
- 📖 **Built-in Prompt & Anatomical Motion Guide**: Designed with the official structured prompt standards.
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Wan 2.2 Studio
|
| 3 |
emoji: 🎬
|
| 4 |
colorFrom: indigo
|
| 5 |
colorTo: purple
|
|
|
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
license: apache-2.0
|
| 11 |
+
short_description: Wan 2.2 Video Studio with Multi-LoRA and I2V/T2V
|
| 12 |
suggested_hardware: zero-a10g
|
| 13 |
---
|
| 14 |
|
| 15 |
+
# Wan 2.2 Video Studio (ZeroGPU + Multi-LoRA + Base NSFW)
|
| 16 |
|
| 17 |
+
A high-performance AI video generation studio running **Wan 2.2 (MoE)** on **ZeroGPU**.
|
| 18 |
|
| 19 |
### Features:
|
| 20 |
+
- 🚀 **Wan 2.2 MoE Architecture**: Native Diffusers integration (`Wan2.2-I2V-A14B`, `Wan2.2-TI2V-5B`, `Wan2.2-T2V-A14B`).
|
| 21 |
+
- 🔞 **Base NSFW Adapter System**: Pre-loaded with `WAN General NSFW Model (Civitai 1307155)` to unlock full anatomical generation.
|
| 22 |
- ⚡ **ZeroGPU Acceleration**: Runs with dynamic GPU scheduling on A10G / H100 hardware.
|
| 23 |
+
- 🧩 **Multi-LoRA Engine**: Load custom action and style LoRAs from Civitai, Hugging Face, or local files with Trigger Words.
|
| 24 |
- 📐 **300-Hours Civitai Optimization**: Strict multiple-of-16 aspect ratios (832x480, 480x832, 1280x720, etc.) for clean motion.
|
| 25 |
- 📖 **Built-in Prompt & Anatomical Motion Guide**: Designed with the official structured prompt standards.
|
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
"""Wan 2.
|
| 2 |
|
| 3 |
from __future__ import annotations
|
| 4 |
|
|
@@ -52,7 +52,8 @@ from PIL import Image, ImageOps
|
|
| 52 |
from diffusers.utils import export_to_video
|
| 53 |
from safetensors import safe_open
|
| 54 |
|
| 55 |
-
|
|
|
|
| 56 |
GPU_SIZE = os.environ.get("WAN_GPU_SIZE", "xlarge")
|
| 57 |
MAX_GPU_DURATION = int(os.environ.get("WAN_MAX_GPU_DURATION", "300"))
|
| 58 |
OUTPUT_DIR = os.path.join(tempfile.gettempdir(), "wan-outputs")
|
|
@@ -85,7 +86,7 @@ NSFW_BASE_ADAPTERS = {
|
|
| 85 |
}
|
| 86 |
|
| 87 |
# =========================================================================
|
| 88 |
-
# Preset Catalog for Wan 2.
|
| 89 |
# =========================================================================
|
| 90 |
LORA_PRESETS = {
|
| 91 |
"None / Desativado": {
|
|
@@ -99,16 +100,16 @@ LORA_PRESETS = {
|
|
| 99 |
"source": "https://civitai.com/models/1307155",
|
| 100 |
"trigger_words": "nsfwsks, uncensored, naked, explicit",
|
| 101 |
"default_strength": 1.0,
|
| 102 |
-
"description": "LoRA Geral NSFW para Wan 2.
|
| 103 |
},
|
| 104 |
-
"HMNSFW AIO V2 / hmmotion (Wan 2.
|
| 105 |
"type": "civitai",
|
| 106 |
"source": "https://civitai.com/api/download/models/3206518",
|
| 107 |
"trigger_words": "hmmotion, missionary, side, fast, third-person side view, medium shot.",
|
| 108 |
"default_strength": 0.5,
|
| 109 |
"description": "LoRA All-in-One de anatomia e movimento realista (Civitai 2834417 / 3206518). Use força <= 0.5 com prompts descritivos.",
|
| 110 |
},
|
| 111 |
-
"Icy Twerk Pro Max (Wan 2.
|
| 112 |
"type": "civitai",
|
| 113 |
"source": "https://civitai.com/api/download/models/3201584",
|
| 114 |
"trigger_words": "icytw3rk, twerking, booty shake, rhythmic hip movement, dynamic motion, bouncing buttocks, high quality",
|
|
@@ -265,7 +266,7 @@ def _validate_public_lora_url(url: str) -> str:
|
|
| 265 |
def _download_lora_url(url: str, civitai_token: str = "") -> tuple[str, str]:
|
| 266 |
import requests
|
| 267 |
|
| 268 |
-
token = (civitai_token or os.environ.get("CIVITAI_API_KEY", "") or os.environ.get("CIVITAI_TOKEN", "")).strip()
|
| 269 |
|
| 270 |
if "civitai." in url and token and "token=" not in url:
|
| 271 |
sep = "&" if "?" in url else "?"
|
|
@@ -310,8 +311,7 @@ def _download_lora_url(url: str, civitai_token: str = "") -> tuple[str, str]:
|
|
| 310 |
if response.status_code in (401, 403):
|
| 311 |
raise gr.Error(
|
| 312 |
"🔒 O Civitai bloqueou o download deste modelo (401 Unauthorized / NSFW). "
|
| 313 |
-
"
|
| 314 |
-
"e cole no campo 'Civitai API Key' no painel do Space."
|
| 315 |
)
|
| 316 |
response.raise_for_status()
|
| 317 |
total = 0
|
|
@@ -334,7 +334,7 @@ def _download_lora_url(url: str, civitai_token: str = "") -> tuple[str, str]:
|
|
| 334 |
if "response" in locals() and response.status_code in (401, 403):
|
| 335 |
raise gr.Error(
|
| 336 |
"🔒 O Civitai bloqueou o download deste modelo (401 Unauthorized / NSFW). "
|
| 337 |
-
"
|
| 338 |
) from err
|
| 339 |
raise
|
| 340 |
raise ValueError("Too many redirects downloading LoRA.")
|
|
@@ -343,7 +343,7 @@ def _download_lora_url(url: str, civitai_token: str = "") -> tuple[str, str]:
|
|
| 343 |
def resolve_single_lora(
|
| 344 |
preset_type: str, custom_url: str, hf_repo: str, hf_file: str, local_file: str, strength: float, civitai_token: str = ""
|
| 345 |
) -> tuple[str | None, str, float]:
|
| 346 |
-
"""Resolves one LoRA file path, label and scale for Wan 2.
|
| 347 |
if float(strength) == 0.0 or preset_type in ("None / Desativado", "None", ""):
|
| 348 |
return None, "None", 0.0
|
| 349 |
|
|
@@ -410,19 +410,31 @@ def load_pipeline(model_repo: str = DEFAULT_MODEL_REPO):
|
|
| 410 |
|
| 411 |
started = time.time()
|
| 412 |
try:
|
| 413 |
-
from diffusers import WanImageToVideoPipeline, WanPipeline
|
| 414 |
|
| 415 |
print(f"[wan] loading pipeline from {model_repo} ...", flush=True)
|
| 416 |
if "I2V" in model_repo or "i2v" in model_repo:
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 421 |
else:
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
|
| 427 |
PIPE = pipe
|
| 428 |
CURRENT_MODEL_REPO = model_repo
|
|
@@ -509,7 +521,7 @@ def _generate_video_gpu(
|
|
| 509 |
|
| 510 |
try:
|
| 511 |
with torch.inference_mode():
|
| 512 |
-
if image_input is not None and ("I2V" in model_repo or "i2v" in model_repo):
|
| 513 |
output = pipe(
|
| 514 |
image=image_input,
|
| 515 |
prompt=prompt,
|
|
@@ -585,6 +597,7 @@ def generate_video(
|
|
| 585 |
if input_image is not None:
|
| 586 |
processed_image = _fit_keyframe(input_image, width, height)
|
| 587 |
|
|
|
|
| 588 |
lora_configs = []
|
| 589 |
active_labels = []
|
| 590 |
|
|
@@ -594,13 +607,13 @@ def generate_video(
|
|
| 594 |
if base_spec.get("source"):
|
| 595 |
b_url = normalize_civitai_url(base_spec["source"])
|
| 596 |
if b_url:
|
| 597 |
-
b_path, b_label = _download_lora_url(b_url,
|
| 598 |
lora_configs.append((b_path, float(nsfw_base_strength)))
|
| 599 |
active_labels.append(f"🔞 NSFW Base: {nsfw_base_choice.split('(')[0].strip()} (@ {nsfw_base_strength:g})")
|
| 600 |
|
| 601 |
# 2. Slot 1 LoRA
|
| 602 |
l1_path, l1_label, l1_scale = resolve_single_lora(
|
| 603 |
-
lora1_preset, lora1_custom_url, lora1_hf_repo, lora1_hf_file, lora1_local_file, lora1_strength,
|
| 604 |
)
|
| 605 |
if l1_path and l1_scale > 0:
|
| 606 |
lora_configs.append((l1_path, l1_scale))
|
|
@@ -608,7 +621,7 @@ def generate_video(
|
|
| 608 |
|
| 609 |
# 3. Slot 2 LoRA
|
| 610 |
l2_path, l2_label, l2_scale = resolve_single_lora(
|
| 611 |
-
lora2_preset, lora2_custom_url, lora2_hf_repo, lora2_hf_file, lora2_local_file, lora2_strength,
|
| 612 |
)
|
| 613 |
if l2_path and l2_scale > 0:
|
| 614 |
lora_configs.append((l2_path, l2_scale))
|
|
@@ -728,17 +741,17 @@ all_preset_choices = (
|
|
| 728 |
+ (["Local File (loras/ folder)"] if get_local_loras() else [])
|
| 729 |
)
|
| 730 |
|
| 731 |
-
with gr.Blocks(css=custom_css, title="Wan 2.
|
| 732 |
gr.HTML(
|
| 733 |
"""
|
| 734 |
<div class="header-card">
|
| 735 |
<div style="margin-bottom: 12px;">
|
| 736 |
<span class="badge badge-zerogpu">⚡ ZeroGPU</span>
|
| 737 |
-
<span class="badge badge-model">🎬 Wan 2.
|
| 738 |
<span class="badge badge-multilora">🧩 Base NSFW + Multi-LoRA Engine</span>
|
| 739 |
</div>
|
| 740 |
-
<h1>Wan 2.
|
| 741 |
-
<p>Image-to-Video (I2V) & Text-to-Video (T2V) com Adaptador NSFW Base
|
| 742 |
</div>
|
| 743 |
"""
|
| 744 |
)
|
|
@@ -759,7 +772,7 @@ with gr.Blocks(css=custom_css, title="Wan 2.1 / 2.2 Video Studio") as app:
|
|
| 759 |
value="deformed, bad anatomy, extra limbs, blurry, low resolution, bad quality, distortion, censorship",
|
| 760 |
)
|
| 761 |
|
| 762 |
-
with gr.Accordion("📖 Guia & Modelos de Prompt HMNSFW / hmmotion (Wan 2.
|
| 763 |
gr.Markdown(
|
| 764 |
"""
|
| 765 |
**Estrutura Recomendada pelo Guia de 300 Horas / Autor do LoRA (`hmmotion`)**:
|
|
@@ -800,7 +813,7 @@ with gr.Blocks(css=custom_css, title="Wan 2.1 / 2.2 Video Studio") as app:
|
|
| 800 |
lora1_preset = gr.Dropdown(
|
| 801 |
label="LoRA Slot 1 Preset / Fonte",
|
| 802 |
choices=all_preset_choices,
|
| 803 |
-
value="HMNSFW AIO V2 / hmmotion (Wan 2.
|
| 804 |
)
|
| 805 |
with gr.Group(visible=False) as lora1_custom_url_grp:
|
| 806 |
lora1_custom_url = gr.Textbox(
|
|
@@ -816,7 +829,7 @@ with gr.Blocks(css=custom_css, title="Wan 2.1 / 2.2 Video Studio") as app:
|
|
| 816 |
|
| 817 |
lora1_trigger_display = gr.Textbox(
|
| 818 |
label="Trigger Words",
|
| 819 |
-
value=LORA_PRESETS.get("HMNSFW AIO V2 / hmmotion (Wan 2.
|
| 820 |
interactive=False,
|
| 821 |
)
|
| 822 |
add_lora1_triggers_btn = gr.Button("📋 Inserir Trigger Words no Prompt", elem_classes=["trigger-btn"])
|
|
@@ -867,12 +880,13 @@ with gr.Blocks(css=custom_css, title="Wan 2.1 / 2.2 Video Studio") as app:
|
|
| 867 |
model_choice = gr.Dropdown(
|
| 868 |
label="Modelo Base Wan",
|
| 869 |
choices=[
|
| 870 |
-
("Wan 2.
|
| 871 |
-
("Wan 2.
|
| 872 |
-
("Wan 2.
|
| 873 |
-
("Wan 2.
|
|
|
|
| 874 |
],
|
| 875 |
-
value="Wan-AI/Wan2.
|
| 876 |
)
|
| 877 |
canvas = gr.Dropdown(
|
| 878 |
label="Proporção & Resolução (Múltiplos de 16)",
|
|
@@ -917,12 +931,13 @@ with gr.Blocks(css=custom_css, title="Wan 2.1 / 2.2 Video Studio") as app:
|
|
| 917 |
randomize_seed = gr.Checkbox(label="🎲 Randomizar Seed", value=True)
|
| 918 |
|
| 919 |
civitai_api_key = gr.Textbox(
|
| 920 |
-
label="🔑 Civitai API Key
|
| 921 |
-
|
|
|
|
| 922 |
type="password",
|
| 923 |
)
|
| 924 |
|
| 925 |
-
generate_btn = gr.Button("🚀 Gerar Vídeo Wan 2.
|
| 926 |
|
| 927 |
with gr.Column(scale=6):
|
| 928 |
output_video = gr.Video(label="Vídeo Gerado", autoplay=True, loop=True)
|
|
|
|
| 1 |
+
"""Wan 2.2 Space with ZeroGPU, Multi-LoRA (Civitai + HF), Presets, Trigger Words, and 300-Hours Optimizations."""
|
| 2 |
|
| 3 |
from __future__ import annotations
|
| 4 |
|
|
|
|
| 52 |
from diffusers.utils import export_to_video
|
| 53 |
from safetensors import safe_open
|
| 54 |
|
| 55 |
+
DEFAULT_CIVITAI_KEY = "50a9e1bd474c03b856070a7272d8015c"
|
| 56 |
+
DEFAULT_MODEL_REPO = os.environ.get("WAN_MODEL_REPO", "Wan-AI/Wan2.2-I2V-A14B-480P-Diffusers")
|
| 57 |
GPU_SIZE = os.environ.get("WAN_GPU_SIZE", "xlarge")
|
| 58 |
MAX_GPU_DURATION = int(os.environ.get("WAN_MAX_GPU_DURATION", "300"))
|
| 59 |
OUTPUT_DIR = os.path.join(tempfile.gettempdir(), "wan-outputs")
|
|
|
|
| 86 |
}
|
| 87 |
|
| 88 |
# =========================================================================
|
| 89 |
+
# Preset Catalog for Wan 2.2 LoRAs (Actions, Motions & Styles)
|
| 90 |
# =========================================================================
|
| 91 |
LORA_PRESETS = {
|
| 92 |
"None / Desativado": {
|
|
|
|
| 100 |
"source": "https://civitai.com/models/1307155",
|
| 101 |
"trigger_words": "nsfwsks, uncensored, naked, explicit",
|
| 102 |
"default_strength": 1.0,
|
| 103 |
+
"description": "LoRA Geral NSFW para Wan 2.2 (Civitai 1307155).",
|
| 104 |
},
|
| 105 |
+
"HMNSFW AIO V2 / hmmotion (Wan 2.2)": {
|
| 106 |
"type": "civitai",
|
| 107 |
"source": "https://civitai.com/api/download/models/3206518",
|
| 108 |
"trigger_words": "hmmotion, missionary, side, fast, third-person side view, medium shot.",
|
| 109 |
"default_strength": 0.5,
|
| 110 |
"description": "LoRA All-in-One de anatomia e movimento realista (Civitai 2834417 / 3206518). Use força <= 0.5 com prompts descritivos.",
|
| 111 |
},
|
| 112 |
+
"Icy Twerk Pro Max (Wan 2.2)": {
|
| 113 |
"type": "civitai",
|
| 114 |
"source": "https://civitai.com/api/download/models/3201584",
|
| 115 |
"trigger_words": "icytw3rk, twerking, booty shake, rhythmic hip movement, dynamic motion, bouncing buttocks, high quality",
|
|
|
|
| 266 |
def _download_lora_url(url: str, civitai_token: str = "") -> tuple[str, str]:
|
| 267 |
import requests
|
| 268 |
|
| 269 |
+
token = (civitai_token or os.environ.get("CIVITAI_API_KEY", "") or os.environ.get("CIVITAI_TOKEN", "") or DEFAULT_CIVITAI_KEY).strip()
|
| 270 |
|
| 271 |
if "civitai." in url and token and "token=" not in url:
|
| 272 |
sep = "&" if "?" in url else "?"
|
|
|
|
| 311 |
if response.status_code in (401, 403):
|
| 312 |
raise gr.Error(
|
| 313 |
"🔒 O Civitai bloqueou o download deste modelo (401 Unauthorized / NSFW). "
|
| 314 |
+
"Verifique sua Civitai API Key nas configurações."
|
|
|
|
| 315 |
)
|
| 316 |
response.raise_for_status()
|
| 317 |
total = 0
|
|
|
|
| 334 |
if "response" in locals() and response.status_code in (401, 403):
|
| 335 |
raise gr.Error(
|
| 336 |
"🔒 O Civitai bloqueou o download deste modelo (401 Unauthorized / NSFW). "
|
| 337 |
+
"Verifique sua Civitai API Key nas configurações."
|
| 338 |
) from err
|
| 339 |
raise
|
| 340 |
raise ValueError("Too many redirects downloading LoRA.")
|
|
|
|
| 343 |
def resolve_single_lora(
|
| 344 |
preset_type: str, custom_url: str, hf_repo: str, hf_file: str, local_file: str, strength: float, civitai_token: str = ""
|
| 345 |
) -> tuple[str | None, str, float]:
|
| 346 |
+
"""Resolves one LoRA file path, label and scale for Wan 2.2."""
|
| 347 |
if float(strength) == 0.0 or preset_type in ("None / Desativado", "None", ""):
|
| 348 |
return None, "None", 0.0
|
| 349 |
|
|
|
|
| 410 |
|
| 411 |
started = time.time()
|
| 412 |
try:
|
| 413 |
+
from diffusers import WanImageToVideoPipeline, WanPipeline, AutoPipelineForImage2Video, AutoPipelineForText2Video
|
| 414 |
|
| 415 |
print(f"[wan] loading pipeline from {model_repo} ...", flush=True)
|
| 416 |
if "I2V" in model_repo or "i2v" in model_repo:
|
| 417 |
+
try:
|
| 418 |
+
pipe = WanImageToVideoPipeline.from_pretrained(
|
| 419 |
+
model_repo,
|
| 420 |
+
torch_dtype=torch.bfloat16,
|
| 421 |
+
)
|
| 422 |
+
except Exception:
|
| 423 |
+
pipe = AutoPipelineForImage2Video.from_pretrained(
|
| 424 |
+
model_repo,
|
| 425 |
+
torch_dtype=torch.bfloat16,
|
| 426 |
+
)
|
| 427 |
else:
|
| 428 |
+
try:
|
| 429 |
+
pipe = WanPipeline.from_pretrained(
|
| 430 |
+
model_repo,
|
| 431 |
+
torch_dtype=torch.bfloat16,
|
| 432 |
+
)
|
| 433 |
+
except Exception:
|
| 434 |
+
pipe = AutoPipelineForText2Video.from_pretrained(
|
| 435 |
+
model_repo,
|
| 436 |
+
torch_dtype=torch.bfloat16,
|
| 437 |
+
)
|
| 438 |
|
| 439 |
PIPE = pipe
|
| 440 |
CURRENT_MODEL_REPO = model_repo
|
|
|
|
| 521 |
|
| 522 |
try:
|
| 523 |
with torch.inference_mode():
|
| 524 |
+
if image_input is not None and ("I2V" in model_repo or "i2v" in model_repo or "TI2V" in model_repo):
|
| 525 |
output = pipe(
|
| 526 |
image=image_input,
|
| 527 |
prompt=prompt,
|
|
|
|
| 597 |
if input_image is not None:
|
| 598 |
processed_image = _fit_keyframe(input_image, width, height)
|
| 599 |
|
| 600 |
+
token_to_use = (civitai_api_key or DEFAULT_CIVITAI_KEY).strip()
|
| 601 |
lora_configs = []
|
| 602 |
active_labels = []
|
| 603 |
|
|
|
|
| 607 |
if base_spec.get("source"):
|
| 608 |
b_url = normalize_civitai_url(base_spec["source"])
|
| 609 |
if b_url:
|
| 610 |
+
b_path, b_label = _download_lora_url(b_url, token_to_use)
|
| 611 |
lora_configs.append((b_path, float(nsfw_base_strength)))
|
| 612 |
active_labels.append(f"🔞 NSFW Base: {nsfw_base_choice.split('(')[0].strip()} (@ {nsfw_base_strength:g})")
|
| 613 |
|
| 614 |
# 2. Slot 1 LoRA
|
| 615 |
l1_path, l1_label, l1_scale = resolve_single_lora(
|
| 616 |
+
lora1_preset, lora1_custom_url, lora1_hf_repo, lora1_hf_file, lora1_local_file, lora1_strength, token_to_use
|
| 617 |
)
|
| 618 |
if l1_path and l1_scale > 0:
|
| 619 |
lora_configs.append((l1_path, l1_scale))
|
|
|
|
| 621 |
|
| 622 |
# 3. Slot 2 LoRA
|
| 623 |
l2_path, l2_label, l2_scale = resolve_single_lora(
|
| 624 |
+
lora2_preset, lora2_custom_url, lora2_hf_repo, lora2_hf_file, lora2_local_file, lora2_strength, token_to_use
|
| 625 |
)
|
| 626 |
if l2_path and l2_scale > 0:
|
| 627 |
lora_configs.append((l2_path, l2_scale))
|
|
|
|
| 741 |
+ (["Local File (loras/ folder)"] if get_local_loras() else [])
|
| 742 |
)
|
| 743 |
|
| 744 |
+
with gr.Blocks(css=custom_css, title="Wan 2.2 Video Studio") as app:
|
| 745 |
gr.HTML(
|
| 746 |
"""
|
| 747 |
<div class="header-card">
|
| 748 |
<div style="margin-bottom: 12px;">
|
| 749 |
<span class="badge badge-zerogpu">⚡ ZeroGPU</span>
|
| 750 |
+
<span class="badge badge-model">🎬 Wan 2.2 (MoE Diffusers)</span>
|
| 751 |
<span class="badge badge-multilora">🧩 Base NSFW + Multi-LoRA Engine</span>
|
| 752 |
</div>
|
| 753 |
+
<h1>Wan 2.2 AI Video Studio</h1>
|
| 754 |
+
<p>Image-to-Video (I2V) & Text-to-Video (T2V) com Arquitetura MoE Wan 2.2, Adaptador NSFW Base e Multi-LoRA.</p>
|
| 755 |
</div>
|
| 756 |
"""
|
| 757 |
)
|
|
|
|
| 772 |
value="deformed, bad anatomy, extra limbs, blurry, low resolution, bad quality, distortion, censorship",
|
| 773 |
)
|
| 774 |
|
| 775 |
+
with gr.Accordion("📖 Guia & Modelos de Prompt HMNSFW / hmmotion (Wan 2.2)", open=False):
|
| 776 |
gr.Markdown(
|
| 777 |
"""
|
| 778 |
**Estrutura Recomendada pelo Guia de 300 Horas / Autor do LoRA (`hmmotion`)**:
|
|
|
|
| 813 |
lora1_preset = gr.Dropdown(
|
| 814 |
label="LoRA Slot 1 Preset / Fonte",
|
| 815 |
choices=all_preset_choices,
|
| 816 |
+
value="HMNSFW AIO V2 / hmmotion (Wan 2.2)",
|
| 817 |
)
|
| 818 |
with gr.Group(visible=False) as lora1_custom_url_grp:
|
| 819 |
lora1_custom_url = gr.Textbox(
|
|
|
|
| 829 |
|
| 830 |
lora1_trigger_display = gr.Textbox(
|
| 831 |
label="Trigger Words",
|
| 832 |
+
value=LORA_PRESETS.get("HMNSFW AIO V2 / hmmotion (Wan 2.2)", {}).get("trigger_words", ""),
|
| 833 |
interactive=False,
|
| 834 |
)
|
| 835 |
add_lora1_triggers_btn = gr.Button("📋 Inserir Trigger Words no Prompt", elem_classes=["trigger-btn"])
|
|
|
|
| 880 |
model_choice = gr.Dropdown(
|
| 881 |
label="Modelo Base Wan",
|
| 882 |
choices=[
|
| 883 |
+
("Wan 2.2 I2V A14B 480P (MoE - Recomendado ZeroGPU)", "Wan-AI/Wan2.2-I2V-A14B-480P-Diffusers"),
|
| 884 |
+
("Wan 2.2 I2V A14B 720P (MoE Alta Definição)", "Wan-AI/Wan2.2-I2V-A14B-720P-Diffusers"),
|
| 885 |
+
("Wan 2.2 TI2V 5B (Híbrido Ultra Rápido)", "Wan-AI/Wan2.2-TI2V-5B-Diffusers"),
|
| 886 |
+
("Wan 2.2 T2V A14B (Texto para Vídeo MoE)", "Wan-AI/Wan2.2-T2V-A14B-Diffusers"),
|
| 887 |
+
("Wan 2.1 I2V 14B 480P (Versão Anterior)", "Wan-AI/Wan2.1-I2V-14B-480P-Diffusers"),
|
| 888 |
],
|
| 889 |
+
value="Wan-AI/Wan2.2-I2V-A14B-480P-Diffusers",
|
| 890 |
)
|
| 891 |
canvas = gr.Dropdown(
|
| 892 |
label="Proporção & Resolução (Múltiplos de 16)",
|
|
|
|
| 931 |
randomize_seed = gr.Checkbox(label="🎲 Randomizar Seed", value=True)
|
| 932 |
|
| 933 |
civitai_api_key = gr.Textbox(
|
| 934 |
+
label="🔑 Civitai API Key",
|
| 935 |
+
value=DEFAULT_CIVITAI_KEY,
|
| 936 |
+
placeholder="Chave de API do Civitai configurada",
|
| 937 |
type="password",
|
| 938 |
)
|
| 939 |
|
| 940 |
+
generate_btn = gr.Button("🚀 Gerar Vídeo Wan 2.2", variant="primary", elem_classes=["generate-btn"])
|
| 941 |
|
| 942 |
with gr.Column(scale=6):
|
| 943 |
output_video = gr.Video(label="Vídeo Gerado", autoplay=True, loop=True)
|