import gradio as gr import moviepy.editor as mp import numpy as np import librosa import matplotlib.pyplot as plt from PIL import Image import tempfile import os def generate_waveform_video(audio_file, image_file): try: # 1. Cargar audio y, sr = librosa.load(audio_file) duration = librosa.get_duration(y=y, sr=sr) # 2. Cargar imagen img_clip = mp.ImageClip(image_file).set_duration(duration) img_w, img_h = img_clip.size # 3. Crear efecto de waveform audio_envelope = np.abs(y) audio_envelope = (audio_envelope / np.max(audio_envelope)) * (img_h // 3) def make_frame(t): fig, ax = plt.subplots(figsize=(img_w/100, img_h/100), dpi=100) ax.set_xlim(0, duration) ax.set_ylim(-img_h//2, img_h//2) ax.axis('off') time_idx = int(t * sr) start = max(0, time_idx - sr//10) end = min(len(audio_envelope), time_idx + sr//10) wave_slice = audio_envelope[start:end] x = np.linspace(t-0.1, t+0.1, len(wave_slice)) ax.fill_between(x, wave_slice - img_h//4, -wave_slice + img_h//4, facecolor='red', alpha=0.7) # Convertir figura a numpy array buf = io.BytesIO() plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0) plt.close(fig) return np.array(Image.open(buf)) # Formato correcto para MoviePy # Crear video effect_clip = mp.VideoClip(make_frame, duration=duration).set_fps(24) final_clip = mp.CompositeVideoClip([img_clip, effect_clip.set_pos("center")]) final_clip = final_clip.set_audio(mp.AudioFileClip(audio_file)) # Guardar en archivo temporal with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmpfile: final_clip.write_videofile(tmpfile.name, fps=24, codec="libx264", audio_codec="aac", logger=None) return tmpfile.name except Exception as e: return f"Error: {str(e)}" # Interfaz Gradio iface = gr.Interface( fn=generate_waveform_video, inputs=[ gr.Audio(type="filepath", label="Audio (WAV/MP3)"), gr.Image(type="filepath", label="Imagen de Fondo"), ], outputs=gr.Video(label="Video Resultante", format="mp4"), title="Generador de Video con Efectos de Audio", description="Crea videos con efectos visuales sincronizados con el audio. Actualmente soporta efecto de waveform." ) if __name__ == "__main__": iface.queue().launch()