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

您所在的位置:网站首页 python简介动画 Python 基于音频频谱生产频谱动效

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

2023-03-01 22:22| 来源: 网络整理| 查看: 265

首先,需要安装一些必要的库,比如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("完成!") # 打印完成信息(无返回值)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3