INVIDEO_BASIC / app.py
gnosticdev's picture
Update app.py
bafc5cd verified
raw
history blame
3.63 kB
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)