Spaces:
Building
Building
File size: 7,128 Bytes
3386266 2740481 aa29714 d4c89ff 2740481 4c8a9c1 d476eea dc833d2 d4c89ff dc833d2 d476eea 4c8a9c1 dc833d2 d4c89ff dc833d2 d476eea 0594fa6 724ed17 0594fa6 724ed17 dc1e7fd d4c89ff dc1e7fd 9abb848 dc1e7fd af20d0a dc1e7fd a75af72 724ed17 af20d0a 9abb848 af20d0a 9abb848 af20d0a a75af72 9abb848 af20d0a 724ed17 af20d0a 724ed17 a75af72 724ed17 af20d0a 724ed17 0594fa6 724ed17 d476eea 0594fa6 724ed17 aa29714 724ed17 aa29714 724ed17 2740481 661caf6 2740481 aa29714 2740481 aa29714 2740481 aa29714 724ed17 dc1e7fd 724ed17 af20d0a 724ed17 2740481 724ed17 a75af72 724ed17 3386266 d476eea 3386266 2740481 aa29714 2740481 724ed17 3386266 2740481 0594fa6 2740481 3386266 3c4ac90 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
import gradio as gr
from tts_module import get_voices, text_to_speech # Usamos el tts_module.py actualizado
from pexels_api import search_pexels
from moviepy.editor import AudioFileClip, VideoFileClip, CompositeAudioClip, concatenate_audioclips, concatenate_videoclips
import asyncio
import os
import requests
import tempfile
# Forzar instalación de moviepy si no está disponible
def install(package):
import subprocess
import sys
subprocess.check_call([sys.executable, "-m", "pip", "install", package])
try:
# Intentar importar moviepy.editor
from moviepy.editor import AudioFileClip, VideoFileClip, CompositeAudioClip, concatenate_audioclips, concatenate_videoclips
print("MoviePy.editor está instalado correctamente.")
except ImportError:
print("Instalando MoviePy...")
install("moviepy==1.0.3") # Forzar instalación de la versión compatible
try:
from moviepy.editor import AudioFileClip, VideoFileClip, CompositeAudioClip, concatenate_audioclips, concatenate_videoclips
print("MoviePy.editor instalado con éxito después de la reinstalación.")
except ImportError:
raise ImportError("Error crítico: No se pudo instalar moviepy.editor. Verifica las dependencias.")
# Ajustar música de fondo (repetición automática)
def adjust_background_music(video_duration, music_file):
music = AudioFileClip(music_file)
if music.duration < video_duration:
repetitions = int(video_duration / music.duration) + 1
music_clips = [music] * repetitions
music = concatenate_audioclips(music_clips)
if music.duration > video_duration:
music = music.subclip(0, video_duration)
music = music.volumex(0.2) # Reducir volumen al 20%
return music
# Concatenar múltiples videos de Pexels
def concatenate_pexels_videos(text, num_videos=5):
sentences = [sentence.strip() for sentence in text.split(".") if sentence.strip()]
video_links = []
for sentence in sentences:
try:
links = search_pexels(sentence, num_results=num_videos)
if links:
video_links.append(links[0]) # Usamos el primer video encontrado para cada frase
except Exception as e:
print(f"Error al buscar video para la frase '{sentence}': {e}")
continue
if not video_links:
raise Exception("No se encontraron videos relevantes para el texto proporcionado.")
video_clips = []
for link in video_links:
video_response = requests.get(link)
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_video:
tmp_video.write(video_response.content)
video_clips.append(VideoFileClip(tmp_video.name))
# Concatenar videos
final_clip = concatenate_videoclips(video_clips, method="compose")
return final_clip
# Combinar audio, video y música con fade out solo en el video y la música
def combine_audio_video(audio_file, video_clip, music_clip=None):
audio_clip = AudioFileClip(audio_file)
# Duración total: speech + 5 segundos para fade out
total_duration = audio_clip.duration + 5
# Extender la duración del video si es más corto que el audio + fade out
if video_clip.duration < total_duration:
video_clip = video_clip.loop(duration=total_duration) # Repetir el video si es necesario
# Aplicar fade out solo al video
video_clip = video_clip.set_duration(total_duration).fadeout(5)
# Combinar audio y video
final_clip = video_clip.set_audio(audio_clip)
# Añadir música de fondo si aplica
if music_clip:
# Extender la música para que coincida con la duración total
if music_clip.duration < total_duration:
repetitions = int(total_duration / music_clip.duration) + 1
music_clips = [music_clip] * repetitions
music_clip = concatenate_audioclips(music_clips)
if music_clip.duration > total_duration:
music_clip = music_clip.subclip(0, total_duration)
# Aplicar fade out a la música
music_clip = music_clip.audio_fadeout(5)
# Combinar audio principal, música y video
final_clip = final_clip.set_audio(CompositeAudioClip([audio_clip, music_clip]))
# Exportar el video final
output_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name
final_clip.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=24)
return output_path
# Función principal
def process_input(text, txt_file, mp3_file, selected_voice, rate, pitch):
try:
if text.strip():
final_text = text
elif txt_file is not None:
final_text = txt_file.decode("utf-8")
else:
return "No input provided", None
# Obtener voces disponibles
voices = asyncio.run(get_voices())
if selected_voice not in voices:
return f"La voz '{selected_voice}' no es válida. Por favor, seleccione una de las siguientes voces: {', '.join(voices.keys())}", None
# Generar audio con edge_tts
try:
audio_file = asyncio.run(text_to_speech(final_text, selected_voice, rate, pitch))
except Exception as e:
return f"Error con la voz seleccionada: {e}", None
# Concatenar múltiples videos de Pexels basados en el texto
try:
video_clip = concatenate_pexels_videos(final_text, num_videos=5)
except Exception as e:
return f"Error al buscar videos en Pexels: {e}", None
# Ajustar música de fondo
if mp3_file is not None:
music_clip = adjust_background_music(video_clip.duration, mp3_file.name)
else:
music_clip = None
# Combinar audio, video y música con fade out solo en el video y la música
final_video = combine_audio_video(audio_file, video_clip, music_clip)
return final_video
except Exception as e:
return f"Error durante el procesamiento: {e}", None
# Interfaz Gradio
with gr.Blocks() as demo:
gr.Markdown("# Text-to-Video Generator")
with gr.Row():
with gr.Column():
text_input = gr.Textbox(label="Write your text here", lines=5)
txt_file_input = gr.File(label="Or upload a .txt file", file_types=[".txt"])
mp3_file_input = gr.File(label="Upload background music (.mp3)", file_types=[".mp3"])
voices = asyncio.run(get_voices()) # Obtener voces disponibles
voice_dropdown = gr.Dropdown(choices=list(voices.keys()), label="Select Voice")
rate_slider = gr.Slider(minimum=-50, maximum=50, value=0, label="Speech Rate Adjustment (%)", step=1)
pitch_slider = gr.Slider(minimum=-20, maximum=20, value=0, label="Pitch Adjustment (Hz)", step=1)
with gr.Column():
output_video = gr.Video(label="Generated Video")
btn = gr.Button("Generate Video")
btn.click(
process_input,
inputs=[text_input, txt_file_input, mp3_file_input, voice_dropdown, rate_slider, pitch_slider],
outputs=output_video
)
demo.launch() |