gnosticdev commited on
Commit
fc4d759
verified
1 Parent(s): 63e5b79

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -34
app.py CHANGED
@@ -6,6 +6,7 @@ from moviepy.editor import *
6
  import edge_tts
7
  import gradio as gr
8
  from pydub import AudioSegment
 
9
 
10
  # Configuraci贸n de Logs
11
  logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
@@ -23,6 +24,10 @@ for file in [INTRO_VIDEO, OUTRO_VIDEO, MUSIC_BG, GLITCH_SOUND, EJEMPLO_VIDEO]:
23
  logging.error(f"Falta archivo necesario: {file}")
24
  raise FileNotFoundError(f"Falta: {file}")
25
 
 
 
 
 
26
  def eliminar_archivo_tiempo(ruta, delay=1800):
27
  def eliminar():
28
  try:
@@ -102,42 +107,32 @@ def aplicar_glitch(video_clip):
102
 
103
  return video_clip.fl_image(glitch_effect)
104
 
105
- async def procesar_video(video_input, texto_tts, voz_seleccionada):
106
  try:
107
- logging.info("Iniciando procesamiento de video")
108
- intro = VideoFileClip(INTRO_VIDEO, target_resolution=(1080, 1920))
109
- outro = VideoFileClip(OUTRO_VIDEO, target_resolution=(1080, 1920))
110
- video_original = VideoFileClip(video_input, target_resolution=(1080, 1920))
111
- audio_original = video_original.audio
112
-
113
- intro.reader.close()
114
- outro.reader.close()
115
- video_original.reader.close()
116
-
117
- duracion_video = video_original.duration
118
- logging.info(f"Duraci贸n del video original: {duracion_video}s")
119
 
120
  audio_final = await procesar_audio(
121
  texto_tts,
122
  voz_seleccionada,
123
- duracion_video,
124
  audio_original
125
  )
126
 
127
  segment_duration = 18
128
  overlap = 2
129
- total_segments = int((duracion_video) // (segment_duration)) + 1
130
 
131
  segments = []
132
  glitch_clips = []
133
  glitch_sound = AudioFileClip(GLITCH_SOUND).volumex(0.5)
134
 
135
- start_time = 0
136
  for i in range(total_segments):
137
- end_time = start_time + segment_duration + overlap
138
- end_time = min(end_time, duracion_video)
139
 
140
- full_segment = video_original.subclip(start_time, end_time)
141
 
142
  if i > 0:
143
  glitch_part = full_segment.subclip(0, 0.5)
@@ -147,49 +142,83 @@ async def procesar_video(video_input, texto_tts, voz_seleccionada):
147
  full_segment.subclip(0.5)
148
  ], method="compose")
149
 
150
- glitch_sound_clip = glitch_sound.set_start(start_time)
151
  glitch_clips.append(glitch_sound_clip)
152
  else:
153
  processed_segment = full_segment
154
 
155
  segments.append(processed_segment)
156
- start_time += segment_duration
 
 
 
 
 
 
 
 
157
 
158
- video_final = concatenate_videoclips(segments, method="compose")
159
- video_con_audio = video_final.set_audio(audio_final)
 
 
 
 
 
 
 
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  intro = VideoFileClip(INTRO_VIDEO, target_resolution=(1080, 1920))
162
  outro = VideoFileClip(OUTRO_VIDEO, target_resolution=(1080, 1920))
163
- video_final = concatenate_videoclips([intro, video_con_audio, outro], method="compose")
164
 
 
165
  with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmp:
166
- video_final.write_videofile(
167
  tmp.name,
168
- codec="libx264",
 
169
  audio_codec="aac",
170
  fps=video_original.fps,
171
- threads=4,
172
- bitrate="5M",
173
  ffmpeg_params=[
174
- "-preset", "ultrafast",
175
- "-crf", "23",
176
  "-movflags", "+faststart",
177
  "-vf", "scale=1920:1080"
178
  ],
179
  verbose=False
180
  )
181
  eliminar_archivo_tiempo(tmp.name, 1800)
182
- logging.info(f"Video procesado guardado en: {tmp.name}")
183
  return tmp.name
184
 
185
  except Exception as e:
186
- logging.error(f"Fallo general en procesamiento: {str(e)}")
187
  raise
188
  finally:
189
  try:
 
190
  intro.close()
191
  outro.close()
192
- video_original.close()
193
  except:
194
  pass
195
 
@@ -226,4 +255,8 @@ with gr.Blocks() as demo:
226
  )
227
 
228
  if __name__ == "__main__":
229
- demo.queue().launch()
 
 
 
 
 
6
  import edge_tts
7
  import gradio as gr
8
  from pydub import AudioSegment
9
+ import psutil # Para monitoreo de recursos
10
 
11
  # Configuraci贸n de Logs
12
  logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
 
24
  logging.error(f"Falta archivo necesario: {file}")
25
  raise FileNotFoundError(f"Falta: {file}")
26
 
27
+ # Configuraci贸n de chunks
28
+ CHUNK_SIZE = 300 # 5 minutos por chunk (ajusta seg煤n tus recursos)
29
+ MAX_CHUNKS = 20 # L铆mite m谩ximo de chunks (previene loops infinitos)
30
+
31
  def eliminar_archivo_tiempo(ruta, delay=1800):
32
  def eliminar():
33
  try:
 
107
 
108
  return video_clip.fl_image(glitch_effect)
109
 
110
+ async def procesar_fragmento(chunk, texto_tts, voz_seleccionada, start_time):
111
  try:
112
+ audio_original = chunk.audio
113
+ duracion_chunk = chunk.duration
 
 
 
 
 
 
 
 
 
 
114
 
115
  audio_final = await procesar_audio(
116
  texto_tts,
117
  voz_seleccionada,
118
+ duracion_chunk,
119
  audio_original
120
  )
121
 
122
  segment_duration = 18
123
  overlap = 2
124
+ total_segments = int((duracion_chunk) // (segment_duration)) + 1
125
 
126
  segments = []
127
  glitch_clips = []
128
  glitch_sound = AudioFileClip(GLITCH_SOUND).volumex(0.5)
129
 
130
+ current_time = 0
131
  for i in range(total_segments):
132
+ end_time = current_time + segment_duration + overlap
133
+ end_time = min(end_time, duracion_chunk)
134
 
135
+ full_segment = chunk.subclip(current_time, end_time)
136
 
137
  if i > 0:
138
  glitch_part = full_segment.subclip(0, 0.5)
 
142
  full_segment.subclip(0.5)
143
  ], method="compose")
144
 
145
+ glitch_sound_clip = glitch_sound.set_start(start_time + current_time)
146
  glitch_clips.append(glitch_sound_clip)
147
  else:
148
  processed_segment = full_segment
149
 
150
  segments.append(processed_segment)
151
+ current_time += segment_duration
152
+
153
+ video_chunk = concatenate_videoclips(segments, method="compose")
154
+ video_chunk = video_chunk.set_audio(audio_final)
155
+ return video_chunk
156
+
157
+ except Exception as e:
158
+ logging.error(f"Fallo procesando fragmento: {str(e)}")
159
+ raise
160
 
161
+ async def procesar_video(video_input, texto_tts, voz_seleccionada):
162
+ try:
163
+ logging.info("Iniciando procesamiento de video")
164
+ video_original = VideoFileClip(video_input, target_resolution=(1080, 1920))
165
+ total_duration = video_original.duration
166
+
167
+ # Monitoreo de recursos
168
+ logging.info(f"Memoria inicial: {psutil.virtual_memory().percent}%")
169
+ logging.info(f"CPU inicial: {psutil.cpu_percent()}%")
170
 
171
+ # Dividir en chunks
172
+ chunks = []
173
+ for start in range(0, int(total_duration), CHUNK_SIZE):
174
+ end = min(start + CHUNK_SIZE, total_duration)
175
+ chunk = video_original.subclip(start, end)
176
+ chunks.append((start, chunk))
177
+
178
+ # Procesar cada chunk
179
+ processed_clips = []
180
+ for i, (start_time, chunk) in enumerate(chunks):
181
+ logging.info(f"Procesando chunk {i+1}/{len(chunks)}")
182
+ processed_chunk = await procesar_fragmento(chunk, texto_tts, voz_seleccionada, start_time)
183
+ processed_clips.append(processed_chunk)
184
+
185
+ # Combinar todos los chunks
186
+ final_video = concatenate_videoclips(processed_clips, method="compose")
187
+
188
+ # Agregar intro y outro
189
  intro = VideoFileClip(INTRO_VIDEO, target_resolution=(1080, 1920))
190
  outro = VideoFileClip(OUTRO_VIDEO, target_resolution=(1080, 1920))
191
+ final_video = concatenate_videoclips([intro, final_video, outro], method="compose")
192
 
193
+ # Renderizado final con optimizaci贸n
194
  with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmp:
195
+ final_video.write_videofile(
196
  tmp.name,
197
+ codec="h264_nvenc", # Usa GPU si est谩 disponible
198
+ preset="p7",
199
  audio_codec="aac",
200
  fps=video_original.fps,
201
+ threads=8,
202
+ bitrate="8M",
203
  ffmpeg_params=[
204
+ "-crf", "28",
 
205
  "-movflags", "+faststart",
206
  "-vf", "scale=1920:1080"
207
  ],
208
  verbose=False
209
  )
210
  eliminar_archivo_tiempo(tmp.name, 1800)
211
+ logging.info(f"Video final guardado: {tmp.name}")
212
  return tmp.name
213
 
214
  except Exception as e:
215
+ logging.error(f"Fallo general: {str(e)}")
216
  raise
217
  finally:
218
  try:
219
+ video_original.close()
220
  intro.close()
221
  outro.close()
 
222
  except:
223
  pass
224
 
 
255
  )
256
 
257
  if __name__ == "__main__":
258
+ demo.queue(
259
+ concurrency_count=1,
260
+ max_size=20,
261
+ server_timeout=3600 # Timeout de 1 hora
262
+ ).launch()