Spaces:
Sleeping
Sleeping
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") |