gnosticdev commited on
Commit
eb21acb
·
verified ·
1 Parent(s): d97f0d8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -53
app.py CHANGED
@@ -38,13 +38,14 @@ def eliminar_archivo_tiempo(ruta, delay=1800):
38
  from threading import Timer
39
  Timer(delay, eliminar).start()
40
 
41
- async def procesar_audio(texto, voz, duracion_video, audio_original=None):
42
  temp_files = []
43
  try:
44
- logging.info("Iniciando procesamiento de audio")
45
  if not texto.strip():
46
  raise ValueError("El texto para TTS no puede estar vacío.")
47
 
 
48
  def dividir_texto(texto, max_length=2000):
49
  return [texto[i:i + max_length] for i in range(0, len(texto), max_length)]
50
 
@@ -64,65 +65,55 @@ async def procesar_audio(texto, voz, duracion_video, audio_original=None):
64
  if tts_audio_final.duration > duracion_video:
65
  tts_audio_final = tts_audio_final.subclip(0, duracion_video)
66
 
67
- needed_ms = int(duracion_video * 1000)
68
- bg_music = AudioSegment.from_mp3(MUSIC_BG)
69
- repeticiones = needed_ms // len(bg_music) + 1
70
- bg_music = bg_music * repeticiones
71
- bg_music = bg_music[:needed_ms].fade_out(1000)
72
-
73
- with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_bg:
74
- bg_music.export(tmp_bg.name, format="mp3")
75
- bg_audio = AudioFileClip(tmp_bg.name).volumex(0.15)
76
- temp_files.append(tmp_bg.name)
77
-
78
- audios = [bg_audio.set_duration(duracion_video)]
79
- if audio_original:
80
- audios.append(audio_original.volumex(0.7))
81
- audios.append(tts_audio_final.volumex(0.85).set_start(0))
82
-
83
- audio_final = CompositeAudioClip(audios).set_duration(duracion_video)
84
- logging.info("Audio procesado exitosamente")
85
- return audio_final, temp_files # Retornamos los archivos temporales para limpieza
86
 
87
  except Exception as e:
88
- logging.error(f"Fallo en procesamiento de audio: {str(e)}")
89
  raise
90
-
91
- def aplicar_glitch(video_clip):
92
- def glitch_effect(frame):
93
- import numpy as np
94
- frame = frame.copy()
95
- height, width, _ = frame.shape
96
- offset = np.random.randint(3, 8)
97
- if height > 0 and offset != 0:
98
- frame[offset:, :] = np.roll(frame[:-offset, :], -offset, axis=0)
99
- return frame
100
-
101
- return video_clip.fl_image(glitch_effect)
 
 
 
 
 
 
102
 
103
  async def procesar_fragmento(chunk, texto_tts, voz_seleccionada, start_time):
104
- temp_files = []
105
  try:
106
- audio_original = chunk.audio
107
  duracion_chunk = chunk.duration
108
 
109
- # Si el chunk es demasiado corto, devolver sin procesar
110
- if duracion_chunk <= 18:
111
- audio_final, temp_files = await procesar_audio(
112
- texto_tts,
113
- voz_seleccionada,
114
- duracion_chunk,
115
- audio_original
116
- )
117
- return chunk.set_audio(audio_final), temp_files
118
-
119
- audio_final, temp_files = await procesar_audio(
120
  texto_tts,
121
  voz_seleccionada,
122
- duracion_chunk,
123
- audio_original
124
  )
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  segment_duration = 18
127
  overlap = 2
128
  segments = []
@@ -132,13 +123,14 @@ async def procesar_fragmento(chunk, texto_tts, voz_seleccionada, start_time):
132
  current_time = 0
133
  while current_time < duracion_chunk:
134
  end_time = current_time + segment_duration
135
- end_time = min(end_time, duracion_chunk)
 
136
 
137
  full_segment = chunk.subclip(current_time, end_time)
138
 
139
  if current_time > 0 and full_segment.duration >= 0.5:
140
  glitch_part = full_segment.subclip(0, 0.5)
141
- glitch_part = aplicar_glitch(glitch_part)
142
  processed_segment = concatenate_videoclips([
143
  glitch_part,
144
  full_segment.subclip(0.5)
@@ -154,7 +146,7 @@ async def procesar_fragmento(chunk, texto_tts, voz_seleccionada, start_time):
154
 
155
  video_chunk = concatenate_videoclips(segments, method="compose")
156
  video_chunk = video_chunk.set_audio(audio_final)
157
- return video_chunk, temp_files
158
 
159
  except Exception as e:
160
  logging.error(f"Fallo procesando fragmento: {str(e)}")
@@ -216,7 +208,6 @@ async def procesar_video(video_input, texto_tts, voz_seleccionada):
216
  raise
217
  finally:
218
  try:
219
- # Cerrar recursos solo después de completar todo el procesamiento
220
  video_original.close()
221
  intro.close()
222
  outro.close()
 
38
  from threading import Timer
39
  Timer(delay, eliminar).start()
40
 
41
+ async def procesar_audio_tts(texto, voz, duracion_video):
42
  temp_files = []
43
  try:
44
+ logging.info("Iniciando procesamiento de TTS")
45
  if not texto.strip():
46
  raise ValueError("El texto para TTS no puede estar vacío.")
47
 
48
+ # Dividir texto en fragmentos manejables
49
  def dividir_texto(texto, max_length=2000):
50
  return [texto[i:i + max_length] for i in range(0, len(texto), max_length)]
51
 
 
65
  if tts_audio_final.duration > duracion_video:
66
  tts_audio_final = tts_audio_final.subclip(0, duracion_video)
67
 
68
+ logging.info("TTS procesado exitosamente")
69
+ return tts_audio_final, temp_files
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
  except Exception as e:
72
+ logging.error(f"Fallo en procesamiento de TTS: {str(e)}")
73
  raise
74
+ finally:
75
+ for file in temp_files:
76
+ try:
77
+ os.remove(file)
78
+ except Exception as e:
79
+ logging.warning(f"Error limpiando {file}: {e}")
80
+
81
+ def crear_musica_fondo(duracion_video):
82
+ """Crea un loop continuo de música de fondo."""
83
+ bg_music = AudioSegment.from_mp3(MUSIC_BG)
84
+ needed_ms = int(duracion_video * 1000)
85
+ repeticiones = needed_ms // len(bg_music) + 1
86
+ bg_music = bg_music * repeticiones
87
+ bg_music = bg_music[:needed_ms].fade_out(1000)
88
+
89
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_bg:
90
+ bg_music.export(tmp_bg.name, format="mp3")
91
+ return AudioFileClip(tmp_bg.name).volumex(0.15), tmp_bg.name
92
 
93
  async def procesar_fragmento(chunk, texto_tts, voz_seleccionada, start_time):
 
94
  try:
 
95
  duracion_chunk = chunk.duration
96
 
97
+ # Procesar TTS para este chunk
98
+ tts_audio_final, tts_temp_files = await procesar_audio_tts(
 
 
 
 
 
 
 
 
 
99
  texto_tts,
100
  voz_seleccionada,
101
+ duracion_chunk
 
102
  )
103
 
104
+ # Crear música de fondo continua
105
+ bg_audio, bg_temp_file = crear_musica_fondo(duracion_chunk)
106
+
107
+ # Combinar pistas de audio
108
+ audio_original = chunk.audio
109
+ audios = [bg_audio.set_duration(duracion_chunk)]
110
+ if audio_original:
111
+ audios.append(audio_original.volumex(0.7))
112
+ audios.append(tts_audio_final.volumex(0.85).set_start(0))
113
+
114
+ audio_final = CompositeAudioClip(audios).set_duration(duracion_chunk)
115
+
116
+ # Dividir el chunk en segmentos con transiciones
117
  segment_duration = 18
118
  overlap = 2
119
  segments = []
 
123
  current_time = 0
124
  while current_time < duracion_chunk:
125
  end_time = current_time + segment_duration
126
+ if end_time > duracion_chunk:
127
+ break # Terminar si ya no hay suficiente tiempo
128
 
129
  full_segment = chunk.subclip(current_time, end_time)
130
 
131
  if current_time > 0 and full_segment.duration >= 0.5:
132
  glitch_part = full_segment.subclip(0, 0.5)
133
+ glitch_part = glitch_part.fx(vfx.glitch, intensity=0.1)
134
  processed_segment = concatenate_videoclips([
135
  glitch_part,
136
  full_segment.subclip(0.5)
 
146
 
147
  video_chunk = concatenate_videoclips(segments, method="compose")
148
  video_chunk = video_chunk.set_audio(audio_final)
149
+ return video_chunk, tts_temp_files + [bg_temp_file]
150
 
151
  except Exception as e:
152
  logging.error(f"Fallo procesando fragmento: {str(e)}")
 
208
  raise
209
  finally:
210
  try:
 
211
  video_original.close()
212
  intro.close()
213
  outro.close()