import os import gradio as gr import requests import tempfile import asyncio import edge_tts from datetime import datetime from moviepy.editor import ( VideoFileClip, AudioFileClip, concatenate_videoclips, CompositeAudioClip, afx ) from transformers import pipeline import logging import nest_asyncio nest_asyncio.apply() logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Generador de texto real con GPT-2 generador = pipeline("text-generation", model="gpt2") # Obtener voces async def get_voices(): return await edge_tts.list_voices() VOICES = asyncio.run(get_voices()) VOICE_OPTIONS = [f"{v['Name']} ({v['Gender']}, {v['Locale']})" for v in VOICES] VOICE_MAP = {v['Name']: v['ShortName'] for v in VOICES} # Simulación de búsqueda de videos def buscar_videos_mock(): return [ "https://samplelib.com/lib/preview/mp4/sample-5s.mp4", "https://samplelib.com/lib/preview/mp4/sample-10s.mp4" ] # Simulación de música de fondo def buscar_musica_mock(): return "https://samplelib.com/lib/preview/mp3/sample-3s.mp3" # Función principal async def generar_video(prompt, voz_str): try: logger.info("Generando guion...") texto = generador(prompt, max_length=500, do_sample=True, truncation=True)[0]['generated_text'] logger.info("Convirtiendo texto en voz...") voz_id = voz_str.split(" ")[0] short_name = VOICE_MAP.get(voz_id, "es-ES-ElviraNeural") voz_path = "voz.mp3" await edge_tts.Communicate(text=texto, voice=short_name).save(voz_path) voz_clip = AudioFileClip(voz_path) logger.info("Descargando clips de video...") video_urls = buscar_videos_mock() clips = [] for url in video_urls: r = requests.get(url, stream=True) with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as f: for chunk in r.iter_content(1024 * 1024): f.write(chunk) f.flush() clip = VideoFileClip(f.name).subclip(0, 5) clips.append(clip) video = concatenate_videoclips(clips).set_audio(voz_clip) logger.info("Descargando música de fondo...") music_url = buscar_musica_mock() r = requests.get(music_url, stream=True) with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as f: for chunk in r.iter_content(1024 * 1024): f.write(chunk) f.flush() music_clip = AudioFileClip(f.name) music_loop = afx.audio_loop(music_clip, duration=video.duration).volumex(0.3) logger.info("Combinando audio de voz y música...") audio_final = CompositeAudioClip([video.audio, music_loop]) video = video.set_audio(audio_final) output_path = f"video_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4" logger.info("Renderizando video final...") video.write_videofile(output_path, fps=24, logger=logger) return output_path except Exception as e: logger.error(f"Error: {e}") return f"Error: {e}" # Interfaz with gr.Blocks() as app: prompt = gr.Textbox(label="Tema del video", placeholder="Ejemplo: Top 5 misterios sin resolver") voz = gr.Dropdown(VOICE_OPTIONS, label="Voz", value=VOICE_OPTIONS[0]) btn = gr.Button("Generar Video") output = gr.Video(label="Resultado") btn.click(fn=lambda p, v: asyncio.run(generar_video(p, v)), inputs=[prompt, voz], outputs=output) if __name__ == "__main__": app.launch(server_name="0.0.0.0", server_port=7860)