Python 基于音频频谱生产频谱动效

首先,需要安装一些必要的库,比如matplotlib、numpy、scipy和moviepy。

pip install matplotlib numpy scipy moviepy

然后,需要用scipy.io.wavfile模块来读取音频文件,并用scipy.fft.fft函数来计算音频信号的傅里叶变换,得到频谱数据。

接下来,需要用matplotlib.pyplot模块来绘制每一帧的频谱图,并用moviepy.editor模块来将这些图像合成为一个视频文件。

最后,需要用tkinter.filedialog模块来调用Windows文件资源管理器选择一个或多个音频文件,并对每个文件执行上述步骤。

# 导入必要的库
import matplotlib.pyplot as plt
import numpy as np
from scipy.io import wavfile
from scipy.fft import fft
from moviepy.editor import ImageSequenceClip
from tkinter.filedialog import askopenfilenames

# 定义一些常量和参数
FPS = 30 # 视频帧率(每秒帧数)
RESOLUTION = (3840, 2160) # 视频分辨率(宽度和高度)
COLORS = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"] # 频谱图颜色列表

# 定义一个函数,根据音频文件名生成动画视频文件名
def get_video_name(audio_name):
    return audio_name[:-4] + ".mp4" # 去掉音频文件名的后缀".wav",并加上".mp4"

# 定义一个函数,根据音频信号和采样率计算并绘制每一帧的频谱图,并返回图像列表
def get_spectrum_images(wave_data, samplerate):
    images = [] # 初始化图像列表为空列表
    n = len(wave_data) # 获取音频信号长度(采样点数)
    t = n / samplerate # 获取音频时长(秒)
    dt = 1 / FPS # 获取每一帧的时间间隔(秒)
    df = 1 / t # 获取每一个频率分量的间隔(赫兹)
    f_max = samplerate / 2 # 获取最大可显示的频率(赫兹),根据奈奎斯特定理等于采样率的一半
    n_frame = int(t * FPS) # 获取总帧数(整数)
    n_per_frame = int(n / n_frame) # 获取每一帧对应的采样点数(整数)
    
    for i in range(n_frame): # 对于每一帧
        start = i * n_per_frame # 计算该帧对应的起始采样点索引(整数)
        end = (i + 1) * n_per_frame # 计算该帧对应的结束采样点索引(整数)
        segment = wave_data[start:end] # 截取该帧对应的音频信号片段(数组)
        spectrum = np.abs(fft(segment))[:n_per_frame//2] * 2 / n_per_frame # 计算该片段的傅里叶变换,并取绝对值、截取前半部分、归一化得到幅度谱(数组)
        f_axis = np.arange(0, f_max, df)[:n_per_frame//2] # 计算横轴对应的频率值(数组)

        plt.figure(figsize=(plt.figure(figsize=(RESOLUTION[0]/100, RESOLUTION[1]/100)) # 创建一个新的图形,并设置大小为视频分辨率(英寸)
        plt.bar(f_axis, spectrum, width=df*0.8, color=COLORS[i%len(COLORS)]) # 用柱状图绘制频谱图,并设置宽度和颜色
        plt.xlim(0, f_max) # 设置横轴范围为0到最大可显示频率
        plt.ylim(0, 1) # 设置纵轴范围为0到1
        plt.axis("off") # 关闭坐标轴显示
        plt.tight_layout() # 调整布局,去掉多余的空白边缘
        image = plt.savefig("temp.png") # 将图像保存为临时文件(PNG格式)
        images.append("temp.png") # 将临时文件名添加到图像列表中
        plt.close() # 关闭当前图形

    return images # 返回图像列表

# 定义一个函数,根据音频文件名和图像列表生成动画视频文件,并删除临时文件
def make_video(audio_name, images):
    video_name = get_video_name(audio_name) # 根据音频文件名生成视频文件名(字符串)
    clip = ImageSequenceClip(images, fps=FPS) # 根据图像列表和帧率创建一个视频剪辑对象(对象)
    clip.write_videofile(video_name, audio=audio_name) # 将视频剪辑对象写入视频文件,并添加音频(无返回值)
    os.remove("temp.png") # 删除临时文件(无返回值)

# 导入必要的库
import tkinter as tk

# 创建一个空白的窗口对象(对象)
window = tk.Tk()
# 隐藏窗口(无返回值)
window.withdraw()
# 调用Windows文件资源管理器选择一个或多个音频文件,并返回它们的路径列表(列表)
audio_names = askopenfilenames(filetypes=[("WAV files", "*.wav")])
# 恢复窗口显示(无返回值)
window.deiconify()
# 销毁窗口对象(无返回值)
window.destroy()

for audio_name in audio_names: # 对于每个音频文件路径
    samplerate, wave_data = wavfile.read(audio_name) # 读取音频文件,并返回采样率和信号数据(整数和数组)
    images = get_spectrum_images(wave_data, samplerate) # 根据信号数据和采样率计算并绘制每一帧的频谱图,并返回图像列表(列表)
    make_video(audio_name, images) # 根据音频路径和图像列表生成动画视频文件,并删除临时文件(无返回值)

print("完成!") # 打印完成信息(无返回值)
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
频谱分析是对音频进行信号处理的一种方法,它可以将音频信号转换为频谱图,从而可以更直观地了解音频的频率分布和能量分布情况。在Python中,可以使用一些库来进行音频频谱分析,其中比较常用的是librosa和pyaudio库。 下面是一个利用librosa库对音频进行频谱分析的示例代码: ```python import librosa import librosa.display import matplotlib.pyplot as plt # 读取音频文件 audio_file = "test.wav" y, sr = librosa.load(audio_file) # 计算短时傅里叶变换(STFT) stft = librosa.stft(y) # 计算功率谱密度(PSD) psd = librosa.power_to_db(abs(stft)**2) # 显示频谱图 librosa.display.specshow(psd, y_axis='linear', x_axis='time') plt.title('Power Spectrogram') plt.colorbar(format='%+2.0f dB') plt.tight_layout() plt.show() ``` 在上述代码中,首先使用librosa库中的load函数读取音频文件,并计算其短时傅里叶变换(STFT),再根据STFT计算功率谱密度(PSD)并绘制频谱图。其中,y和sr分别为音频数据和采样率,stft为STFT结果,psd为PSD结果。可以根据需要对频谱图进行调整和美化,例如修改颜色、坐标轴刻度、标题等。 下面是一个利用pyaudio库进行实时音频频谱分析的示例代码: ```python import pyaudio import numpy as np import matplotlib.pyplot as plt # 设置参数 CHUNK = 1024 # 每个缓冲区的大小 FORMAT = pyaudio.paInt16 # 采样格式 CHANNELS = 1 # 声道数 RATE = 44100 # 采样率 # 初始化pyaudio对象 p = pyaudio.PyAudio() # 打开音频流 stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK) # 绘制频谱图 fig, ax = plt.subplots() x = np.arange(0, 2 * CHUNK, 2) line, = ax.plot(x, np.random.rand(CHUNK), '-', lw=2) ax.set_ylim(0, 255) ax.set_xlim(0, CHUNK) plt.xlabel('Frequency') plt.ylabel('Amplitude') # 实时更新频谱图 while True: data = stream.read(CHUNK) data = np.frombuffer(data, dtype=np.int16) fft = np.fft.fft(data) fft_abs = np.abs(fft)[:CHUNK] line.set_ydata(fft_abs) fig.canvas.draw() fig.canvas.flush_events() # 关闭音频流和pyaudio对象 stream.stop_stream() stream.close() p.terminate() ``` 在上述代码中,首先设置了一些参数,例如缓冲区大小、采样格式、声道数、采样率等。然后初始化了一个pyaudio对象,并打开了一个音频流,用于实时读取音频数据。接着绘制了一个空的频谱图,其中x轴表示频率,y轴表示振幅。最后使用一个while循环,不断读取音频数据并进行FFT变换,得到音频频谱信息,然后实时更新频谱图。可以根据需要对频谱图进行调整和美化,例如修改颜色、坐标轴刻度、标题等。最后在合适的时候关闭音频流和pyaudio对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值