gnosticdev commited on
Commit
02e97a3
·
verified ·
1 Parent(s): 94b8ea9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -16
app.py CHANGED
@@ -3,6 +3,8 @@ import tempfile
3
  import logging
4
  import os
5
  import asyncio
 
 
6
  from moviepy.editor import (
7
  VideoFileClip, AudioFileClip, ImageClip,
8
  concatenate_videoclips, CompositeVideoClip, CompositeAudioClip
@@ -21,6 +23,7 @@ MUSIC_BG = "musicafondo.mp3"
21
  FX_SOUND = "fxsound.mp3"
22
  WATERMARK = "watermark.png"
23
  EJEMPLO_VIDEO = "ejemplo.mp4" # Video de ejemplo en el root
 
24
 
25
  # Validar existencia de archivos obligatorios
26
  for file in [INTRO_VIDEO, OUTRO_VIDEO, MUSIC_BG, FX_SOUND, WATERMARK, EJEMPLO_VIDEO]:
@@ -28,6 +31,20 @@ for file in [INTRO_VIDEO, OUTRO_VIDEO, MUSIC_BG, FX_SOUND, WATERMARK, EJEMPLO_VI
28
  logging.error(f"Falta archivo necesario: {file}")
29
  raise FileNotFoundError(f"Falta archivo necesario: {file}")
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  def cortar_video(video_path, metodo="inteligente", duracion=10):
32
  """Corta el video en clips según el método especificado."""
33
  try:
@@ -40,11 +57,11 @@ def cortar_video(video_path, metodo="inteligente", duracion=10):
40
  logging.info(f"Video cortado en {len(clips)} clips manuales.")
41
  return clips
42
 
43
- # Método "inteligente" simplificado (cortes cada 5 segundos como fallback)
44
  clips = []
45
  ultimo_corte = 0
46
  for i in range(1, math.ceil(video.duration)):
47
- if i % 5 == 0: # Corte cada 5 segundos (puedes mejorar esto con VAD más adelante)
48
  clips.append(video.subclip(ultimo_corte, i))
49
  ultimo_corte = i
50
  if ultimo_corte < video.duration:
@@ -57,12 +74,14 @@ def cortar_video(video_path, metodo="inteligente", duracion=10):
57
 
58
  async def procesar_audio(texto, voz, duracion_total, duracion_intro, duracion_video_editado):
59
  """Genera el TTS y mezcla con la música de fondo."""
 
60
  try:
61
  logging.info("Generando TTS y mezclando audio...")
62
  communicate = edge_tts.Communicate(texto, voz)
63
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
64
  await communicate.save(tmp.name)
65
  tts_audio = AudioFileClip(tmp.name)
 
66
 
67
  # Ajustar duración del TTS
68
  if tts_audio.duration > duracion_video_editado:
@@ -77,6 +96,7 @@ async def procesar_audio(texto, voz, duracion_total, duracion_intro, duracion_vi
77
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
78
  bg_music.export(tmp.name, format="mp3")
79
  bg_audio = AudioFileClip(tmp.name).volumex(0.10)
 
80
 
81
  # Combinar audios
82
  audio_final = CompositeAudioClip([
@@ -88,6 +108,15 @@ async def procesar_audio(texto, voz, duracion_total, duracion_intro, duracion_vi
88
  except Exception as e:
89
  logging.error(f"Error al procesar audio: {e}")
90
  raise
 
 
 
 
 
 
 
 
 
91
 
92
  def agregar_transiciones(clips):
93
  """Agrega transiciones con watermark y sonido FX entre clips."""
@@ -112,7 +141,6 @@ def agregar_transiciones(clips):
112
 
113
  async def procesar_video(video_input, texto_tts, voz_seleccionada, metodo_corte, duracion_corte):
114
  """Procesa el video completo con intro, cortes, TTS y outro."""
115
- temp_files = []
116
  try:
117
  logging.info("Iniciando procesamiento de video...")
118
  # Cortar y editar video
@@ -136,22 +164,18 @@ async def procesar_video(video_input, texto_tts, voz_seleccionada, metodo_corte,
136
 
137
  # Renderizar video final
138
  video_final = video_final.set_audio(audio_final)
139
- with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp:
140
- video_final.write_videofile(tmp.name, codec="libx264", fps=24)
141
- temp_files.append(tmp.name)
142
- logging.info("Video procesado y guardado temporalmente.")
143
- return tmp.name
 
 
 
 
144
  except Exception as e:
145
  logging.error(f"Error durante el procesamiento: {e}")
146
  raise
147
- finally:
148
- for file in temp_files:
149
- try:
150
- if os.path.exists(file):
151
- os.remove(file)
152
- logging.info(f"Archivo temporal eliminado: {file}")
153
- except Exception as e:
154
- logging.warning(f"No se pudo eliminar el archivo temporal {file}: {e}")
155
 
156
  # Interfaz Gradio con ejemplo de uso
157
  with gr.Blocks() as demo:
 
3
  import logging
4
  import os
5
  import asyncio
6
+ import time
7
+ from threading import Timer
8
  from moviepy.editor import (
9
  VideoFileClip, AudioFileClip, ImageClip,
10
  concatenate_videoclips, CompositeVideoClip, CompositeAudioClip
 
23
  FX_SOUND = "fxsound.mp3"
24
  WATERMARK = "watermark.png"
25
  EJEMPLO_VIDEO = "ejemplo.mp4" # Video de ejemplo en el root
26
+ OUTPUT_DIR = "output_videos" # Carpeta para videos finales
27
 
28
  # Validar existencia de archivos obligatorios
29
  for file in [INTRO_VIDEO, OUTRO_VIDEO, MUSIC_BG, FX_SOUND, WATERMARK, EJEMPLO_VIDEO]:
 
31
  logging.error(f"Falta archivo necesario: {file}")
32
  raise FileNotFoundError(f"Falta archivo necesario: {file}")
33
 
34
+ # Crear carpeta de salida si no existe
35
+ os.makedirs(OUTPUT_DIR, exist_ok=True)
36
+
37
+ def eliminar_archivo_tiempo(ruta, delay=1800):
38
+ """Elimina un archivo después de 'delay' segundos (30 minutos por defecto)."""
39
+ def eliminar():
40
+ try:
41
+ if os.path.exists(ruta):
42
+ os.remove(ruta)
43
+ logging.info(f"Archivo eliminado por timer: {ruta}")
44
+ except Exception as e:
45
+ logging.error(f"Error al eliminar {ruta}: {e}")
46
+ Timer(delay, eliminar).start()
47
+
48
  def cortar_video(video_path, metodo="inteligente", duracion=10):
49
  """Corta el video en clips según el método especificado."""
50
  try:
 
57
  logging.info(f"Video cortado en {len(clips)} clips manuales.")
58
  return clips
59
 
60
+ # Método "inteligente" simplificado (cortes cada 5 segundos)
61
  clips = []
62
  ultimo_corte = 0
63
  for i in range(1, math.ceil(video.duration)):
64
+ if i % 5 == 0:
65
  clips.append(video.subclip(ultimo_corte, i))
66
  ultimo_corte = i
67
  if ultimo_corte < video.duration:
 
74
 
75
  async def procesar_audio(texto, voz, duracion_total, duracion_intro, duracion_video_editado):
76
  """Genera el TTS y mezcla con la música de fondo."""
77
+ temp_files = []
78
  try:
79
  logging.info("Generando TTS y mezclando audio...")
80
  communicate = edge_tts.Communicate(texto, voz)
81
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
82
  await communicate.save(tmp.name)
83
  tts_audio = AudioFileClip(tmp.name)
84
+ temp_files.append(tmp.name)
85
 
86
  # Ajustar duración del TTS
87
  if tts_audio.duration > duracion_video_editado:
 
96
  with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
97
  bg_music.export(tmp.name, format="mp3")
98
  bg_audio = AudioFileClip(tmp.name).volumex(0.10)
99
+ temp_files.append(tmp.name)
100
 
101
  # Combinar audios
102
  audio_final = CompositeAudioClip([
 
108
  except Exception as e:
109
  logging.error(f"Error al procesar audio: {e}")
110
  raise
111
+ finally:
112
+ # Eliminar archivos temporales de audio inmediatamente
113
+ for file in temp_files:
114
+ try:
115
+ if os.path.exists(file):
116
+ os.remove(file)
117
+ logging.info(f"Archivo temporal de audio eliminado: {file}")
118
+ except Exception as e:
119
+ logging.warning(f"No se pudo eliminar el archivo temporal {file}: {e}")
120
 
121
  def agregar_transiciones(clips):
122
  """Agrega transiciones con watermark y sonido FX entre clips."""
 
141
 
142
  async def procesar_video(video_input, texto_tts, voz_seleccionada, metodo_corte, duracion_corte):
143
  """Procesa el video completo con intro, cortes, TTS y outro."""
 
144
  try:
145
  logging.info("Iniciando procesamiento de video...")
146
  # Cortar y editar video
 
164
 
165
  # Renderizar video final
166
  video_final = video_final.set_audio(audio_final)
167
+ timestamp = int(time.time())
168
+ output_path = os.path.join(OUTPUT_DIR, f"video_{timestamp}.mp4")
169
+
170
+ video_final.write_videofile(output_path, codec="libx264", fps=24)
171
+
172
+ # Programar eliminación del video en 30 minutos
173
+ eliminar_archivo_tiempo(output_path, delay=1800)
174
+ logging.info(f"Video guardado temporalmente en: {output_path}")
175
+ return output_path
176
  except Exception as e:
177
  logging.error(f"Error durante el procesamiento: {e}")
178
  raise
 
 
 
 
 
 
 
 
179
 
180
  # Interfaz Gradio con ejemplo de uso
181
  with gr.Blocks() as demo: