File size: 9,771 Bytes
4225fe9 ebb5440 7a0fe93 ebb5440 2e33d63 8c7203f 6c1eb66 2e33d63 eddc67d 6c1eb66 2e33d63 ebb5440 2e33d63 d1ec474 6c1eb66 2e33d63 ac0e5d3 2e33d63 6c1eb66 2e33d63 6c1eb66 2e33d63 6c1eb66 2e33d63 6c1eb66 2e33d63 6c1eb66 2e33d63 6c1eb66 2e33d63 d1ec474 2e33d63 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | import streamlit as st
from PIL import Image
import torch
import tempfile
import os
import io
import base64
# Configuration de la page - IMPORTANT pour Hugging Face Spaces
st.set_page_config(
page_title="Video AI Generator",
page_icon="🎥",
layout="wide",
initial_sidebar_state="expanded"
)
# Configuration spéciale pour Hugging Face Spaces
if 'HF_SPACE' in os.environ:
# Désactiver les vérifications CSRF pour HF Spaces
st.set_option('server.enableCORS', True)
st.set_option('server.enableXsrfProtection', False)
# Configuration pour éviter les erreurs de mémoire
@st.cache_resource
def load_pipeline():
"""Charge le pipeline avec optimisations mémoire"""
try:
from diffusers import StableDiffusionImg2ImgPipeline
# Utiliser un modèle plus léger ou optimisé
model_id = "runwayml/stable-diffusion-v1-5"
pipeline = StableDiffusionImg2ImgPipeline.from_pretrained(
model_id,
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
use_safetensors=True,
)
# Optimisations mémoire
if torch.cuda.is_available():
pipeline = pipeline.to("cuda")
pipeline.enable_memory_efficient_attention()
pipeline.enable_attention_slicing()
else:
pipeline = pipeline.to("cpu")
return pipeline
except Exception as e:
st.error(f"Erreur lors du chargement du modèle : {e}")
return None
def safe_file_upload():
"""Upload de fichier sécurisé avec gestion d'erreurs"""
try:
# Upload avec paramètres optimisés pour HF Spaces
uploaded_file = st.file_uploader(
"Choisissez une image",
type=['png', 'jpg', 'jpeg'],
accept_multiple_files=False,
key="image_uploader",
help="Formats supportés: PNG, JPG, JPEG (max 10MB recommandé)"
)
if uploaded_file is not None:
# Vérifier la taille du fichier
file_size = len(uploaded_file.getvalue())
if file_size > 10 * 1024 * 1024: # 10MB
st.warning(f"⚠️ Fichier volumineux ({file_size/1024/1024:.1f}MB). Réduisez la taille pour de meilleures performances.")
# Charger l'image avec gestion d'erreur
try:
image = Image.open(uploaded_file)
st.success(f"✅ Image chargée: {image.size[0]}x{image.size[1]} pixels")
return image, uploaded_file
except Exception as img_error:
st.error(f"❌ Erreur lors du chargement de l'image: {img_error}")
return None, None
except Exception as upload_error:
st.error(f"❌ Erreur d'upload: {upload_error}")
st.info("💡 Essayez de rafraîchir la page ou utilisez un fichier plus petit")
return None, None
return None, None
def process_image(image, prompt, strength=0.75, guidance_scale=7.5):
"""Traite l'image avec le pipeline"""
try:
pipeline = load_pipeline()
if pipeline is None:
return None
# Redimensionner l'image pour éviter les problèmes de mémoire
max_size = 512
if image.width > max_size or image.height > max_size:
image.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
# S'assurer que l'image est en RGB
if image.mode != "RGB":
image = image.convert("RGB")
# Générer l'image
with torch.autocast("cuda" if torch.cuda.is_available() else "cpu"):
result = pipeline(
prompt=prompt,
image=image,
strength=strength,
guidance_scale=guidance_scale,
num_inference_steps=20, # Réduire pour plus de vitesse
height=image.height,
width=image.width
)
return result.images[0]
except Exception as e:
st.error(f"Erreur lors de la génération : {e}")
return None
# Interface utilisateur
def main():
st.title("🎥 Générateur Video AI")
st.markdown("Transformez vos images avec l'IA")
# Afficher le statut de l'environnement
if 'HF_SPACE' in os.environ:
st.info("🚀 Application déployée sur Hugging Face Spaces")
# Sidebar pour les paramètres
with st.sidebar:
st.header("⚙️ Paramètres")
strength = st.slider(
"Force de transformation",
min_value=0.1,
max_value=1.0,
value=0.75,
step=0.05,
help="Plus élevé = plus de changements"
)
guidance_scale = st.slider(
"Échelle de guidance",
min_value=1.0,
max_value=20.0,
value=7.5,
step=0.5,
help="Plus élevé = plus fidèle au prompt"
)
st.markdown("---")
st.markdown("💡 **Conseils:**")
st.markdown("- Utilisez des images < 10MB")
st.markdown("- Format recommandé: PNG, JPG")
st.markdown("- Résolution max: 512x512")
# Section principale
col1, col2 = st.columns([1, 1])
with col1:
st.header("📤 Image d'entrée")
# Upload de fichier sécurisé
input_image, uploaded_file = safe_file_upload()
if input_image is not None:
# Redimensionner pour l'affichage
display_image = input_image.copy()
if display_image.width > 400:
display_image.thumbnail((400, 400), Image.Resampling.LANCZOS)
st.image(display_image, caption="Image d'origine", use_column_width=True)
# Zone de texte pour le prompt
prompt = st.text_area(
"🎨 Décrivez la transformation souhaitée:",
placeholder="Ex: transformer en anime style, ajouter des couleurs vives, style cyberpunk...",
height=100,
key="prompt_input"
)
# Bouton de génération
if st.button("🚀 Générer", type="primary", use_container_width=True):
if prompt.strip():
with st.spinner("Génération en cours... Cela peut prendre quelques minutes."):
result_image = process_image(
input_image,
prompt,
strength,
guidance_scale
)
if result_image:
# Stocker le résultat dans la session
st.session_state['result_image'] = result_image
st.success("✅ Génération terminée!")
st.rerun()
else:
st.error("❌ Erreur lors de la génération")
else:
st.warning("⚠️ Veuillez entrer une description")
with col2:
st.header("🎨 Résultat")
# Afficher le résultat s'il existe
if 'result_image' in st.session_state:
result_image = st.session_state['result_image']
# Redimensionner pour l'affichage
display_result = result_image.copy()
if display_result.width > 400:
display_result.thumbnail((400, 400), Image.Resampling.LANCZOS)
st.image(display_result, caption="Image transformée", use_column_width=True)
# Bouton de téléchargement
try:
buffered = io.BytesIO()
result_image.save(buffered, format="PNG")
st.download_button(
label="💾 Télécharger le résultat",
data=buffered.getvalue(),
file_name="result_ai.png",
mime="image/png",
use_container_width=True
)
except Exception as e:
st.error(f"Erreur lors de la préparation du téléchargement: {e}")
else:
st.info("👈 Uploadez une image et entrez un prompt pour commencer")
# Section de dépannage
with st.expander("🔧 Problèmes d'upload?"):
st.markdown("""
**Si vous ne pouvez pas charger d'images:**
1. **Rafraîchissez** la page (F5)
2. **Réduisez** la taille de votre image (< 5MB)
3. **Changez** le format (essayez JPG au lieu de PNG)
4. **Utilisez** un autre navigateur
5. **Attendez** quelques secondes et réessayez
**Formats supportés:** PNG, JPG, JPEG
**Taille recommandée:** < 10MB
""")
# Instructions
with st.expander("📖 Instructions d'utilisation"):
st.markdown("""
### Comment utiliser cette application:
1. **Uploadez une image** dans la section de gauche
2. **Décrivez la transformation** que vous souhaitez
3. **Ajustez les paramètres** dans la sidebar si nécessaire
4. **Cliquez sur Générer** et patientez
5. **Téléchargez le résultat** une fois terminé
### Exemples de prompts:
- "transformer en style anime"
- "ajouter des couleurs arc-en-ciel"
- "style cyberpunk néon"
- "portrait artistique à l'aquarelle"
- "paysage fantastique avec des dragons"
""")
if __name__ == "__main__":
main() |