gnosticdev commited on
Commit
9857383
verified
1 Parent(s): 9402942

Create app.py

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