gnosticdev commited on
Commit
35ee7d1
·
verified ·
1 Parent(s): dd73bde

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -44
app.py CHANGED
@@ -3,64 +3,83 @@ import moviepy.editor as mp
3
  import numpy as np
4
  import librosa
5
  import matplotlib.pyplot as plt
6
- import io
 
7
 
8
- def audio_to_video(audio_file, image_file, effect_type="waveform"):
 
 
 
 
9
  try:
10
- # Cargar audio
11
- y, sr = librosa.load(audio_file)
 
12
  duration = librosa.get_duration(y=y, sr=sr)
 
13
 
14
- # Cargar imagen
15
- img_clip = mp.ImageClip(image_file).set_duration(duration)
16
-
17
- # Generar efecto visual (waveform)
18
- if effect_type == "waveform":
19
- audio_envelope = np.abs(y) # Envelope del audio
20
- audio_envelope = (audio_envelope / np.max(audio_envelope)) * (img_clip.h / 2)
21
 
22
- def make_frame(t):
23
- fig, ax = plt.subplots(figsize=(img_clip.w/100, img_clip.h/100), dpi=100)
24
- ax.set_xlim(0, duration)
25
- ax.set_ylim(-img_clip.h/2, img_clip.h/2)
26
- ax.axis('off')
27
-
28
- time_index = int(t * sr)
29
- wave_slice = audio_envelope[max(0, time_index - sr//10):min(len(audio_envelope), time_index + sr//10)]
30
- ax.plot(np.linspace(t-0.1, t+0.1, len(wave_slice)), wave_slice - img_clip.h/4, color='red')
31
- ax.plot(np.linspace(t-0.1, t+0.1, len(wave_slice)), -wave_slice + img_clip.h/4, color='red')
32
-
33
- buf = io.BytesIO()
34
- fig.savefig(buf, format='png', bbox_inches='tight', pad_inches=0)
35
- plt.close(fig)
36
- return np.array(Image.open(buf)) # Convertir a array de imagen
37
 
38
- effect_clip = mp.VideoClip(make_frame, duration=duration).set_fps(24)
39
- final_clip = mp.CompositeVideoClip([img_clip, effect_clip.set_pos("center")])
40
- else:
41
- return "Error: Efecto no soportado."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- # Agregar audio al video
44
- final_clip = final_clip.set_audio(mp.AudioFileClip(audio_file))
45
- output_path = "output.mp4"
46
- final_clip.write_videofile(output_path, fps=24, codec="libx264", audio_codec="aac")
47
- return output_path
 
 
 
 
 
 
 
 
 
48
 
49
  except Exception as e:
 
50
  return f"Error: {str(e)}"
51
 
52
- # Interfaz de Gradio
53
  iface = gr.Interface(
54
- fn=audio_to_video,
55
  inputs=[
56
- gr.Audio(type="filepath", label="Subir Audio (WAV/MP3)"),
57
- gr.Image(type="filepath", label="Subir Imagen"),
58
- gr.Radio(["waveform"], value="waveform", label="Efecto Visual")
59
  ],
60
- outputs=gr.Video(label="Video Generado"),
61
- title="Audio + Imagen → Video con Efecto Sincronizado",
62
- description="Sube un audio y una imagen para generar un video con efecto visual sincronizado (waveform)."
 
63
  )
64
 
65
  if __name__ == "__main__":
66
- iface.queue().launch()
 
 
3
  import numpy as np
4
  import librosa
5
  import matplotlib.pyplot as plt
6
+ from io import BytesIO
7
+ import logging
8
 
9
+ # Configuración de logging
10
+ logging.basicConfig(level=logging.INFO)
11
+ logger = logging.getLogger("audio_to_video")
12
+
13
+ def generate_waveform_video(audio_path, image_path):
14
  try:
15
+ # 1. Cargar audio
16
+ logger.info("Cargando archivo de audio...")
17
+ y, sr = librosa.load(audio_path)
18
  duration = librosa.get_duration(y=y, sr=sr)
19
+ logger.info(f"Duración del audio: {duration:.2f} segundos")
20
 
21
+ # 2. Cargar imagen
22
+ logger.info("Procesando imagen...")
23
+ img_clip = mp.ImageClip(image_path).set_duration(duration)
24
+ img_width, img_height = img_clip.size
 
 
 
25
 
26
+ # 3. Crear efecto de waveform
27
+ logger.info("Generando efecto visual...")
28
+ audio_envelope = np.abs(y) # Envelope del audio
29
+ audio_envelope = (audio_envelope / np.max(audio_envelope)) * (img_height // 3)
 
 
 
 
 
 
 
 
 
 
 
30
 
31
+ def make_frame(t):
32
+ fig, ax = plt.subplots(figsize=(img_width/100, img_height/100), dpi=100)
33
+ ax.set_xlim(0, duration)
34
+ ax.set_ylim(-img_height//2, img_height//2)
35
+ ax.axis('off')
36
+
37
+ time_index = int(t * sr)
38
+ start = max(0, time_index - sr//10)
39
+ end = min(len(audio_envelope), time_index + sr//10)
40
+ wave_slice = audio_envelope[start:end]
41
+
42
+ x_values = np.linspace(t-0.1, t+0.1, len(wave_slice))
43
+ ax.fill_between(x_values, wave_slice - img_height//4, -wave_slice + img_height//4,
44
+ facecolor='red', alpha=0.7)
45
+
46
+ buf = BytesIO()
47
+ plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0)
48
+ plt.close(fig)
49
+ return mp.ImageClip(buf).get_frame(0)
50
 
51
+ logger.info("Renderizando video...")
52
+ effect_clip = mp.VideoClip(make_frame, duration=duration).set_fps(24)
53
+ final_clip = mp.CompositeVideoClip([img_clip, effect_clip.set_pos("center")])
54
+
55
+ # 4. Combinar con audio
56
+ final_clip = final_clip.set_audio(mp.AudioFileClip(audio_path))
57
+
58
+ # 5. Guardar en memoria
59
+ buffer = BytesIO()
60
+ final_clip.write_videofile(buffer, fps=24, codec="libx264",
61
+ audio_codec="aac", logger=None)
62
+ buffer.seek(0)
63
+ logger.info("Video generado exitosamente")
64
+ return buffer
65
 
66
  except Exception as e:
67
+ logger.error(f"Error durante la generación: {str(e)}")
68
  return f"Error: {str(e)}"
69
 
70
+ # Interfaz Gradio
71
  iface = gr.Interface(
72
+ fn=generate_waveform_video,
73
  inputs=[
74
+ gr.Audio(type="filepath", label="Audio (WAV/MP3)"),
75
+ gr.Image(type="filepath", label="Imagen de Fondo"),
 
76
  ],
77
+ outputs=gr.Video(label="Video Resultante", format="mp4"),
78
+ title="Generador de Video con Efectos de Audio",
79
+ description="Crea videos con efectos visuales sincronizados con el audio. Actualmente soporta efecto de waveform.",
80
+ allow_flagging="never"
81
  )
82
 
83
  if __name__ == "__main__":
84
+ logger.info("Iniciando aplicación Gradio...")
85
+ iface.queue().launch(share=False, debug=True)