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()