Wan2.2-mini / app.py
LucanDerLurch's picture
Update app.py
590fc82 verified
import gradio as gr
import torch
from diffusers import I2VGenXLPipeline, LCMScheduler
from diffusers.utils import export_to_video
import gc
import traceback
MODEL_ID = "ali-vilab/i2vgen-xl"
LORA_ID = "latent-consistency/lcm-lora-sdxl"
pipe = None
def load_model_safely():
global pipe
if pipe is not None:
return pipe, "Modell ist bereit."
log = "System Start...\n"
print("Lade Modell...")
try:
# Standard float32 für maximale CPU Kompatibilität
pipe = I2VGenXLPipeline.from_pretrained(
MODEL_ID,
torch_dtype=torch.float32,
variant="fp16"
)
log += "🚀 Lade LCM Turbo LoRA...\n"
try:
pipe.load_lora_weights(LORA_ID)
pipe.fuse_lora()
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
log += "✅ LCM Turbo ist AKTIV!\n"
except Exception as e:
log += f"⚠️ Turbo Fehler: {e}\n"
# Versuche aggressives Speichermanagement
try:
pipe.enable_model_cpu_offload()
log += "✅ Model Offloading aktiv.\n"
except:
try:
pipe.enable_sequential_cpu_offload()
log += "✅ Sequential Offloading aktiv.\n"
except:
log += "❌ RAM WARNUNG: Kein Offloading.\n"
pipe.enable_vae_slicing()
pipe.enable_vae_tiling()
return pipe, log
except Exception as e:
return None, f"Absturz beim Laden: {e}\n{traceback.format_exc()}"
def generate_video(image_in, prompt, negative_prompt, resolution, progress=gr.Progress()):
global pipe
log_messages = ""
if image_in is None:
return None, "Kein Bild!"
# Initialisierung des Balkens
progress(0, desc="Lade Modell...")
if pipe is None:
model, msg = load_model_safely()
log_messages += msg
pipe = model
if pipe is None:
return None, log_messages + "Abbruch: Modell nicht geladen."
gc.collect()
try:
# EINSTELLUNGEN
steps = 6
guidance = 1.2
# Slider Wert übernehmen
target_size = int(resolution)
log_messages += f"Skaliere Bild auf {target_size}x{target_size}...\n"
# Bild resizing (WICHTIG für Speed!)
image_in = image_in.resize((target_size, target_size))
log_messages += f"Starte Generierung ({steps} Steps)...\n"
generator = torch.manual_seed(42)
# --- FIX FÜR DEN FORTSCHRITTSBALKEN (Alte Methode) ---
def callback_fn(step, timestep, latents):
# step ist hier der Index (0, 1, 2...)
current = step + 1
progress((current, steps), desc=f"Step {current}/{steps} (Größe: {target_size}px)")
# -----------------------------------------------------
output = pipe(
prompt=prompt,
image=image_in,
negative_prompt=negative_prompt,
num_frames=16,
num_inference_steps=steps,
guidance_scale=guidance,
height=target_size,
width=target_size,
generator=generator,
callback=callback_fn, # Alte Methode nutzen!
callback_steps=1
).frames[0]
video_path = "turbo_output.mp4"
export_to_video(output, video_path, fps=8)
log_messages += "✅ FERTIG!"
return video_path, log_messages
except Exception as e:
# Fehler abfangen und anzeigen
err_msg = str(e)
return None, log_messages + f"\n❌ Fehler: {err_msg}"
# UI
with gr.Blocks() as demo:
gr.Markdown("# I2VGen-XL ⚡ LCM TURBO (Repariert)")
gr.Markdown("Wähle die Auflösung passend zur Geduld. **384px oder 448px** empfohlen!")
with gr.Row():
with gr.Column():
img = gr.Image(type="pil", label="Bild")
txt = gr.Textbox(label="Prompt", value="fireworks in the sky")
neg = gr.Textbox(value="distortion, blurry", label="Negative")
# DER WICHTIGE REGLER FÜR SPEED
resolution_slider = gr.Slider(
minimum=320,
maximum=640,
value=448,
step=64,
label="Auflösung (Pixel)",
info="384 = Schnell | 448 = Mittel | 512+ = Langsam"
)
btn = gr.Button("Turbo Start")
with gr.Row():
vid = gr.Video(label="Video")
logs = gr.Textbox(label="Status Log", lines=10)
btn.click(generate_video, [img, txt, neg, resolution_slider], [vid, logs])
demo.launch()