INVIDEO_BASIC / app.py
gnosticdev's picture
Update app.py
c537a4f verified
raw
history blame
4.09 kB
import gradio as gr
import asyncio
import edge_tts
import requests
import tempfile
import os
from datetime import datetime
from moviepy.editor import VideoFileClip, concatenate_videoclips, AudioFileClip, CompositeAudioClip
# Voz predeterminada (puedes cambiarla o cargar lista)
VOCES = [{'ShortName': 'es-ES-ElviraNeural', 'Name': 'Elvira', 'Gender': 'Female'}]
VOICE_NAMES = [f"{v['Name']} ({v['Gender']})" for v in VOCES]
# Simula función para generar texto según prompt
def generar_texto(prompt):
# Aquí deberías integrar tu generador real, por ahora solo repetimos prompt
return f"Este es un texto generado para el tema: {prompt}"
# Simula función para buscar videos (debes conectar con Pexels u otra API)
def buscar_videos(prompt):
# Retorna lista simulada con links a videos (debes poner tu API real)
return [
{
"video_files": [{"link": "https://filesamples.com/samples/video/mp4/sample_640x360.mp4"}],
"duration": 10
},
{
"video_files": [{"link": "https://filesamples.com/samples/video/mp4/sample_640x360.mp4"}],
"duration": 10
}
]
async def crear_video(prompt, voz_index, musica_path=None):
try:
texto = generar_texto(prompt)
voz_shortname = VOCES[voz_index]['ShortName']
# Generar audio TTS
archivo_audio = "audio.mp3"
await edge_tts.Communicate(texto, voz_shortname).save(archivo_audio)
audio_clip = AudioFileClip(archivo_audio)
duracion_audio = audio_clip.duration
# Cargar música si se pasa
if musica_path:
musica_clip = AudioFileClip(musica_path).volumex(0.2) # Volumen bajo para música
musica_clip = musica_clip.subclip(0, duracion_audio)
audio_final = CompositeAudioClip([musica_clip, audio_clip])
else:
audio_final = audio_clip
# Descargar y preparar videos
videos = buscar_videos(prompt)
if not videos:
return None
clips = []
for v in videos[:3]:
video_url = v['video_files'][0]['link']
response = requests.get(video_url, stream=True)
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
for chunk in response.iter_content(chunk_size=1024*1024):
temp_file.write(chunk)
temp_file.close()
clip = VideoFileClip(temp_file.name).subclip(0, min(duracion_audio/len(videos), v['duration']))
clips.append(clip)
video_final = concatenate_videoclips(clips)
video_final = video_final.set_audio(audio_final)
output_filename = f"video_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
video_final.write_videofile(output_filename, codec="libx264", audio_codec="aac", fps=24)
# Limpieza
audio_clip.close()
if musica_path:
musica_clip.close()
for c in clips:
c.close()
os.remove(c.filename)
os.remove(archivo_audio)
return output_filename
except Exception as e:
return f"Error: {e}"
def run_crear_video(prompt, voz_nombre, musica_file):
try:
voz_index = VOICE_NAMES.index(voz_nombre)
except ValueError:
voz_index = 0
musica_path = musica_file.name if musica_file else None
return asyncio.run(crear_video(prompt, voz_index, musica_path))
with gr.Blocks(title="Generador de Video con TTS y Música de Fondo") as demo:
with gr.Row():
with gr.Column():
prompt = gr.Textbox(label="Tema del video", lines=2)
voz = gr.Dropdown(VOICE_NAMES, label="Voz", value=VOICE_NAMES[0])
musica = gr.File(label="Sube música de fondo (opcional, mp3/wav)", file_types=[".mp3", ".wav"])
btn = gr.Button("Generar Video")
with gr.Column():
salida = gr.Video(label="Video generado")
btn.click(run_crear_video, inputs=[prompt, voz, musica], outputs=salida)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)