Spaces:
Sleeping
Sleeping
| """ | |
| generate.py — Script principal de génération vidéo (Texte → Vidéo) | |
| Modèle utilisé : Wan 2.1 T2V 1.3B (Hugging Face Diffusers) | |
| Usage : | |
| python generate.py --prompt "votre prompt" --output ../outputs/ma_video.mp4 | |
| """ | |
| import argparse | |
| import os | |
| import sys | |
| def _select_torch_dtype(torch_module): | |
| if not torch_module.cuda.is_available(): | |
| return torch_module.float32 | |
| if torch_module.cuda.is_bf16_supported(): | |
| return torch_module.bfloat16 | |
| return torch_module.float16 | |
| def generate_video( | |
| prompt: str, | |
| output_path: str, | |
| negative_prompt: str = "déformé, moche, flou, mauvaise qualité, artefacts, texte, filigrane", | |
| num_frames: int = 24, | |
| num_inference_steps: int = 25, | |
| height: int = 480, | |
| width: int = 832, | |
| ) -> str: | |
| """ | |
| Génère une vidéo à partir d'un prompt texte et la sauvegarde dans le chemin spécifié. | |
| Args: | |
| prompt (str) : Description textuelle de la vidéo à générer. | |
| output_path (str) : Chemin de sauvegarde de la vidéo (ex: outputs/video.mp4). | |
| negative_prompt (str) : Ce que l'on ne veut PAS voir dans la vidéo. | |
| num_frames (int) : Nombre d'images à générer (24 ≈ 1 seconde à 24 fps). | |
| num_inference_steps (int): Nombre d'étapes de diffusion (plus = meilleure qualité, plus lent). | |
| height (int) : Hauteur de la vidéo en pixels. | |
| width (int) : Largeur de la vidéo en pixels. | |
| Returns: | |
| str: Le chemin de la vidéo générée, ou une chaîne vide en cas d'erreur. | |
| """ | |
| try: | |
| import torch | |
| # Importation différée pour éviter les erreurs si les dépendances ne sont pas installées | |
| from diffusers import AutoencoderKLWan, WanPipeline | |
| from diffusers.utils import export_to_video | |
| print(f"[INFO] Chargement du modèle Wan 2.1 T2V 1.3B...") | |
| print(f"[INFO] (Le premier chargement peut prendre du temps — téléchargement des poids)") | |
| model_id = "Wan-AI/Wan2.1-T2V-1.3B-Diffusers" | |
| dtype = _select_torch_dtype(torch) | |
| device = "cuda" if torch.cuda.is_available() else "cpu" | |
| print(f"[INFO] Appareil détecté : {device} | dtype : {dtype}") | |
| # Chargement du VAE (encodeur/décodeur vidéo) | |
| vae = AutoencoderKLWan.from_pretrained( | |
| model_id, subfolder="vae", torch_dtype=dtype | |
| ) | |
| # Chargement du pipeline principal | |
| pipe = WanPipeline.from_pretrained( | |
| model_id, vae=vae, torch_dtype=dtype | |
| ) | |
| if torch.cuda.is_available(): | |
| # Optimisation mémoire : décharge les parties inactives du modèle vers la RAM | |
| pipe.enable_model_cpu_offload() | |
| else: | |
| pipe = pipe.to(device) | |
| print(f"[INFO] Modèle chargé. Génération de la vidéo...") | |
| print(f"[INFO] Prompt : {prompt}") | |
| # Génération des frames vidéo | |
| output = pipe( | |
| prompt=prompt, | |
| negative_prompt=negative_prompt, | |
| height=height, | |
| width=width, | |
| num_frames=num_frames, | |
| num_inference_steps=num_inference_steps, | |
| ) | |
| # Création du dossier de sortie si nécessaire | |
| os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True) | |
| # Export en fichier vidéo MP4 | |
| video_path = export_to_video(output.frames[0], output_path, fps=16) | |
| print(f"[SUCCESS] Vidéo sauvegardée : {video_path}") | |
| return video_path | |
| except ImportError as e: | |
| print(f"[ERREUR] Dépendance manquante : {e}") | |
| print("[AIDE] Installez les dépendances avec : pip install -r requirements.txt") | |
| return "" | |
| except OSError as e: | |
| print(f"[ERREUR] Problème d'environnement Python ou de bibliothèque native : {e}") | |
| print("[AIDE] Utilisez de préférence Python 3.10, 3.11 ou 3.12 avec une version compatible de PyTorch.") | |
| return "" | |
| except Exception as e: | |
| print(f"[ERREUR] Erreur lors de la génération : {e}") | |
| return "" | |
| if __name__ == "__main__": | |
| parser = argparse.ArgumentParser( | |
| description="Générateur de vidéo IA (Texte → Vidéo) avec Wan 2.1" | |
| ) | |
| parser.add_argument( | |
| "--prompt", type=str, required=True, | |
| help="Description textuelle de la vidéo à générer" | |
| ) | |
| parser.add_argument( | |
| "--output", type=str, default="../outputs/generated_video.mp4", | |
| help="Chemin de sortie pour la vidéo (défaut: ../outputs/generated_video.mp4)" | |
| ) | |
| parser.add_argument( | |
| "--negative_prompt", type=str, | |
| default="déformé, moche, flou, mauvaise qualité, artefacts, texte, filigrane", | |
| help="Ce que l'on ne veut PAS voir dans la vidéo" | |
| ) | |
| parser.add_argument( | |
| "--num_frames", type=int, default=24, | |
| help="Nombre d'images à générer (défaut: 24 ≈ 1.5 secondes)" | |
| ) | |
| parser.add_argument( | |
| "--steps", type=int, default=25, | |
| help="Nombre d'étapes de diffusion (défaut: 25)" | |
| ) | |
| args = parser.parse_args() | |
| result = generate_video( | |
| prompt=args.prompt, | |
| output_path=args.output, | |
| negative_prompt=args.negative_prompt, | |
| num_frames=args.num_frames, | |
| num_inference_steps=args.steps, | |
| ) | |
| if result: | |
| print(f"\n✅ Génération réussie ! Vidéo disponible ici : {result}") | |
| else: | |
| print("\n❌ La génération a échoué. Consultez les messages d'erreur ci-dessus.") | |
| sys.exit(1) | |