Skip to content

Commit 07725f4

Browse files
authored
Create waveform_visualizer.py
1 parent 16f0528 commit 07725f4

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

waveform_visualizer.py

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import numpy as np
2+
import matplotlib.pyplot as plt
3+
from matplotlib.animation import FuncAnimation
4+
from scipy.io import wavfile
5+
from moviepy.editor import VideoFileClip, AudioFileClip, CompositeVideoClip
6+
from pydub import AudioSegment
7+
import os
8+
import tempfile
9+
10+
def convert_to_wav(input_file):
11+
audio = AudioSegment.from_file(input_file)
12+
temp_wav = tempfile.NamedTemporaryFile(suffix='.wav', delete=False)
13+
audio.export(temp_wav.name, format='wav')
14+
return temp_wav.name
15+
16+
def create_waveform_video(audio_file, output_file):
17+
temp_wav_name = None
18+
try:
19+
# Convert to WAV if not already
20+
if not audio_file.lower().endswith('.wav'):
21+
print("Converting audio to WAV format...")
22+
temp_wav_name = convert_to_wav(audio_file)
23+
audio_file = temp_wav_name
24+
25+
# Read the WAV file
26+
sample_rate, audio_data = wavfile.read(audio_file)
27+
28+
# If stereo, take the mean of both channels
29+
if len(audio_data.shape) > 1:
30+
audio_data = np.mean(audio_data, axis=1)
31+
32+
# Normalize audio data
33+
audio_data = audio_data / np.max(np.abs(audio_data))
34+
35+
# Calculate duration
36+
duration = len(audio_data) / sample_rate
37+
38+
# Set up the figure and axis
39+
fig, ax = plt.subplots(figsize=(16, 9), facecolor='black')
40+
ax.set_facecolor('black')
41+
ax.set_ylim(-1, 1)
42+
ax.set_xlim(0, 1) # Set x-axis from 0 to 1
43+
44+
# Add subtle grid
45+
ax.grid(color='dimgray', linestyle=':', linewidth=0.5, alpha=0.5)
46+
47+
# Remove axis labels
48+
ax.set_xticks([])
49+
ax.set_yticks([])
50+
51+
line, = ax.plot([], [], color='white', lw=2)
52+
53+
# Number of points to display
54+
num_points = 1000
55+
56+
# Animation function
57+
def animate(frame):
58+
start = frame * sample_rate // 30
59+
end = start + num_points
60+
x = np.linspace(0, 1, num_points)
61+
y = audio_data[start:end]
62+
if len(y) < num_points:
63+
y = np.pad(y, (0, num_points - len(y)), 'constant')
64+
line.set_data(x, y)
65+
return line,
66+
67+
# Create the animation
68+
anim = FuncAnimation(fig, animate, frames=int(30 * duration),
69+
interval=1000/30, blit=True)
70+
71+
# Save the animation as a temporary file
72+
temp_video = tempfile.NamedTemporaryFile(suffix='.mp4', delete=False)
73+
anim.save(temp_video.name, fps=30, extra_args=['-vcodec', 'libx264'])
74+
75+
# Close the matplotlib figure
76+
plt.close(fig)
77+
78+
# Load the temporary video file
79+
video = VideoFileClip(temp_video.name)
80+
81+
# Load the audio file
82+
audio = AudioFileClip(audio_file)
83+
84+
# Set the audio of the video
85+
final_video = video.set_audio(audio)
86+
87+
# Write the final video file
88+
final_video.write_videofile(output_file, codec='libx264', audio_codec='aac')
89+
90+
# Close the clips
91+
video.close()
92+
audio.close()
93+
final_video.close()
94+
95+
# Remove the temporary video file
96+
os.unlink(temp_video.name)
97+
98+
except Exception as e:
99+
print(f"An error occurred: {str(e)}")
100+
finally:
101+
# Clean up the temporary WAV file if it was created
102+
if temp_wav_name and os.path.exists(temp_wav_name):
103+
os.unlink(temp_wav_name)
104+
105+
def main():
106+
while True:
107+
audio_file = input("Enter the path to your audio file: ").strip()
108+
if os.path.isfile(audio_file):
109+
break
110+
else:
111+
print("Invalid file path. Please try again.")
112+
113+
output_file = input("Enter the name for the output MP4 file (default: output.mp4): ").strip()
114+
if not output_file:
115+
output_file = "output.mp4"
116+
elif not output_file.lower().endswith('.mp4'):
117+
output_file += '.mp4'
118+
119+
print(f"Creating video from {audio_file}...")
120+
create_waveform_video(audio_file, output_file)
121+
print(f"Video created successfully: {output_file}")
122+
123+
if __name__ == "__main__":
124+
main()

0 commit comments

Comments
 (0)