Spaces:
Sleeping
Sleeping
File size: 7,812 Bytes
43fcbe8 d68572a 38ff849 8337d0b fa691a5 d68572a 38ff849 d68572a 9143db2 fa691a5 53ae22b d68572a 38ff849 fa691a5 38ff849 d68572a 9143db2 d68572a 9143db2 d68572a 77ffd33 9143db2 d68572a 9143db2 d68572a 9143db2 d68572a 9143db2 38ff849 9143db2 07b3b3d d68572a 53ae22b 9143db2 53ae22b d68572a 9143db2 d68572a 9b819da d68572a 9143db2 d68572a 9143db2 d68572a 07b3b3d d68572a fa691a5 d68572a c7b9a72 9143db2 d68572a 9143db2 3e716f3 d68572a 9143db2 3e716f3 9b819da fa691a5 9143db2 d68572a 9143db2 d68572a 9143db2 38ff849 9143db2 d68572a 9143db2 9b819da 38ff849 3e716f3 38ff849 d68572a 9143db2 38ff849 fa201eb 9143db2 fa201eb 38ff849 fa201eb 9b819da 720c3d5 07b3b3d 9143db2 07b3b3d 9143db2 d68572a c9d2e08 d68572a 9143db2 d7f3a60 9143db2 d68572a 8337d0b d68572a 9143db2 9b819da 9e5ee0a d7f3a60 07b3b3d 9b819da |
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 |
import os
import subprocess
import requests
import gradio as gr
from moviepy.editor import *
from datetime import datetime
import logging
import re
import torch
from transformers import GPT2LMHeadModel, GPT2Tokenizer
# Configuración inicial
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
PEXELS_API_KEY = os.getenv("PEXELS_API_KEY")
# Lista de voces válidas
VOICES = [
"es-MX-DaliaNeural", "es-ES-ElviraNeural", "es-AR-ElenaNeural",
"es-MX-JorgeNeural", "es-ES-AlvaroNeural", "es-AR-TomasNeural",
"en-US-JennyNeural", "fr-FR-DeniseNeural", "de-DE-KatjaNeural",
"it-IT-ElsaNeural", "pt-BR-FranciscaNeural", "ja-JP-NanamiNeural",
"en-GB-SoniaNeural", "es-CL-CatalinaNeural", "es-CO-GonzaloNeural"
]
# Cargar modelo y tokenizador de GPT-2 en español
try:
tokenizer = GPT2Tokenizer.from_pretrained("datificate/gpt2-small-spanish")
model = GPT2LMHeadModel.from_pretrained("datificate/gpt2-small-spanish")
logger.info("Modelo GPT-2 en español cargado correctamente")
except Exception as e:
logger.error(f"Error cargando el modelo: {str(e)}")
model = None
tokenizer = None
def generar_guion_largo(tema, custom_script=None):
"""Genera un texto largo sobre el tema usando GPT-2"""
if custom_script:
return custom_script
if model is None or tokenizer is None:
return f"Texto generado automáticamente sobre {tema}. " * 50
try:
# Prompt directo como solicitaste
prompt = f"Escribe un texto largo y detallado sobre {tema}"
inputs = tokenizer(prompt, return_tensors="pt", max_length=512, truncation=True)
# Generar texto
outputs = model.generate(
inputs.input_ids,
max_length=800,
temperature=0.9,
top_k=50,
top_p=0.95,
num_return_sequences=1,
pad_token_id=tokenizer.eos_token_id
)
guion = tokenizer.decode(outputs[0], skip_special_tokens=True)
# Limpiar texto
guion = re.sub(r'<.*?>', '', guion)
guion = re.sub(r'\n+', '\n', guion)
logger.info(f"Guion generado: {len(guion)} caracteres")
return guion
except Exception as e:
logger.error(f"Error generando guion: {str(e)}")
return f"Texto generado automáticamente sobre {tema}. " * 50
def buscar_videos_pexels(tema, num_videos=4):
"""Busca videos en Pexels usando el tema directamente"""
try:
headers = {"Authorization": PEXELS_API_KEY}
logger.info(f"Buscando videos para: {tema}")
response = requests.get(
f"https://api.pexels.com/videos/search?query={tema}&per_page={num_videos}",
headers=headers,
timeout=15
)
videos = response.json().get("videos", [])
# Filtrar videos de alta calidad
return sorted(
videos,
key=lambda x: (x.get('width', 0) * x.get('height', 0), x.get('duration', 0)),
reverse=True
)[:num_videos]
except Exception as e:
logger.error(f"Error buscando videos: {str(e)}")
return []
def descargar_video(url, output_path):
"""Descarga un video de manera eficiente"""
try:
with requests.get(url, stream=True, timeout=30) as r:
r.raise_for_status()
with open(output_path, 'wb') as f:
for chunk in r.iter_content(chunk_size=8192):
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 guion largo
guion = generar_guion_largo(prompt, custom_script)
# 2. Generar narración
voz_archivo = "voz.mp3"
subprocess.run([
'edge-tts',
'--voice', voz_seleccionada,
'--text', guion,
'--write-media', voz_archivo
], check=True)
# 3. Procesar audio principal
audio = AudioFileClip(voz_archivo)
duracion_total = audio.duration
# 4. Buscar videos relevantes
videos_data = buscar_videos_pexels(prompt)
if not videos_data:
logger.warning("No se encontraron videos. Usando videos genéricos...")
videos_data = buscar_videos_pexels("nature")
# 5. Descargar y preparar videos
clips = []
for i, video in enumerate(videos_data):
try:
# Seleccionar la mejor calidad disponible
video_file = max(
video['video_files'],
key=lambda x: x.get('width', 0) * x.get('height', 0)
)
video_url = video_file['link']
temp_path = f"temp_video_{i}.mp4"
if descargar_video(video_url, temp_path):
clip = VideoFileClip(temp_path)
# Calcular duración proporcional para cada clip
duracion_clip = duracion_total / len(videos_data)
# Ajustar clip a la duración requerida
if clip.duration < duracion_clip:
clip = clip.loop(duration=duracion_clip)
else:
clip = clip.subclip(0, duracion_clip)
clips.append(clip)
except Exception as e:
logger.error(f"Error procesando video {i}: {str(e)}")
if not clips:
raise Exception("No se pudieron cargar videos válidos")
# 6. Combinar videos
video_final = concatenate_videoclips(clips)
video_final = video_final.set_audio(audio)
# 7. Exportar video final
output_path = f"video_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
video_final.write_videofile(
output_path,
fps=24,
codec="libx264",
audio_codec="aac",
threads=4,
preset='fast'
)
logger.info(f"Video generado exitosamente: {output_path}")
return output_path
except Exception as e:
logger.error(f"ERROR: {str(e)}")
return None
finally:
# Limpieza garantizada
if os.path.exists(voz_archivo):
os.remove(voz_archivo)
for i in range(5):
temp_file = f"temp_video_{i}.mp4"
if os.path.exists(temp_file):
os.remove(temp_file)
# Interfaz simplificada y funcional
with gr.Blocks(title="Generador de Videos") as app:
gr.Markdown("# 🎬 GENERADOR AUTOMÁTICO DE VIDEOS")
with gr.Row():
with gr.Column():
prompt = gr.Textbox(label="Tema del video", placeholder="Ej: 'La historia de la inteligencia artificial'")
custom_script = gr.TextArea(
label="Guion personalizado (opcional)",
placeholder="Pega tu guion completo aquí...",
lines=5
)
voz = gr.Dropdown(label="Voz Narradora", choices=VOICES, value=VOICES[0])
musica = gr.File(label="Música de fondo (opcional)", file_types=["audio"])
btn = gr.Button("Generar Video", variant="primary")
with gr.Column():
output = gr.Video(label="Video Resultado", format="mp4")
btn.click(
fn=crear_video,
inputs=[prompt, custom_script, voz, musica],
outputs=output
)
if __name__ == "__main__":
app.launch(server_name="0.0.0.0", server_port=7860) |