Spaces:
Sleeping
Sleeping
File size: 8,063 Bytes
43fcbe8 19224f2 38ff849 8337d0b c9d2e08 07b3b3d 38ff849 dd712f9 07b3b3d 38ff849 720c3d5 38ff849 1672ed1 38ff849 1672ed1 38ff849 07b3b3d 38ff849 07b3b3d 38ff849 07b3b3d 38ff849 07b3b3d 38ff849 c7b9a72 38ff849 19224f2 38ff849 19224f2 8337d0b 38ff849 8337d0b 19224f2 38ff849 c7b9a72 19224f2 38ff849 8337d0b 38ff849 07b3b3d 38ff849 07b3b3d 38ff849 19224f2 38ff849 8337d0b 38ff849 8337d0b 38ff849 8337d0b 38ff849 fa201eb 38ff849 fa201eb 38ff849 720c3d5 07b3b3d 38ff849 07b3b3d 38ff849 c9d2e08 38ff849 d7f3a60 38ff849 8337d0b 38ff849 518f669 9e5ee0a d7f3a60 38ff849 07b3b3d |
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 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
import os
import subprocess
import requests
import gradio as gr
from moviepy.editor import *
from datetime import datetime
import tempfile
import logging
from transformers import pipeline
# Configuraci贸n inicial
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
PEXELS_API_KEY = os.getenv("PEXELS_API_KEY") # Configurar en Hugging Face
# Lista de voces v谩lidas (puedes a帽adir m谩s)
VOICES = [
"es-MX-DaliaNeural", "es-ES-ElviraNeural", "es-AR-ElenaNeural",
"en-US-JennyNeural", "fr-FR-DeniseNeural", "de-DE-KatjaNeural",
"it-IT-ElsaNeural", "pt-BR-FranciscaNeural", "ja-JP-NanamiNeural"
]
# Inicializar el generador de texto
try:
script_generator = pipeline("text-generation", model="facebook/mbart-large-50")
except:
logger.warning("No se pudo cargar el modelo de generaci贸n de texto")
script_generator = None
def generar_guion(prompt):
"""Genera un guion autom谩tico usando IA"""
if script_generator:
try:
result = script_generator(
f"Genera un guion breve para un video sobre '{prompt}' con 3 puntos principales:",
max_length=250,
num_return_sequences=1
)
return result[0]['generated_text']
except Exception as e:
logger.error(f"Error generando guion: {str(e)}")
# Fallback si falla la generaci贸n
return f"1. Primer punto sobre {prompt}\n2. Segundo punto\n3. Tercer punto"
def descargar_video(url, output_path):
"""Descarga un video y lo guarda localmente"""
try:
response = requests.get(url, stream=True, timeout=20)
response.raise_for_status()
with open(output_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=1024*1024): # 1MB chunks
if chunk:
f.write(chunk)
return True
except Exception as e:
logger.error(f"Error descargando video: {str(e)}")
return False
def crear_video(prompt, custom_script, voz_seleccionada, musica=None):
try:
# 1. Generar o usar guion
guion = custom_script if custom_script else generar_guion(prompt)
logger.info(f"Guion: {guion[:100]}...")
# 2. Generar voz
voz_archivo = "voz.mp3"
subprocess.run([
'edge-tts',
'--voice', voz_seleccionada,
'--text', guion,
'--write-media', voz_archivo
], check=True)
# 3. Buscar videos en Pexels
headers = {"Authorization": PEXELS_API_KEY}
response = requests.get(
f"https://api.pexels.com/videos/search?query={prompt[:50]}&per_page=3",
headers=headers,
timeout=15
)
videos_data = response.json().get("videos", [])
if not videos_data:
raise Exception("No se encontraron videos en Pexels")
# 4. Descargar y preparar clips de video
clips = []
for i, video in enumerate(videos_data[:3]):
# Seleccionar la mejor calidad de video disponible
video_files = sorted(
[vf for vf in video['video_files'] if vf.get('width')],
key=lambda x: x['width'],
reverse=True
)
if not video_files:
continue
video_url = video_files[0]['link']
temp_video_path = f"temp_video_{i}.mp4"
if descargar_video(video_url, temp_video_path):
clip = VideoFileClip(temp_video_path)
# Calcular duraci贸n proporcional
clip_duration = min(10, clip.duration) # M谩ximo 10 segundos por clip
clips.append(clip.subclip(0, clip_duration))
if not clips:
raise Exception("No se pudieron cargar videos v谩lidos")
# 5. Procesar audio
audio = AudioFileClip(voz_archivo)
total_duration = audio.duration
if musica:
musica_clip = AudioFileClip(musica.name)
if musica_clip.duration < total_duration:
# Crear loop si la m煤sica es m谩s corta
looped_music = musica_clip.loop(duration=total_duration)
else:
looped_music = musica_clip.subclip(0, total_duration)
audio = CompositeAudioClip([audio, looped_music.volumex(0.25)])
# 6. Crear video final
# Calcular duraci贸n por clip
clip_durations = [c.duration for c in clips]
total_clip_duration = sum(clip_durations)
scale_factor = total_duration / total_clip_duration if total_clip_duration > 0 else 1
# Ajustar velocidad de los clips para que coincidan con el audio
adjusted_clips = [c.fx(vfx.speedx, scale_factor) for c in clips]
final_clip = concatenate_videoclips(adjusted_clips, method="compose")
# Aplicar transici贸n suave entre clips
final_clip = final_clip.fx(vfx.fadein, 0.5).fx(vfx.fadeout, 0.5)
# Ajustar duraci贸n exacta
final_clip = final_clip.set_duration(total_duration).set_audio(audio)
# 7. Guardar video final
output_path = f"video_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
final_clip.write_videofile(
output_path,
codec="libx264",
audio_codec="aac",
threads=2,
preset='fast',
fps=24
)
return output_path
except Exception as e:
logger.error(f"ERROR: {str(e)}")
return None
finally:
# Limpieza de archivos temporales
if os.path.exists(voz_archivo):
os.remove(voz_archivo)
for i in range(3):
if os.path.exists(f"temp_video_{i}.mp4"):
os.remove(f"temp_video_{i}.mp4")
# Interfaz Gradio mejorada
with gr.Blocks(theme=gr.themes.Soft(), title="Generador de Videos Profesional") as app:
gr.Markdown("# 馃幀 GENERADOR DE VIDEOS AUTOM脕TICO")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### Configuraci贸n del Video")
prompt = gr.Textbox(label="Tema principal", placeholder="Ej: 'Lugares misteriosos de Espa帽a'")
custom_script = gr.TextArea(
label="Guion personalizado (opcional)",
placeholder="Pega aqu铆 tu propio guion...",
lines=5
)
voz = gr.Dropdown(
label="Selecciona una voz",
choices=VOICES,
value="es-ES-ElviraNeural",
interactive=True
)
musica = gr.File(
label="M煤sica de fondo (opcional)",
file_types=[".mp3", ".wav"],
type="filepath"
)
btn = gr.Button("馃殌 GENERAR VIDEO", variant="primary", size="lg")
with gr.Column(scale=2):
output = gr.Video(
label="Video Resultante",
format="mp4",
interactive=False,
elem_id="video-player"
)
gr.Examples(
examples=[
["Lugares hist贸ricos de Roma", "", "it-IT-ElsaNeural", None],
["Tecnolog铆as del futuro", "", "en-US-JennyNeural", None],
["Playas paradis铆acas del Caribe", "", "es-MX-DaliaNeural", None]
],
inputs=[prompt, custom_script, voz, musica],
label="Ejemplos para probar"
)
btn.click(
fn=crear_video,
inputs=[prompt, custom_script, voz, musica],
outputs=output
)
# CSS para mejorar la visualizaci贸n
app.css = """
#video-player {
max-width: 100%;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
"""
if __name__ == "__main__":
app.launch(server_name="0.0.0.0", server_port=7860) |