Spaces:
Running
Running
| 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) | |