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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +31 -98
app.py CHANGED
@@ -1,133 +1,66 @@
1
  import gradio as gr
2
- print(f"Gradio version: {gr.__version__}")
3
  import moviepy.editor as mp
4
  import numpy as np
5
  import librosa
6
- import librosa.display
7
  import matplotlib.pyplot as plt
8
  import io
9
- import os
10
 
11
- # Función principal para generar el video
12
  def audio_to_video(audio_file, image_file, effect_type="waveform"):
13
- """
14
- Genera un video a partir de un archivo de audio y una imagen, con un efecto visual sincronizado.
15
-
16
- Args:
17
- audio_file: Ruta al archivo de audio (wav o mp3).
18
- image_file: Ruta al archivo de imagen (debe ser un formato soportado por MoviePy).
19
- effect_type: Tipo de efecto visual a utilizar ("waveform" por defecto, otros tipos se pueden agregar).
20
-
21
- Returns:
22
- Ruta al archivo de video generado (mp4). Si falla, retorna un mensaje de error.
23
- """
24
  try:
25
- # 1. Cargar el audio usando Librosa
26
  y, sr = librosa.load(audio_file)
27
  duration = librosa.get_duration(y=y, sr=sr)
28
 
29
- # 2. Cargar la imagen
30
- img_clip = mp.ImageClip(image_file)
31
- img_clip = img_clip.set_duration(duration) # Asignar la duración del audio a la imagen
32
 
33
- # 3. Generar el efecto visual
34
  if effect_type == "waveform":
35
- audio_envelope = np.abs(y) # Calculate the audio envelope
36
-
37
- # Normalize audio envelope to image dimensions
38
- audio_envelope = audio_envelope / np.max(audio_envelope)
39
- audio_envelope = audio_envelope * img_clip.size[1] / 2 # Scale to half the image height
40
-
41
 
42
  def make_frame(t):
43
- # Create a new figure for each frame
44
- fig, ax = plt.subplots(figsize=(img_clip.size[0]/100, img_clip.size[1]/100), dpi=100) # Adjust figsize for image dimensions
45
  ax.set_xlim(0, duration)
46
- ax.set_ylim(-img_clip.size[1] / 2, img_clip.size[1] / 2)
47
- ax.axis('off') # Hide axis
48
-
49
- # Plot waveform
50
  time_index = int(t * sr)
51
- wave_slice = audio_envelope[max(0,time_index - sr//10):min(len(audio_envelope), time_index + sr//10)]
52
- time_slice = np.linspace(0,0.2,len(wave_slice))
53
- ax.plot(np.linspace(t-0.1,t+0.1,len(wave_slice)), wave_slice-img_clip.size[1]/4, color='red')
54
- ax.plot(np.linspace(t-0.1,t+0.1,len(wave_slice)), -wave_slice+img_clip.size[1]/4, color='red')
55
-
56
-
57
- # Convert the Matplotlib figure to an image
58
  buf = io.BytesIO()
59
- fig.canvas.print_png(buf)
60
- data = np.frombuffer(buf.getvalue(), dtype=np.uint8)
61
- img = plt.imread(io.BytesIO(data)) #read as image
62
- plt.close(fig) # Close the figure to prevent memory leaks
63
- return img
64
-
65
-
66
- audio_effect_clip = mp.VideoClip(make_frame, duration=duration)
67
- audio_effect_clip = audio_effect_clip.set_fps(24) # Set a reasonable frame rate
68
 
 
 
69
  else:
70
- return "Error: Efecto visual no soportado."
71
-
72
- # 4. Overlay effect onto image
73
- final_clip = mp.CompositeVideoClip([img_clip, audio_effect_clip.set_pos("center")])
74
 
75
-
76
- # 5. Agregar el audio al video
77
- audio_clip = mp.AudioFileClip(audio_file)
78
- final_clip = final_clip.set_audio(audio_clip)
79
-
80
-
81
- # 6. Guardar el video
82
- output_video_path = "output.mp4"
83
- final_clip.write_videofile(output_video_path, fps=24, codec="libx264", audio_codec="aac") # Ajustar los parámetros de codificación según sea necesario
84
- return output_video_path
85
 
86
  except Exception as e:
87
  return f"Error: {str(e)}"
88
 
89
-
90
- # ----------------------------------
91
- # Gradio Interface
92
- # ----------------------------------
93
-
94
  iface = gr.Interface(
95
  fn=audio_to_video,
96
  inputs=[
97
- # Eliminamos 'source="upload"' (no es necesario en Gradio 4.x)
98
- gr.Audio(type="filepath", label="Subir Archivo de Audio (WAV o MP3)"),
99
  gr.Image(type="filepath", label="Subir Imagen"),
100
- gr.Radio(["waveform"], value="waveform", label="Tipo de Efecto Visual")
101
  ],
102
- outputs=gr.Video(label="Video Generado"), # Usar gr.Video() en lugar de "video"
103
- title="Audio to Video Generator",
104
- description="Sube un audio y una imagen para generar un video con efecto visual sincronizado.",
105
- examples=[["audio_example.wav", "image_example.jpg", "waveform"]]
106
  )
107
 
108
-
109
- # ----------------------------------
110
- # Example files (optional). Create these files
111
- # or remove the 'examples' line above.
112
- # ----------------------------------
113
- # Create dummy audio and image for example purposes if they don't exist
114
- if not os.path.exists("audio_example.wav"):
115
- sr = 22050
116
- T = 5
117
- t = np.linspace(0, T, int(T*sr), endpoint=False)
118
- x = 0.5*np.sin(2*np.pi*440*t) # A4 frequency
119
- librosa.output.write_wav("audio_example.wav", x, sr)
120
-
121
- if not os.path.exists("image_example.jpg"):
122
- # Create a simple placeholder image
123
- import matplotlib.pyplot as plt
124
- fig, ax = plt.subplots(figsize=(6,4))
125
- ax.text(0.5, 0.5, "Placeholder Image", ha="center", va="center")
126
- ax.axis("off")
127
- fig.savefig("image_example.jpg")
128
- plt.close(fig)
129
-
130
-
131
-
132
  if __name__ == "__main__":
133
  iface.queue().launch()
 
1
  import gradio as gr
 
2
  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()