gnosticdev commited on
Commit
373b785
verified
1 Parent(s): bff2060

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -10
app.py CHANGED
@@ -36,7 +36,6 @@ os.environ["GRADIO_SERVER_TIMEOUT"] = "3800" # 30 minutos en segundos
36
  # ------------------- Configuraci贸n & Globals -------------------
37
  logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
38
  logger = logging.getLogger(__name__)
39
-
40
  PEXELS_API_KEY = os.getenv("PEXELS_API_KEY")
41
  if not PEXELS_API_KEY:
42
  logger.warning("PEXELS_API_KEY no definido. Los videos no funcionar谩n.")
@@ -271,8 +270,18 @@ def loop_audio_to_duration(audio_clip: AudioFileClip, target_duration: float) ->
271
  return audio_clip
272
 
273
  def create_video(script_text: str, generate_script: bool, music_path: str | None, task_id: str) -> str:
274
- """Funci贸n principal para crear el video"""
275
  temp_dir = tempfile.mkdtemp()
 
 
 
 
 
 
 
 
 
 
 
276
 
277
  try:
278
  # Paso 1: Generar o usar gui贸n
@@ -330,14 +339,20 @@ def create_video(script_text: str, generate_script: bool, music_path: str | None
330
  video_clips = []
331
 
332
  for path in video_paths:
 
333
  try:
334
  clip = VideoFileClip(path)
335
  # Tomar m谩ximo 8 segundos de cada clip
336
  duration = min(8, clip.duration)
337
- video_clips.append(clip.subclip(0, duration))
 
 
 
338
  except Exception as e:
339
  logger.error(f"Error procesando video {path}: {e}")
340
- continue
 
 
341
 
342
  if not video_clips:
343
  raise RuntimeError("No se pudieron procesar los videos")
@@ -345,12 +360,22 @@ def create_video(script_text: str, generate_script: bool, music_path: str | None
345
  # Concatenar videos
346
  base_video = concatenate_videoclips(video_clips, method="chain")
347
 
348
- # Extender video si es m谩s corto que el audio
349
  if base_video.duration < video_duration:
 
350
  loops_needed = math.ceil(video_duration / base_video.duration)
351
- base_video = concatenate_videoclips([base_video] * loops_needed)
 
 
 
 
 
 
 
 
 
352
 
353
- # Cortar al tiempo exacto del audio
354
  base_video = base_video.subclip(0, video_duration)
355
 
356
  # Paso 5: Componer audio final
@@ -366,6 +391,11 @@ def create_video(script_text: str, generate_script: bool, music_path: str | None
366
  else:
367
  final_audio = voice_clip
368
 
 
 
 
 
 
369
 
370
  # Paso 7: Renderizar video final
371
  update_task_progress(task_id, "Paso 7/7: Renderizando video final...")
@@ -374,10 +404,12 @@ def create_video(script_text: str, generate_script: bool, music_path: str | None
374
  output_path = os.path.join(RESULTS_DIR, f"video_{task_id}.mp4")
375
  final_video.write_videofile(
376
  output_path,
377
- fps=15,
378
  codec="libx264",
379
- audio_codec="mp3",
380
- threads=2,
 
 
381
  logger=None,
382
  verbose=False
383
  )
 
36
  # ------------------- Configuraci贸n & Globals -------------------
37
  logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
38
  logger = logging.getLogger(__name__)
 
39
  PEXELS_API_KEY = os.getenv("PEXELS_API_KEY")
40
  if not PEXELS_API_KEY:
41
  logger.warning("PEXELS_API_KEY no definido. Los videos no funcionar谩n.")
 
270
  return audio_clip
271
 
272
  def create_video(script_text: str, generate_script: bool, music_path: str | None, task_id: str) -> str:
 
273
  temp_dir = tempfile.mkdtemp()
274
+ # Constantes para normalizaci贸n
275
+ TARGET_FPS = 24
276
+ TARGET_RESOLUTION = (1280, 720) # (ancho, alto)
277
+
278
+ def normalize_clip(clip):
279
+ """Normaliza un clip de video a resoluci贸n y FPS est谩ndar"""
280
+ if clip.size != TARGET_RESOLUTION:
281
+ clip = clip.resize(TARGET_RESOLUTION)
282
+ if clip.fps != TARGET_FPS:
283
+ clip = clip.set_fps(TARGET_FPS)
284
+ return clip
285
 
286
  try:
287
  # Paso 1: Generar o usar gui贸n
 
339
  video_clips = []
340
 
341
  for path in video_paths:
342
+ clip = None
343
  try:
344
  clip = VideoFileClip(path)
345
  # Tomar m谩ximo 8 segundos de cada clip
346
  duration = min(8, clip.duration)
347
+ processed_clip = clip.subclip(0, duration)
348
+ # Normalizar el clip (resoluci贸n y FPS)
349
+ processed_clip = normalize_clip(processed_clip)
350
+ video_clips.append(processed_clip)
351
  except Exception as e:
352
  logger.error(f"Error procesando video {path}: {e}")
353
+ finally:
354
+ if clip is not None:
355
+ clip.close()
356
 
357
  if not video_clips:
358
  raise RuntimeError("No se pudieron procesar los videos")
 
360
  # Concatenar videos
361
  base_video = concatenate_videoclips(video_clips, method="chain")
362
 
363
+ # Extender video si es m谩s corto que el audio con transiciones suaves
364
  if base_video.duration < video_duration:
365
+ fade_duration = 0.5 # segundos de fundido
366
  loops_needed = math.ceil(video_duration / base_video.duration)
367
+
368
+ # Crear una lista de clips para el loop
369
+ looped_clips = [base_video]
370
+ for _ in range(loops_needed - 1):
371
+ # Crear un clip con fundido de entrada para la transici贸n
372
+ fade_in_clip = base_video.crossfadein(fade_duration)
373
+ looped_clips.append(fade_in_clip)
374
+ looped_clips.append(base_video)
375
+
376
+ base_video = concatenate_videoclips(looped_clips)
377
 
378
+ # Asegurar que el video tenga la duraci贸n exacta del audio
379
  base_video = base_video.subclip(0, video_duration)
380
 
381
  # Paso 5: Componer audio final
 
391
  else:
392
  final_audio = voice_clip
393
 
394
+ # Paso 6: Agregar subt铆tulos
395
+ update_task_progress(task_id, "Paso 6/7: Agregando subt铆tulos...")
396
+ subtitle_clips = create_subtitle_clips(script, base_video.w, base_video.h, video_duration)
397
+ if subtitle_clips:
398
+ base_video = CompositeVideoClip([base_video] + subtitle_clips)
399
 
400
  # Paso 7: Renderizar video final
401
  update_task_progress(task_id, "Paso 7/7: Renderizando video final...")
 
404
  output_path = os.path.join(RESULTS_DIR, f"video_{task_id}.mp4")
405
  final_video.write_videofile(
406
  output_path,
407
+ fps=TARGET_FPS,
408
  codec="libx264",
409
+ audio_codec="aac", # Mejor calidad de audio
410
+ bitrate="8000k", # Controlar calidad de video
411
+ threads=4, # Mejor uso de CPU
412
+ preset="slow", # Mejor compresi贸n
413
  logger=None,
414
  verbose=False
415
  )