Générez des vidéos avec le modèle Wan2.1 d'Alibaba sur les GPU Clore.ai
Générez des vidéos de haute qualité avec les modèles texte-à-vidéo et image-à-vidéo Wan2.1 d'Alibaba sur les GPU CLORE.AI.
Tous les exemples peuvent être exécutés sur des serveurs GPU loués via CLORE.AI Marketplace.
Pourquoi Wan2.1 ?
Haute qualité - Génération vidéo à la pointe de la technologie
Plusieurs modes - Texte vers vidéo, image vers vidéo
Différentes tailles - De 1,3B à 14B de paramètres
Vidéos longues - Jusqu'à 81 images
Poids ouverts - Licence Apache 2.0
Variantes de modèle
Modèle
Paramètres
VRAM
Résolution
Images
Wan2.1-T2V-1.3B
1,3B
8 Go
480p
81
Wan2.1-T2V-14B
14B
24 Go
720p
81
Wan2.1-I2V-14B
14B
24 Go
720p
81
Déploiement rapide sur CLORE.AI
Image Docker :
pytorch/pytorch:2.5.1-cuda12.4-cudnn9-devel
Ports :
Commande :
Accéder à votre service
Après le déploiement, trouvez votre http_pub URL dans Mes commandes:
Aller à la Mes commandes page
Cliquez sur votre commande
Trouvez l' http_pub URL (par ex., abc123.clorecloud.net)
Utilisez https://VOTRE_HTTP_PUB_URL au lieu de localhost dans les exemples ci-dessous.
Exigences matérielles
Modèle
GPU minimum
Recommandé
Optimal
T2V 1,3B
RTX 3070 8GB
RTX 3090 24GB
RTX 4090
T2V 14B
RTX 4090 24GB
A100 40GB
A100 80GB
I2V 14B
RTX 4090 24GB
A100 40GB
A100 80GB
Installation
Texte vers Vidéo
Utilisation de base (1,3B)
Haute qualité (14B)
Image vers Vidéo
Animer une image
Image vers Vidéo avec Wan2.1-I2V-14B
Wan2.1-I2V-14B anime une image statique en utilisant un prompt textuel pour guider le mouvement. Nécessite 24GB de VRAM (RTX 4090 ou A100 40GB recommandé).
Détails du modèle
Propriété
Valeur
ID du modèle
Wan-AI/Wan2.1-I2V-14B-480P
Paramètres
14 milliards
VRAM requise
24 Go
Résolution maximale
480p (854×480) ou 720p (1280×720)
Nombre maximal d'images
81
Licence
Apache 2.0
Exigences matérielles
GPU
VRAM
Statut
RTX 4090
24 Go
✅ Recommandé
RTX 3090
24 Go
✅ Pris en charge
A100 40GB
40Go
✅ Optimal
A100 80GB
80GB
✅ Meilleure qualité
RTX 3080
10Go
❌ Insuffisant
Script CLI rapide
Enregistrer sous generate_i2v.py et exécutez :
generate_i2v.py — Script complet
Pipeline I2V avancé (API Python)
Conseils de prompt I2V
Objectif
Exemple de prompt
Mouvement de caméra
"la caméra recule lentement depuis le sujet"
Effet de parallaxe
"mouvement parallax subtil, décalage de la profondeur de champ"
Animation de personnage
"la silhouette tourne la tête et sourit"
Animation de la nature
"les feuilles bruissent sous une brise légère, la lumière change"
Mouvement abstrait
"les couleurs tourbillonnent et se mélangent, mouvement fluide"
#!/usr/bin/env python3
"""
Script CLI Wan2.1 Image-to-Video.
Utilisation : python generate_i2v.py --model Wan-AI/Wan2.1-I2V-14B-480P \
--image input.jpg --prompt "la caméra recule lentement"
"""
import argparse
import os
import sys
import torch
from diffusers import WanImageToVideoPipeline
from diffusers.utils import load_image, export_to_video
from PIL import Image
def parse_args():
parser = argparse.ArgumentParser(description="Générateur Wan2.1 Image-to-Video")
parser.add_argument(
"--model",
type=str,
default="Wan-AI/Wan2.1-I2V-14B-480P",
help="ID du modèle depuis Hugging Face (par défaut : Wan-AI/Wan2.1-I2V-14B-480P)",
)
parser.add_argument(
"--image",
type=str,
required=True,
help="Chemin vers l'image d'entrée (JPEG ou PNG)",
)
parser.add_argument(
"--prompt",
type=str,
required=True,
help='Prompt textuel décrivant le mouvement souhaité (ex. "la caméra recule lentement")',
)
parser.add_argument(
"--negative-prompt",
type=str,
default="flou, basse qualité, déformé, mouvement saccadé, artefacts",
help="Prompt négatif pour éviter les artefacts indésirables",
)
parser.add_argument(
"--frames",
type=int,
default=49,
help="Nombre d'images vidéo à générer (par défaut : 49, max : 81)",
)
parser.add_argument(
"--steps",
type=int,
default=50,
help="Nombre d'étapes de diffusion (par défaut : 50)",
)
parser.add_argument(
"--guidance",
type=float,
default=7.0,
help="Échelle de guidance sans classificateur (par défaut : 7.0)",
)
parser.add_argument(
"--seed",
type=int,
default=-1,
help="Graine aléatoire pour reproductibilité (-1 = aléatoire)",
)
parser.add_argument(
"--fps",
type=int,
default=16,
help="FPS de la vidéo de sortie (par défaut : 16)",
)
parser.add_argument(
"--output",
type=str,
default="output_i2v.mp4",
help="Chemin du fichier vidéo de sortie (par défaut : output_i2v.mp4)",
)
parser.add_argument(
"--height",
type=int,
default=480,
help="Hauteur de la vidéo de sortie en pixels (par défaut : 480)",
)
parser.add_argument(
"--width",
type=int,
default=854,
help="Largeur de la vidéo de sortie en pixels (par défaut : 854)",
)
parser.add_argument(
"--cpu-offload",
action="store_true",
default=True,
help="Activer le déchargement du modèle vers le CPU pour économiser la VRAM (par défaut : True)",
)
parser.add_argument(
"--vae-tiling",
action="store_true",
default=False,
help="Activer le tiling VAE pour des sorties haute résolution",
)
return parser.parse_args()
def load_and_resize_image(image_path: str, width: int, height: int) -> Image.Image:
"""Charger l'image depuis le chemin et redimensionner aux dimensions cibles."""
if not os.path.exists(image_path):
print(f"[ERROR] Image non trouvée : {image_path}", file=sys.stderr)
sys.exit(1)
img = Image.open(image_path).convert("RGB")
original_size = img.size
img = img.resize((width, height), Image.LANCZOS)
print(f"[INFO] Image chargée : {image_path} ({original_size[0]}x{original_size[1]}) → redimensionnée en {width}x{height}")
return img
def load_pipeline(model_id: str, cpu_offload: bool, vae_tiling: bool):
"""Charger le pipeline Wan I2V avec des optimisations mémoire."""
print(f"[INFO] Chargement du modèle : {model_id}")
print(f"[INFO] CUDA disponible : {torch.cuda.is_available()}")
if torch.cuda.is_available():
vram_gb = torch.cuda.get_device_properties(0).total_memory / 1e9
print(f"[INFO] GPU : {torch.cuda.get_device_name(0)} ({vram_gb:.1f} GB de VRAM)")
if vram_gb < 23:
print("[WARN] Moins de 24GB de VRAM détectés — activez --cpu-offload ou utilisez le modèle 1.3B")
pipe = WanImageToVideoPipeline.from_pretrained(
model_id,
torch_dtype=torch.float16,
)
if cpu_offload:
print("[INFO] Activation du déchargement du modèle sur le CPU")
pipe.enable_model_cpu_offload()
else:
pipe.to("cuda")
if vae_tiling:
print("[INFO] Activation du tiling VAE pour la génération haute résolution")
pipe.enable_vae_tiling()
return pipe
def generate_video(pipe, args) -> None:
"""Exécuter le pipeline I2V et sauvegarder la vidéo de sortie."""
image = load_and_resize_image(args.image, args.width, args.height)
generator = None
if args.seed >= 0:
generator = torch.Generator("cuda").manual_seed(args.seed)
print(f"[INFO] Utilisation de la graine : {args.seed}")
else:
print("[INFO] Utilisation d'une graine aléatoire")
print(f"[INFO] Génération de {args.frames} images à {args.width}x{args.height}")
print(f"[INFO] Étapes : {args.steps} | Guidance : {args.guidance} | FPS : {args.fps}")
print(f"[INFO] Prompt : {args.prompt}")
output = pipe(
prompt=args.prompt,
negative_prompt=args.negative_prompt,
image=image,
num_frames=args.frames,
height=args.height,
width=args.width,
num_inference_steps=args.steps,
guidance_scale=args.guidance,
generator=generator,
)
export_to_video(output.frames[0], args.output, fps=args.fps)
print(f"[INFO] Vidéo sauvegardée dans : {os.path.abspath(args.output)}")
duration = args.frames / args.fps
print(f"[INFO] Durée : {duration:.1f}s à {args.fps}fps ({args.frames} images)")
def main():
args = parse_args()
if not torch.cuda.is_available():
print("[ERROR] GPU CUDA introuvable. Wan2.1-I2V-14B nécessite un GPU compatible CUDA.", file=sys.stderr)
sys.exit(1)
pipe = load_pipeline(args.model, args.cpu_offload, args.vae_tiling)
generate_video(pipe, args)
print("[DONE] Génération image-vidéo terminée !")
if __name__ == "__main__":
main()
import torch
from diffusers import WanImageToVideoPipeline
from diffusers.utils import load_image, export_to_video
from PIL import Image
# ── Charger le pipeline ──────────────────────────────────────────────────────────────
pipe = WanImageToVideoPipeline.from_pretrained(
"Wan-AI/Wan2.1-I2V-14B-480P",
torch_dtype=torch.float16,
)
pipe.enable_model_cpu_offload() # maintient la VRAM en dessous de 24GB
pipe.enable_vae_tiling() # optionnel : utile pour le 720p
# ── Charger & préparer l'image d'entrée ───────────────────────────────────────────────
image = load_image("input.jpg").resize((854, 480))
# ── Générer ─────────────────────────────────────────────────────────────────────────
prompt = "la caméra recule lentement, révélant le paysage complet"
negative_prompt = "flou, basse qualité, déformé, scintillement, artefacts"
generator = torch.Generator("cuda").manual_seed(42)
output = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
image=image,
num_frames=49, # ~3 secondes à 16fps
height=480,
width=854,
num_inference_steps=50,
guidance_scale=7.5,
generator=generator,
)
export_to_video(output.frames[0], "i2v_output.mp4", fps=16)
print("Sauvegardé : i2v_output.mp4")
# Obligatoire sur les GPU 24GB
pipe.enable_model_cpu_offload()
# Optionnel : réduit le pic de VRAM d'environ 10%
pipe.enable_vae_tiling()
pipe.enable_vae_slicing()
# Vider entre les exécutions
import gc
gc.collect()
torch.cuda.empty_cache()
prompts = [
"Timelapse de nuages se déplaçant au-dessus des sommets, éclairage dramatique",
"Vagues de l'océan s'écrasant sur des rochers, ralenti, cinématographique",
"Aurores boréales dansant dans le ciel nocturne, couleurs vibrantes",
"Forêt en automne avec des feuilles tombant, atmosphère paisible"
]
prompts = [
"Un golden retriever courant dans un champ de fleurs",
"Un papillon sortant de son cocon, plan macro",
"Un samouraï tirant son sabre, éclairage dramatique",
"Un robot marchant dans des rues de ville futuriste"
]
prompts = [
"Peinture colorée tourbillonnant dans l'eau, art abstrait",
"Formes géométriques se transformant et se métamorphosant, couleurs néon",
"Gouttes d'encre se répandant dans du lait, photographie macro"
]
import os
import torch
from diffusers import WanPipeline
from diffusers.utils import export_to_video
pipe = WanPipeline.from_pretrained("alibaba-pai/Wan2.1-T2V-1.3B", torch_dtype=torch.float16)
pipe.to("cuda")
pipe.enable_model_cpu_offload()
prompts = [
"Un lanceur de fusée s'envolant dans l'espace",
"Poissons nageant dans un récif corallien",
"Pluie tombant dans une rue de ville la nuit"
]
output_dir = "./videos"
os.makedirs(output_dir, exist_ok=True)
for i, prompt in enumerate(prompts):
print(f"Génération {i+1}/{len(prompts)} : {prompt[:40]}...")
output = pipe(
prompt=prompt,
num_frames=49,
num_inference_steps=50
)
export_to_video(output.frames[0], f"{output_dir}/video_{i:03d}.mp4", fps=16)
torch.cuda.empty_cache()
import gradio as gr
import torch
from diffusers import WanPipeline
from diffusers.utils import export_to_video
import tempfile
pipe = WanPipeline.from_pretrained("alibaba-pai/Wan2.1-T2V-1.3B", torch_dtype=torch.float16)
pipe.to("cuda")
pipe.enable_model_cpu_offload()
def generate_video(prompt, negative_prompt, frames, steps, guidance, seed):
generator = torch.Generator("cuda").manual_seed(seed) if seed > 0 else None
output = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_frames=frames,
num_inference_steps=steps,
guidance_scale=guidance,
generator=generator
)
with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as f:
export_to_video(output.frames[0], f.name, fps=16)
return f.name
demo = gr.Interface(
fn=generate_video,
inputs=[
gr.Textbox(label="Prompt", lines=2),
gr.Textbox(label="Negative Prompt", value="flou, basse qualité"),
gr.Slider(17, 81, value=49, step=8, label="Images"),
gr.Slider(20, 100, value=50, step=5, label="Étapes"),
gr.Slider(3, 12, value=7, step=0.5, label="Guidance"),
gr.Number(value=-1, label="Graine")
],
outputs=gr.Video(label="Vidéo générée"),
title="Wan2.1 - Génération Texte vers Vidéo",
description="Générez des vidéos à partir de prompts textuels. Exécution sur CLORE.AI."
)
demo.launch(server_name="0.0.0.0", server_port=7860)
# Activer toutes les optimisations
pipe.enable_model_cpu_offload()
pipe.enable_vae_tiling()
pipe.enable_vae_slicing()
# Pour une VRAM très faible
pipe.enable_sequential_cpu_offload()
# Vider le cache entre les générations
torch.cuda.empty_cache()
# Utiliser un modèle plus petit
pipe = WanPipeline.from_pretrained("alibaba-pai/Wan2.1-T2V-1.3B")
# Activer toutes les optimisations
pipe.enable_model_cpu_offload()
pipe.enable_vae_tiling()
# Réduire le nombre d'images
output = pipe(prompt, num_frames=17)
# Réduire la résolution
output = pipe(prompt, height=480, width=854)