Visualizzatore Musicale con Python.Jupyter Notebook in descrizione
ฝัง
- เผยแพร่เมื่อ 15 ก.ย. 2024
- import librosa
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from moviepy.editor import VideoFileClip, AudioFileClip
import tempfile
import os
from scipy.signal import savgol_filter
def load_and_preprocess_music(file_path):
y, sr = librosa.load(file_path)
n_fft = 2048
hop_length = 512
mel_spec = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=128, n_fft=n_fft, hop_length=hop_length)
mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)
mel_spec_db = savgol_filter(mel_spec_db, window_length=15, polyorder=3, axis=1)
return y, sr, mel_spec_db
def create_base_animation():
fig, ax = plt.subplots(figsize=(16, 9), facecolor='black')
ax.set_facecolor('black')
ax.axis('off')
Create a gradient background
gradient = np.linspace(0, 1, 256).reshape(1, -1)
gradient = np.repeat(gradient, 512, axis=0)
ax.imshow(gradient, cmap='cool', aspect='auto', extent=[0, 1, 0, 1], alpha=0.3)
Frequency bars
freq_bars = ax.bar(np.linspace(0.2, 0.8, 64), np.zeros(64), color='cyan', alpha=0.8, width=0.008)
Waveform
waveform, = ax.plot([], [], color='white', alpha=0.8, linewidth=2)
Time text
text_obj = ax.text(0.02, 0.98, "", transform=ax.transAxes, fontsize=16, color='white',
verticalalignment='top')
Scatter particles
scatter = ax.scatter([], [], s=50, c=[], cmap='viridis', alpha=0.6)
Pulsing circle
circle = plt.Circle((0.5, 0.5), 0.4, color='cyan', fill=False, linewidth=2, alpha=0.8)
ax.add_patch(circle)
return fig, ax, freq_bars, waveform, text_obj, scatter, circle
def update_animation(frame, mel_spec_db, y, sr, freq_bars, waveform, text_obj, scatter, circle):
spec_slice = mel_spec_db[:, frame]
bar_heights = np.interp(spec_slice, (spec_slice.min(), spec_slice.max()), (0, 1))
Update frequency bars
for bar, h in zip(freq_bars, bar_heights[:64]):
bar.set_height(h)
energy = np.mean(bar_heights)
Update bar colors
for bar in freq_bars:
bar.set_color(plt.cm.viridis(energy))
start = int(frame / 30 * sr)
end = start + sr // 30
waveform_data = y[start:end]
waveform_x = np.linspace(0, 1, len(waveform_data))
waveform_y = waveform_data * 0.3 + 0.5
waveform.set_data(waveform_x, waveform_y)
Update time text
current_time = frame / 30
minutes = int(current_time // 60)
seconds = int(current_time % 60)
text_obj.set_text(f"{minutes:02d}:{seconds:02d}")
Update scatter plot
scatter.set_offsets(np.c_[np.random.rand(100), np.random.rand(100)])
scatter.set_array(np.random.rand(100))
Update pulsing circle
circle.set_radius(0.3 + 0.1 * np.sin(2 * np.pi * frame / 30))
circle.set_edgecolor(plt.cm.viridis(energy))
return list(freq_bars) + [waveform, text_obj, scatter, circle]
def create_animation(mel_spec_db, y, sr):
fig, ax, freq_bars, waveform, text_obj, scatter, circle = create_base_animation()
duration = len(y) / sr
anim = FuncAnimation(fig, update_animation, frames=int(duration * 30),
fargs=(mel_spec_db, y, sr, freq_bars, waveform, text_obj, scatter, circle),
interval=33.33, blit=True)
return anim, fig
def render_animation(anim, fig, audio_path, output_path):
with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as temp_video:
anim.save(temp_video.name, fps=30, bitrate=5000, extra_args=['-vcodec', 'libx264'])
plt.close(fig)
video = VideoFileClip(temp_video.name)
audio = AudioFileClip(audio_path)
video = video.set_duration(audio.duration)
final_video = video.set_audio(audio)
final_video.write_videofile(output_path, codec='libx264', audio_codec='aac')
video.close()
audio.close()
final_video.close()
os.unlink(temp_video.name)
def main(audio_path, output_path):
y, sr, mel_spec_db = load_and_preprocess_music(audio_path)
anim, fig = create_animation(mel_spec_db, y, sr)
render_animation(anim, fig, audio_path, output_path)
print(f"Animation saved to {output_path}")
if _name_ == "__main__":
audio_path = "/content/drive/MyDrive/Shadow20ext%20v2.mp3" # Replace with your audio file path
output_path = "enhanced_music_visualizer.mp4"
main(audio_path, output_path)