gnosticdev commited on
Commit
7c87717
verified
1 Parent(s): 30c3706

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -92
app.py CHANGED
@@ -8,67 +8,45 @@ import logging
8
  import re
9
  import torch
10
  from transformers import GPT2LMHeadModel, GPT2Tokenizer
11
- import warnings
12
 
13
- # Configuraci贸n inicial
14
  logging.basicConfig(level=logging.INFO)
15
  logger = logging.getLogger(__name__)
16
 
17
- # Suprimir warnings no deseados
18
- warnings.filterwarnings("ignore", category=UserWarning)
19
- warnings.filterwarnings("ignore", category=DeprecationWarning)
20
 
21
- PEXELS_API_KEY = os.getenv("PEXELS_API_KEY")
 
22
 
23
- # Lista de voces v谩lidas
24
- VOICES = [
25
- "es-MX-DaliaNeural", "es-ES-ElviraNeural", "es-AR-ElenaNeural",
26
- "es-MX-JorgeNeural", "es-ES-AlvaroNeural", "es-AR-TomasNeural",
27
- "en-US-JennyNeural", "fr-FR-DeniseNeural", "de-DE-KatjaNeural"
28
- ]
29
-
30
- # Cargar modelo GPT-2 con configuraci贸n optimizada
31
- try:
32
- tokenizer = GPT2Tokenizer.from_pretrained("datificate/gpt2-small-spanish")
33
- model = GPT2LMHeadModel.from_pretrained("datificate/gpt2-small-spanish")
34
- logger.info("Modelo GPT-2 cargado correctamente")
35
- except Exception as e:
36
- logger.error(f"Error cargando modelo: {str(e)}")
37
- model = None
38
- tokenizer = None
39
 
40
  def generar_texto(tema):
41
- """Genera texto largo sobre el tema sin estructuras predefinidas"""
42
- if model is None or tokenizer is None:
43
- return f"Contenido sobre {tema}. " * 50
44
-
45
  try:
46
- # Prompt directo y simple
47
- prompt = f"Describe detalladamente {tema}"
48
 
49
- # Codificar el texto con truncamiento
50
- inputs = tokenizer(prompt, return_tensors="pt", max_length=512, truncation=True)
51
-
52
- # Generar texto con par谩metros optimizados
53
  outputs = model.generate(
54
  inputs.input_ids,
55
  max_length=800,
56
  do_sample=True,
57
  temperature=0.7,
58
- top_k=40,
59
- num_return_sequences=1,
60
  pad_token_id=tokenizer.eos_token_id
61
  )
62
 
63
  texto = tokenizer.decode(outputs[0], skip_special_tokens=True)
64
  return re.sub(r'\s+', ' ', texto).strip()
65
-
66
  except Exception as e:
67
- logger.error(f"Error generando texto: {str(e)}")
68
- return f"Texto generado sobre {tema}. " * 50
69
 
70
- def obtener_videos(tema):
71
- """Obtiene videos de Pexels con manejo robusto de errores"""
72
  try:
73
  headers = {"Authorization": PEXELS_API_KEY}
74
  response = requests.get(
@@ -78,64 +56,65 @@ def obtener_videos(tema):
78
  )
79
  return response.json().get("videos", [])[:3]
80
  except Exception as e:
81
- logger.error(f"Error obteniendo videos: {str(e)}")
82
  return []
83
 
84
- def crear_video(prompt, voz_seleccionada):
 
85
  try:
86
  # 1. Generar texto
87
- texto = generar_texto(prompt)
88
- logger.info(f"Texto generado: {len(texto)} caracteres")
89
 
90
- # 2. Crear narraci贸n de voz
91
- voz_file = "narracion.mp3"
92
  subprocess.run([
93
  'edge-tts',
94
  '--voice', voz_seleccionada,
95
  '--text', texto,
96
- '--write-media', voz_file
97
  ], check=True)
98
 
99
- audio = AudioFileClip(voz_file)
100
- duracion = audio.duration
 
101
 
102
- # 3. Obtener y procesar videos
103
- videos = obtener_videos(prompt) or obtener_videos("nature")
104
  clips = []
105
 
106
- for i, video in enumerate(videos):
107
  try:
108
- # Seleccionar video de mayor calidad
109
- video_file = max(video['video_files'], key=lambda x: x.get('width', 0))
110
- temp_file = f"temp_{i}.mp4"
111
 
112
- # Descargar video
113
- with requests.get(video_file['link'], stream=True) as r:
 
114
  r.raise_for_status()
115
  with open(temp_file, 'wb') as f:
116
  for chunk in r.iter_content(chunk_size=8192):
117
  f.write(chunk)
118
 
119
- # Procesar clip
120
  clip = VideoFileClip(temp_file)
121
- clip_duration = min(duracion/len(videos), clip.duration)
122
- clips.append(clip.subclip(0, clip_duration))
123
 
124
  except Exception as e:
125
- logger.error(f"Error procesando video {i}: {str(e)}")
126
 
127
- # 4. Crear video final
128
  if not clips:
129
- final_clip = ColorClip((1280, 720), (0, 0, 0), duration=duracion)
130
  else:
131
- final_clip = concatenate_videoclips(clips).set_duration(duracion)
132
 
133
- final_clip = final_clip.set_audio(audio)
134
 
135
- # 5. Exportar video
136
- output_file = f"video_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
137
- final_clip.write_videofile(
138
- output_file,
139
  fps=24,
140
  codec="libx264",
141
  audio_codec="aac",
@@ -143,40 +122,37 @@ def crear_video(prompt, voz_seleccionada):
143
  preset='fast'
144
  )
145
 
146
- return output_file
147
-
148
  except Exception as e:
149
- logger.error(f"Error cr铆tico: {str(e)}")
150
  return None
 
151
  finally:
152
  # Limpieza de archivos temporales
153
- for f in [voz_file, *[f"temp_{i}.mp4" for i in range(3)]]:
154
- if os.path.exists(f):
155
- try:
156
- os.remove(f)
157
- except:
158
- pass
159
 
160
- # Interfaz minimalista
161
  with gr.Blocks() as app:
 
 
162
  with gr.Row():
163
- with gr.Column():
164
- tema = gr.Textbox(label="Tema del video")
165
- voz = gr.Dropdown(label="Voz", choices=VOICES, value=VOICES[0])
166
- btn = gr.Button("Generar Video")
167
-
168
- with gr.Column():
169
- video = gr.Video(label="Resultado")
170
-
171
  btn.click(
172
  fn=crear_video,
173
  inputs=[tema, voz],
174
- outputs=video
175
  )
176
 
177
  if __name__ == "__main__":
178
- app.launch(
179
- server_name="0.0.0.0",
180
- server_port=7860,
181
- share=False
182
- )
 
8
  import re
9
  import torch
10
  from transformers import GPT2LMHeadModel, GPT2Tokenizer
 
11
 
12
+ # Configuraci贸n b谩sica
13
  logging.basicConfig(level=logging.INFO)
14
  logger = logging.getLogger(__name__)
15
 
16
+ # Configuraci贸n de entorno (usa tu propia API key de Pexels)
17
+ PEXELS_API_KEY = os.getenv("PEXELS_API_KEY") or "TU_API_KEY_AQUI"
 
18
 
19
+ # Voces disponibles (Edge-TTS)
20
+ VOICES = ["es-MX-DaliaNeural", "es-ES-ElviraNeural", "en-US-JennyNeural"]
21
 
22
+ # Carga el modelo GPT-2 en espa帽ol (ligero y r谩pido)
23
+ tokenizer = GPT2Tokenizer.from_pretrained("datificate/gpt2-small-spanish")
24
+ model = GPT2LMHeadModel.from_pretrained("datificate/gpt2-small-spanish")
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  def generar_texto(tema):
27
+ """Genera un texto largo y natural sobre el tema (sin estructuras forzadas)."""
 
 
 
28
  try:
29
+ prompt = f"Habla extensamente sobre {tema} en un tono natural y detallado:"
30
+ inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=512)
31
 
 
 
 
 
32
  outputs = model.generate(
33
  inputs.input_ids,
34
  max_length=800,
35
  do_sample=True,
36
  temperature=0.7,
37
+ top_k=50,
 
38
  pad_token_id=tokenizer.eos_token_id
39
  )
40
 
41
  texto = tokenizer.decode(outputs[0], skip_special_tokens=True)
42
  return re.sub(r'\s+', ' ', texto).strip()
43
+
44
  except Exception as e:
45
+ logger.error(f"Error generando texto: {e}")
46
+ return f"Contenido generado sobre {tema}."
47
 
48
+ def buscar_videos(tema):
49
+ """Busca videos en Pexels y devuelve los 3 m谩s relevantes."""
50
  try:
51
  headers = {"Authorization": PEXELS_API_KEY}
52
  response = requests.get(
 
56
  )
57
  return response.json().get("videos", [])[:3]
58
  except Exception as e:
59
+ logger.error(f"Error buscando videos: {e}")
60
  return []
61
 
62
+ def crear_video(tema, voz_seleccionada):
63
+ """Genera el video final con voz y clips de video."""
64
  try:
65
  # 1. Generar texto
66
+ texto = generar_texto(tema)
 
67
 
68
+ # 2. Convertir texto a voz (Edge-TTS)
69
+ voz_archivo = "narracion.mp3"
70
  subprocess.run([
71
  'edge-tts',
72
  '--voice', voz_seleccionada,
73
  '--text', texto,
74
+ '--write-media', voz_archivo
75
  ], check=True)
76
 
77
+ # 3. Procesar audio
78
+ audio = AudioFileClip(voz_archivo)
79
+ duracion_total = audio.duration
80
 
81
+ # 4. Buscar y descargar videos
82
+ videos = buscar_videos(tema) or buscar_videos("nature")
83
  clips = []
84
 
85
+ for i, video in enumerate(videos[:3]): # M谩ximo 3 videos
86
  try:
87
+ mejor_calidad = max(video['video_files'], key=lambda x: x.get('width', 0))
88
+ url_video = mejor_calidad['link']
 
89
 
90
+ # Descargar video temporal
91
+ temp_file = f"temp_video_{i}.mp4"
92
+ with requests.get(url_video, stream=True) as r:
93
  r.raise_for_status()
94
  with open(temp_file, 'wb') as f:
95
  for chunk in r.iter_content(chunk_size=8192):
96
  f.write(chunk)
97
 
98
+ # Ajustar duraci贸n del clip
99
  clip = VideoFileClip(temp_file)
100
+ duracion_clip = min(duracion_total / len(videos), clip.duration)
101
+ clips.append(clip.subclip(0, duracion_clip))
102
 
103
  except Exception as e:
104
+ logger.error(f"Error procesando video {i}: {e}")
105
 
106
+ # 5. Combinar clips (o usar fondo negro si no hay videos)
107
  if not clips:
108
+ video_final = ColorClip((1280, 720), (0, 0, 0), duration=duracion_total)
109
  else:
110
+ video_final = concatenate_videoclips(clips, method="compose")
111
 
112
+ video_final = video_final.set_audio(audio)
113
 
114
+ # 6. Exportar video
115
+ nombre_archivo = f"video_final_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
116
+ video_final.write_videofile(
117
+ nombre_archivo,
118
  fps=24,
119
  codec="libx264",
120
  audio_codec="aac",
 
122
  preset='fast'
123
  )
124
 
125
+ return nombre_archivo
126
+
127
  except Exception as e:
128
+ logger.error(f"Error cr铆tico: {e}")
129
  return None
130
+
131
  finally:
132
  # Limpieza de archivos temporales
133
+ if os.path.exists(voz_archivo):
134
+ os.remove(voz_archivo)
135
+ for i in range(3):
136
+ temp_file = f"temp_video_{i}.mp4"
137
+ if os.path.exists(temp_file):
138
+ os.remove(temp_file)
139
 
140
+ # Interfaz de Gradio (sencilla y funcional)
141
  with gr.Blocks() as app:
142
+ gr.Markdown("# 馃幀 Generador Autom谩tico de Videos")
143
+
144
  with gr.Row():
145
+ tema = gr.Textbox(label="Tema del video", placeholder="Ej: 'Historia de la inteligencia artificial'")
146
+ voz = gr.Dropdown(label="Voz", choices=VOICES, value=VOICES[0])
147
+ btn = gr.Button("Generar Video", variant="primary")
148
+
149
+ salida = gr.Video(label="Resultado")
150
+
 
 
151
  btn.click(
152
  fn=crear_video,
153
  inputs=[tema, voz],
154
+ outputs=salida
155
  )
156
 
157
  if __name__ == "__main__":
158
+ app.launch(server_name="0.0.0.0", server_port=7860)