Spaces:
Running
Running
import os | |
import asyncio | |
import edge_tts | |
import gradio as gr | |
from moviepy.editor import * | |
from transformers import pipeline | |
import requests | |
from datetime import datetime | |
# 1. Configuraci贸n inicial (SIN ASYNCIO en callbacks) | |
VOICES = asyncio.run(edge_tts.list_voices()) | |
PEXELS_API_KEY = os.getenv("PEXELS_API_KEY") | |
# 2. Generador de gui贸n (sincr贸nico) | |
def generar_guion(prompt): | |
try: | |
generator = pipeline("text-generation", model="facebook/mbart-large-50") | |
return generator( | |
f"Genera un guion sobre '{prompt}' (4 puntos breves):", | |
max_length=200, | |
num_return_sequences=1 | |
)[0]['generated_text'] | |
except Exception as e: | |
print(f"Error en generaci贸n: {e}") | |
return prompt # Fallback al texto original | |
# 3. Funci贸n principal (sincr贸nica) | |
def crear_video(prompt, script_personalizado, voz_seleccionada, musica=None): | |
try: | |
# A. Generar gui贸n | |
guion = script_personalizado if script_personalizado else generar_guion(prompt) | |
# B. Generar voz (soluci贸n sincr贸nica) | |
os.system(f'edge-tts --voice "{voz_seleccionada}" --text "{guion}" --write-media "voz.mp3"') | |
# C. Descargar videos | |
headers = {"Authorization": PEXELS_API_KEY} | |
query = prompt[:50].replace(" ", "+") | |
response = requests.get( | |
f"https://api.pexels.com/videos/search?query={query}&per_page=2", | |
headers=headers, | |
timeout=10 | |
) | |
videos = response.json().get("videos", []) | |
# D. Procesar audio | |
audio = AudioFileClip("voz.mp3") | |
if musica: | |
musica_clip = AudioFileClip(musica.name) | |
if musica_clip.duration < audio.duration: | |
musica_clip = musica_clip.loop(duration=audio.duration) | |
audio = CompositeAudioClip([audio, musica_clip.volumex(0.3)]) | |
# E. Renderizar video | |
clips = [VideoFileClip(v["video_files"][0]["link"]).subclip(0, 5) for v in videos[:2]] | |
final_clip = concatenate_videoclips(clips).set_audio(audio) | |
output_path = f"video_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4" | |
final_clip.write_videofile(output_path, codec="libx264", audio_codec="aac", threads=2) | |
return output_path | |
except Exception as e: | |
print(f"ERROR CR脥TICO: {e}") | |
return None | |
# 4. Interfaz (con queue enabled=False) | |
with gr.Blocks(title="Generador de Videos", css="footer {visibility: hidden}") as app: | |
gr.Markdown("# 馃幀 GENERADOR DE VIDEOS (ESTABLE)") | |
with gr.Row(): | |
with gr.Column(): | |
prompt = gr.Textbox(label="Tema principal", placeholder="Ej: 'Tecnolog铆a en 2025'") | |
script = gr.TextArea(label="Guion personalizado (opcional)", lines=5) | |
voz = gr.Dropdown( | |
label="Selecciona voz", | |
choices=[v["Name"] for v in VOICES], | |
value="es-ES-ElviraNeural" | |
) | |
musica = gr.File(label="M煤sica (opcional)", file_types=[".mp3"]) | |
btn = gr.Button("Generar Video", variant="primary") | |
with gr.Column(): | |
output = gr.Video(label="Resultado", autoplay=True) | |
btn.click( | |
fn=crear_video, | |
inputs=[prompt, script, voz, musica], | |
outputs=output, | |
api_name="generar" # Evita usar colas | |
) | |
# 5. Lanzamiento (sin colas) | |
app.launch(enable_queue=False) # 隆Clave para evitar el error! |