Spaces:
Running
Running
File size: 7,568 Bytes
43fcbe8 d68572a 38ff849 8337d0b fa691a5 d68572a 07b3b3d 38ff849 53ae22b d68572a 3e716f3 d68572a fa691a5 53ae22b c1f9283 d68572a 38ff849 fa691a5 38ff849 d68572a 77ffd33 d68572a 38ff849 d68572a 07b3b3d d68572a 53ae22b d68572a 53ae22b d68572a 9b819da d68572a 07b3b3d d68572a fa691a5 d68572a c7b9a72 d68572a 9b819da d68572a 3e716f3 d68572a 3e716f3 9b819da fa691a5 d68572a 38ff849 d68572a 9b819da 38ff849 3e716f3 38ff849 d68572a 38ff849 fa201eb 38ff849 fa201eb 9b819da 720c3d5 07b3b3d d68572a 07b3b3d d68572a c9d2e08 d68572a d7f3a60 d68572a 8337d0b d68572a 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 |
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
import nltk
from nltk.tokenize import sent_tokenize
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
import re
# Configuraci贸n inicial
nltk.download('punkt', quiet=True)
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",
"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="gpt2", # Modelo m谩s flexible
device=0 if torch.cuda.is_available() else -1
)
except:
logger.warning("No se pudo cargar el modelo de generaci贸n de texto")
script_generator = None
def generar_guion(prompt):
"""Genera un guion natural y extenso basado en el prompt"""
if script_generator:
try:
result = script_generator(
f"Genera un texto detallado y bien estructurado sobre '{prompt}' para un video de YouTube:",
max_length=500, # Texto m谩s largo
temperature=0.9, # M谩s creatividad
num_return_sequences=1
)
guion = result[0]['generated_text']
# Limpiar el guion generado
guion = re.sub(r'<.*?>', '', guion)
guion = re.sub(r'\n+', '\n', guion)
return guion.strip()
except Exception as e:
logger.error(f"Error generando guion: {str(e)}")
# Fallback natural
return f"En este video exploraremos en profundidad el tema de {prompt}. " \
"Analizaremos diversos aspectos y perspectivas para ofrecer una visi贸n completa. " \
"Veremos c贸mo este tema se relaciona con nuestra vida cotidiana y su impacto en la sociedad actual."
def extraer_palabras_clave(texto, n=7):
"""Extrae palabras clave relevantes usando TF-IDF"""
# Preprocesamiento del texto
texto = re.sub(r'[^\w\s]', '', texto.lower())
# Tokenizar en oraciones
oraciones = sent_tokenize(texto)
# Crear matriz TF-IDF
vectorizer = TfidfVectorizer(
stop_words=['el', 'la', 'los', 'las', 'de', 'en', 'y', 'que', 'un', 'una', 'con', 'para'],
max_features=500
)
X = vectorizer.fit_transform(oraciones)
# Obtener palabras con mayor puntuaci贸n TF-IDF
suma_scores = np.asarray(X.sum(axis=0)).ravel()
indices = np.argsort(suma_scores)[::-1][:n]
palabras = vectorizer.get_feature_names_out()
return [palabras[i] for i in indices]
def buscar_videos_pexels(palabras_clave, num_videos=3):
"""Busca videos en Pexels usando palabras clave con enfoque en relevancia"""
try:
headers = {"Authorization": PEXELS_API_KEY}
query = "+".join(palabras_clave[:3]) # Usar las 3 palabras m谩s relevantes
logger.info(f"Buscando videos con palabras clave: {query}")
response = requests.get(
f"https://api.pexels.com/videos/search?query={query}&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('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=25) 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 natural
guion = custom_script if custom_script else generar_guion(prompt)
logger.info(f"Guion generado ({len(guion)} caracteres)")
# 2. Extraer palabras clave del guion completo
palabras_clave = extraer_palabras_clave(guion)
logger.info(f"Palabras clave extra铆das: {', '.join(palabras_clave)}")
# 3. Buscar videos relevantes usando IA
videos_data = buscar_videos_pexels(palabras_clave)
if not videos_data:
raise Exception("No se encontraron videos relevantes. Usando backup...")
# 4. Generar narraci贸n
voz_archivo = "voz.mp3"
subprocess.run([
'edge-tts',
'--voice', voz_seleccionada,
'--text', guion,
'--write-media', voz_archivo
], check=True)
# 5. Procesar audio
audio = AudioFileClip(voz_archivo)
duracion_total = audio.duration
# 6. Descargar y preparar videos
clips = []
for i, video in enumerate(videos_data):
# Seleccionar la mejor calidad
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)
# Ajustar duraci贸n proporcional
duracion_clip = min(duracion_total / len(videos_data), clip.duration)
clips.append(clip.subclip(0, duracion_clip))
# 7. Combinar videos
video_final = concatenate_videoclips(clips)
video_final = video_final.set_audio(audio)
# 8. Exportar
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=2
)
return output_path
except Exception as e:
logger.error(f"ERROR: {str(e)}")
return None
finally:
# Limpieza
if os.path.exists(voz_archivo):
os.remove(voz_archivo)
for i in range(3):
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():
prompt = gr.Textbox(label="Tema del video", placeholder="Ej: Exploraci贸n espacial")
voz = gr.Dropdown(label="Voz Narradora", choices=VOICES, value=VOICES[0])
btn = gr.Button("Generar Video", variant="primary")
output = gr.Video(label="Resultado", format="mp4")
btn.click(
fn=crear_video,
inputs=[prompt, gr.Textbox(visible=False), voz, gr.File(visible=False)],
outputs=output
)
if __name__ == "__main__":
app.launch(server_name="0.0.0.0", server_port=7860) |