import os import re import requests import gradio as gr from moviepy.editor import * import edge_tts import tempfile import logging from datetime import datetime import numpy as np from sklearn.feature_extraction.text import TfidfVectorizer import nltk from transformers import pipeline import torch import asyncio from nltk.tokenize import sent_tokenize import nest_asyncio # Nueva importación importante # Aplicar parche para el event loop nest_asyncio.apply() # Configuración inicial nltk.download('punkt', quiet=True) logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) # Configuración de modelos PEXELS_API_KEY = os.getenv("PEXELS_API_KEY") MODEL_NAME = "DeepESP/gpt2-spanish" # Lista de voces disponibles (versión optimizada) async def get_voices(): voices = await edge_tts.list_voices() return [v['ShortName'] for v in voices] # Ejecutar en un nuevo event loop loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) VOICE_NAMES = loop.run_until_complete(get_voices()) def generar_guion_profesional(prompt): """Genera guiones optimizados para voz""" try: generator = pipeline( "text-generation", model=MODEL_NAME, device=0 if torch.cuda.is_available() else -1 ) response = generator( f"Escribe un guion conciso (máximo 500 caracteres) sobre '{prompt}':", max_length=500, temperature=0.7, num_return_sequences=1 ) return response[0]['generated_text'] except Exception as e: logger.error(f"Error generando guion: {str(e)}") return f"Guion de ejemplo sobre {prompt}. Esto es una introducción. Aquí están los puntos principales. Conclusión final." # Función asíncrona optimizada async def async_video_creation(prompt, custom_script, voz_index, musica=None): try: # 1. Generar guion guion = custom_script if custom_script else generar_guion_profesional(prompt) if len(guion) > 2000: guion = guion[:2000] # Limitar tamaño para TTS # 2. Generar voz voz_archivo = "voz.mp3" communicate = edge_tts.Communicate(text=guion, voice=VOICE_NAMES[voz_index]) await communicate.save(voz_archivo) # 3. Crear clip de audio audio = AudioFileClip(voz_archivo) duracion = audio.duration # 4. Crear video simple (versión simplificada) clip = ColorClip(size=(1280, 720), color=(0, 0, 0), duration=duracion) clip = clip.set_audio(audio) # 5. Exportar output_path = f"video_output_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4" clip.write_videofile( output_path, fps=24, codec="libx264", audio_codec="aac", threads=2 ) return output_path except Exception as e: logger.error(f"Error crítico: {str(e)}") return None finally: if os.path.exists(voz_archivo): os.remove(voz_archivo) # Wrapper sincrónico para Gradio def generar_video(prompt, custom_script, voz_index, musica=None): try: return asyncio.run(async_video_creation(prompt, custom_script, voz_index, musica)) except Exception as e: logger.error(f"Error en wrapper: {str(e)}") return None # Interfaz simplificada with gr.Blocks(title="Generador de Videos") as app: gr.Markdown("## 🎥 Generador Automático de Videos") with gr.Row(): with gr.Column(): prompt = gr.Textbox(label="Tema del video", placeholder="Ej: Inteligencia Artificial") voz = gr.Dropdown(label="Voz Narradora", choices=VOICE_NAMES, value=VOICE_NAMES[0]) btn = gr.Button("Generar Video", variant="primary") with gr.Column(): output = gr.Video(label="Resultado", format="mp4") btn.click( fn=generar_video, inputs=[prompt, gr.Textbox(visible=False), voz], outputs=output, timeout=300 # 5 minutos de timeout ) if __name__ == "__main__": app.launch(server_port=7860, server_name="0.0.0.0")