gnosticdev commited on
Commit
344c699
verified
1 Parent(s): fb4e1f4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +34 -50
app.py CHANGED
@@ -27,41 +27,28 @@ for file in [INTRO_VIDEO, OUTRO_VIDEO, MUSIC_BG, FX_SOUND, WATERMARK]:
27
  if not os.path.exists(file):
28
  raise FileNotFoundError(f"Falta: {file}")
29
 
30
- async def procesar_audio(texto, voz):
31
  try:
32
  communicate = edge_tts.Communicate(texto, voz)
33
- with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
34
- await communicate.save(tmp.name)
35
- return tmp.name # Retorna solo el TTS sin procesar
36
- except Exception as e:
37
- logging.error(f"TTS fallido: {e}")
38
- raise
39
-
40
- def mezclar_audio(tts_path, duracion_total):
41
- try:
42
- # Cargar TTS
43
- tts = AudioSegment.from_mp3(tts_path)
44
 
45
  # Preparar m煤sica de fondo en loop
46
- bg = AudioSegment.from_mp3(MUSIC_BG)
47
- bg = bg - 10 # 10% volumen (ajusta seg煤n necesidad)
 
 
48
 
49
- # Calcular repeticiones necesarias
50
- repeticiones = math.ceil(duracion_total * 1000 / len(bg))
51
- bg_loop = bg * repeticiones
52
 
53
- # Recortar a duraci贸n exacta
54
- bg_final = bg_loop[:duracion_total*1000].fade_out(3000)
55
-
56
- # Combinar TTS y m煤sica
57
- audio_final = bg_final.overlay(tts, position=0)
58
-
59
- # Guardar temporal
60
- with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
61
- audio_final.export(tmp.name, format="mp3")
62
- return tmp.name
63
  except Exception as e:
64
- logging.error(f"Error mezclando audio: {e}")
65
  raise
66
 
67
  def cortar_video(video_path, metodo="inteligente", duracion=10):
@@ -108,7 +95,7 @@ def agregar_transiciones(clips):
108
  raise
109
 
110
  async def procesar_video(
111
- video_input,
112
  texto_tts,
113
  voz_seleccionada,
114
  metodo_corte,
@@ -116,7 +103,7 @@ async def procesar_video(
116
  ):
117
  temp_files = []
118
  try:
119
- # Procesar video
120
  clips = cortar_video(video_input, metodo_corte, duracion_corte)
121
  video_editado = agregar_transiciones(clips)
122
 
@@ -125,47 +112,44 @@ async def procesar_video(
125
  outro = VideoFileClip(OUTRO_VIDEO)
126
  video_final = concatenate_videoclips([intro, video_editado, outro])
127
 
128
- # Generar TTS
129
- tts_path = await procesar_audio(texto_tts, voz_seleccionada)
130
- duracion_tts = AudioFileClip(tts_path).duration
131
-
132
- # Calcular duraci贸n total (intro + contenido + outro)
133
- duracion_total = intro.duration + video_editado.duration + outro.duration
134
 
135
- # Mezclar audio
136
- audio_mix_path = mezclar_audio(tts_path, duracion_total)
137
 
138
  # Combinar video y audio
139
  video_final = video_final.set_audio(AudioFileClip(audio_mix_path))
140
 
141
- # Guardar resultado final
142
- with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp:
143
- video_final.write_videofile(tmp.name, codec="libx264", fps=24)
144
- temp_files.append(tmp.name)
145
- return tmp.name
146
  except Exception as e:
147
  logging.error(f"Error general: {e}")
148
  raise
149
  finally:
150
- # Eliminar temporales
151
- for file in temp_files + [tts_path, audio_mix_path]:
152
  try:
153
- os.remove(file)
154
- except:
155
- pass
 
156
 
157
  # Interfaz Gradio
158
  with gr.Blocks() as demo:
159
  gr.Markdown("# Video Editor IA")
160
 
161
  with gr.Tab("Principal"):
162
- video_input = gr.Video(label="Subir video")
163
  texto_tts = gr.Textbox(label="Texto para TTS", lines=3)
164
  voz_seleccionada = gr.Dropdown(
165
  label="Voz",
166
  choices=["es-ES-AlvaroNeural", "es-MX-BeatrizNeural"]
167
  )
168
- procesar_btn = gr.Button("Generar")
169
  video_output = gr.Video(label="Resultado")
170
 
171
  with gr.Tab("Ajustes"):
 
27
  if not os.path.exists(file):
28
  raise FileNotFoundError(f"Falta: {file}")
29
 
30
+ async def procesar_audio(texto, voz, duracion_total):
31
  try:
32
  communicate = edge_tts.Communicate(texto, voz)
33
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_tts:
34
+ await communicate.save(tmp_tts.name)
35
+ tts_audio = AudioSegment.from_mp3(tmp_tts.name)
 
 
 
 
 
 
 
 
36
 
37
  # Preparar m煤sica de fondo en loop
38
+ bg_music = AudioSegment.from_mp3(MUSIC_BG) - 10 # 10% volumen
39
+ repeticiones = math.ceil(duracion_total * 1000 / len(bg_music))
40
+ bg_music_loop = bg_music * repeticiones
41
+ bg_music_final = bg_music_loop[:duracion_total*1000].fade_out(3000)
42
 
43
+ # Combinar TTS (despu茅s de la intro) con m煤sica
44
+ intro_duration = VideoFileClip(INTRO_VIDEO).duration * 1000 # Duraci贸n en ms
45
+ audio_final = bg_music_final.overlay(tts_audio, position=intro_duration)
46
 
47
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_mix:
48
+ audio_final.export(tmp_mix.name, format="mp3")
49
+ return tmp_mix.name
 
 
 
 
 
 
 
50
  except Exception as e:
51
+ logging.error(f"Error procesando audio: {e}")
52
  raise
53
 
54
  def cortar_video(video_path, metodo="inteligente", duracion=10):
 
95
  raise
96
 
97
  async def procesar_video(
98
+ video_input,
99
  texto_tts,
100
  voz_seleccionada,
101
  metodo_corte,
 
103
  ):
104
  temp_files = []
105
  try:
106
+ # Procesar video principal
107
  clips = cortar_video(video_input, metodo_corte, duracion_corte)
108
  video_editado = agregar_transiciones(clips)
109
 
 
112
  outro = VideoFileClip(OUTRO_VIDEO)
113
  video_final = concatenate_videoclips([intro, video_editado, outro])
114
 
115
+ # Calcular duraci贸n total para la m煤sica
116
+ duracion_total = video_final.duration
 
 
 
 
117
 
118
+ # Generar audio (m煤sica en loop + TTS despu茅s de intro)
119
+ audio_mix_path = await procesar_audio(texto_tts, voz_seleccionada, duracion_total)
120
 
121
  # Combinar video y audio
122
  video_final = video_final.set_audio(AudioFileClip(audio_mix_path))
123
 
124
+ # Renderizar
125
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_out:
126
+ video_final.write_videofile(tmp_out.name, codec="libx264", fps=24)
127
+ temp_files.append(tmp_out.name)
128
+ return tmp_out.name
129
  except Exception as e:
130
  logging.error(f"Error general: {e}")
131
  raise
132
  finally:
133
+ # Eliminar archivos temporales
134
+ for file in temp_files + [getattr(video_input, 'name', None)]:
135
  try:
136
+ if file and os.path.exists(file):
137
+ os.remove(file)
138
+ except Exception as e:
139
+ logging.warning(f"Error eliminando {file}: {e}")
140
 
141
  # Interfaz Gradio
142
  with gr.Blocks() as demo:
143
  gr.Markdown("# Video Editor IA")
144
 
145
  with gr.Tab("Principal"):
146
+ video_input = gr.Video(label="Subir video") # Solo un video
147
  texto_tts = gr.Textbox(label="Texto para TTS", lines=3)
148
  voz_seleccionada = gr.Dropdown(
149
  label="Voz",
150
  choices=["es-ES-AlvaroNeural", "es-MX-BeatrizNeural"]
151
  )
152
+ procesar_btn = gr.Button("Generar Video")
153
  video_output = gr.Video(label="Resultado")
154
 
155
  with gr.Tab("Ajustes"):