Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import moviepy.editor as mp | |
| import numpy as np | |
| import librosa | |
| import librosa.display | |
| import matplotlib.pyplot as plt | |
| import io | |
| import os | |
| # Funci贸n principal para generar el video | |
| def audio_to_video(audio_file, image_file, effect_type="waveform"): | |
| """ | |
| Genera un video a partir de un archivo de audio y una imagen, con un efecto visual sincronizado. | |
| Args: | |
| audio_file: Ruta al archivo de audio (wav o mp3). | |
| image_file: Ruta al archivo de imagen (debe ser un formato soportado por MoviePy). | |
| effect_type: Tipo de efecto visual a utilizar ("waveform" por defecto, otros tipos se pueden agregar). | |
| Returns: | |
| Ruta al archivo de video generado (mp4). Si falla, retorna un mensaje de error. | |
| """ | |
| try: | |
| # 1. Cargar el audio usando Librosa | |
| y, sr = librosa.load(audio_file) | |
| duration = librosa.get_duration(y=y, sr=sr) | |
| # 2. Cargar la imagen | |
| img_clip = mp.ImageClip(image_file) | |
| img_clip = img_clip.set_duration(duration) # Asignar la duraci贸n del audio a la imagen | |
| # 3. Generar el efecto visual | |
| if effect_type == "waveform": | |
| audio_envelope = np.abs(y) # Calculate the audio envelope | |
| # Normalize audio envelope to image dimensions | |
| audio_envelope = audio_envelope / np.max(audio_envelope) | |
| audio_envelope = audio_envelope * img_clip.size[1] / 2 # Scale to half the image height | |
| def make_frame(t): | |
| # Create a new figure for each frame | |
| fig, ax = plt.subplots(figsize=(img_clip.size[0]/100, img_clip.size[1]/100), dpi=100) # Adjust figsize for image dimensions | |
| ax.set_xlim(0, duration) | |
| ax.set_ylim(-img_clip.size[1] / 2, img_clip.size[1] / 2) | |
| ax.axis('off') # Hide axis | |
| # Plot waveform | |
| time_index = int(t * sr) | |
| wave_slice = audio_envelope[max(0,time_index - sr//10):min(len(audio_envelope), time_index + sr//10)] | |
| time_slice = np.linspace(0,0.2,len(wave_slice)) | |
| ax.plot(np.linspace(t-0.1,t+0.1,len(wave_slice)), wave_slice-img_clip.size[1]/4, color='red') | |
| ax.plot(np.linspace(t-0.1,t+0.1,len(wave_slice)), -wave_slice+img_clip.size[1]/4, color='red') | |
| # Convert the Matplotlib figure to an image | |
| buf = io.BytesIO() | |
| fig.canvas.print_png(buf) | |
| data = np.frombuffer(buf.getvalue(), dtype=np.uint8) | |
| img = plt.imread(io.BytesIO(data)) #read as image | |
| plt.close(fig) # Close the figure to prevent memory leaks | |
| return img | |
| audio_effect_clip = mp.VideoClip(make_frame, duration=duration) | |
| audio_effect_clip = audio_effect_clip.set_fps(24) # Set a reasonable frame rate | |
| else: | |
| return "Error: Efecto visual no soportado." | |
| # 4. Overlay effect onto image | |
| final_clip = mp.CompositeVideoClip([img_clip, audio_effect_clip.set_pos("center")]) | |
| # 5. Agregar el audio al video | |
| audio_clip = mp.AudioFileClip(audio_file) | |
| final_clip = final_clip.set_audio(audio_clip) | |
| # 6. Guardar el video | |
| output_video_path = "output.mp4" | |
| 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 | |
| return output_video_path | |
| except Exception as e: | |
| return f"Error: {str(e)}" | |
| # ---------------------------------- | |
| # Gradio Interface | |
| # ---------------------------------- | |
| iface = gr.Interface( | |
| fn=audio_to_video, | |
| inputs=[ | |
| gr.Audio(source="upload", type="filepath", label="Subir Archivo de Audio (WAV o MP3)"), | |
| gr.Image(source="upload", type="filepath", label="Subir Imagen"), | |
| gr.Radio(["waveform"], value="waveform", label="Tipo de Efecto Visual (Waveform es el 煤nico soportado por ahora)") | |
| ], | |
| outputs="video", | |
| title="Audio to Video Generator", | |
| 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'.", | |
| examples=[["audio_example.wav", "image_example.jpg", "waveform"]] # Add example files if you want. | |
| ) | |
| # ---------------------------------- | |
| # Example files (optional). Create these files | |
| # or remove the 'examples' line above. | |
| # ---------------------------------- | |
| # Create dummy audio and image for example purposes if they don't exist | |
| if not os.path.exists("audio_example.wav"): | |
| sr = 22050 | |
| T = 5 | |
| t = np.linspace(0, T, int(T*sr), endpoint=False) | |
| x = 0.5*np.sin(2*np.pi*440*t) # A4 frequency | |
| librosa.output.write_wav("audio_example.wav", x, sr) | |
| if not os.path.exists("image_example.jpg"): | |
| # Create a simple placeholder image | |
| import matplotlib.pyplot as plt | |
| fig, ax = plt.subplots(figsize=(6,4)) | |
| ax.text(0.5, 0.5, "Placeholder Image", ha="center", va="center") | |
| ax.axis("off") | |
| fig.savefig("image_example.jpg") | |
| plt.close(fig) | |
| iface.launch() |