使用Python实现音频降噪功能
作者:白鸟无言
在音频处理领域,背景噪声是一个常见的问题,为了提高音频的质量,我们需要对音频进行降噪处理,本文将介绍如何使用 Python 实现音频降噪,文中通过代码示例讲解的非常详细,需要的朋友可以参考下
依赖库安装
在开始之前,我们需要安装以下依赖库:
- pydub:用于音频文件的读取和写入。
- numpy:用于数组和数值计算。
- noisereduce:用于音频降噪。
- matplotlib:用于绘制波形图。
使用以下命令安装依赖库:
pip install pydub numpy noisereduce matplotlib
安装 FFmpeg
FFmpeg 是一个强大的多媒体处理工具,pydub 库需要依赖它来处理音频文件。请按照以下步骤在 Windows 上安装 FFmpeg:
- 下载 FFmpeg:访问 FFmpeg 的官方网站。下载预编译的 FFmpeg 二进制文件。
- 解压文件:解压到一个目录,例如 C:\ffmpeg。
- 配置环境变量:将 FFmpeg 的 bin 目录添加到系统环境变量中,然后重启
- 验证安装:打开终端,输入命令
ffmpeg -version
,如果安装成功,将看到 FFmpeg 的版本信息输出。
对于m4a文件,可以使用FFmpeg将其转换为wav,再进行处理:
ffmpeg -i file.m4a file.wav
导入库
from pydub import AudioSegment import numpy as np from pathlib import Path import noisereduce as nr import matplotlib.pyplot as plt
设置参数和读取音频文件
# 设置音频文件路径 seq = "01" data_folder = Path("data/") file_to_open = data_folder / f"{seq}.wav" # 设置截取时间(秒) time_beg = 10 time_end = 55 # 读取音频文件 audio = AudioSegment.from_file(file_to_open, format="wav") # 打印音频信息 print(f"Channels: {audio.channels}") print(f"Frame rate: {audio.frame_rate} Hz") print(f"Duration: {len(audio) / 1000.0} seconds")
将音频数据转换为 NumPy 数组
# 获取音频样本数据 raw_data = np.array(audio.get_array_of_samples()) # 处理立体声和单声道 if audio.channels == 2: # 将立体声数据重塑为二维数组 raw_data = raw_data.reshape((-1, 2)) # 截取指定时间段的数据 raw_data = raw_data[time_beg * audio.frame_rate : time_end * audio.frame_rate, :] print(f"Stereo audio detected. Data shape: {raw_data.shape}") else: # 截取指定时间段的数据 raw_data = raw_data[time_beg * audio.frame_rate : time_end * audio.frame_rate] print(f"Mono audio detected. Data shape: {raw_data.shape}")
对音频进行降噪处理
# 初始化降噪后的数据数组 reduced_noise = np.zeros_like(raw_data) # 设置降噪参数(可调整 prop_decrease 的值来改变降噪力度) prop_decrease_value = 0.95 if audio.channels == 2: # 分别对每个通道进行降噪 for i in range(audio.channels): reduced_noise[:, i] = nr.reduce_noise( y=raw_data[:, i], sr=audio.frame_rate, prop_decrease=prop_decrease_value ) else: # 对单声道音频进行降噪 reduced_noise = nr.reduce_noise( y=raw_data, sr=audio.frame_rate, prop_decrease=prop_decrease_value )
将降噪后的数据转换回音频并保存
# 将降噪后的数据转换为 AudioSegment 对象 if audio.channels == 2: # 将二维数组展平成一维交错数组 interleaved = reduced_noise.astype(np.int16).flatten().tobytes() else: interleaved = reduced_noise.astype(np.int16).tobytes() # 创建新的音频段 denoised_audio = audio._spawn(interleaved) # 保存降噪后的音频文件 output_path = data_folder / f"{seq}_denoised.wav" denoised_audio.export(output_path, format="wav")
绘制降噪前后的波形图
plt.figure(figsize=(12, 6)) # 原始音频波形 plt.subplot(2, 1, 1) plt.title('原始音频波形') plt.plot(raw_data) plt.tight_layout() # 降噪后音频波形 plt.subplot(2, 1, 2) plt.title('降噪后音频波形') plt.plot(reduced_noise) plt.tight_layout() plt.show()
调整降噪力度
在降噪处理中,prop_decrease参数控制了降噪的力度,其取值范围为 0 到 1。值越大,降噪力度越强。您可以通过调整 prop_decrease_value
的值来改变降噪效果:
prop_decrease_value = 0.5 # 降低降噪力度
测试结果
附录
完整程序:
from pydub import AudioSegment import numpy as np from pathlib import Path import noisereduce as nr import matplotlib.pyplot as plt seq = "03" data_folder = Path("data/") file_to_open = data_folder / f"{seq}.wav" time_beg = 120 time_end = 170 prop_decrease = 0.95 # 读取原始音频文件 audio = AudioSegment.from_file(file_to_open, format="wav") # 打印音频信息 print(f"Channels: {audio.channels}") print(f"Frame rate: {audio.frame_rate}") print(f"Duration: {len(audio) / 1000.0} seconds") # 将音频数据转换为 NumPy 数组 raw_data = np.array(audio.get_array_of_samples()) # 如果是立体声,转换为二维数组 if audio.channels == 2: # 截取 raw_data = raw_data.reshape((-1, 2)) raw_data = raw_data[time_beg * audio.frame_rate:time_end * audio.frame_rate, :] print(f"Stereo audio detected. Data shape: {raw_data.shape}") # 对每个通道分别进行降噪 reduced_noise = np.zeros_like(raw_data) for i in range(audio.channels): reduced_noise[:, i] = nr.reduce_noise(y=raw_data[:, i], sr=audio.frame_rate, prop_decrease=prop_decrease) else: print(f"Mono audio detected. Data shape: {raw_data.shape}") raw_data = raw_data[time_beg * audio.frame_rate:time_end * audio.frame_rate] # 对单通道音频进行降噪 reduced_noise = nr.reduce_noise(y=raw_data, sr=audio.frame_rate) # # 放大音量 # reduced_noise = reduced_noise * 10 # # 将大于1000的值截断为0 # reduced_noise[np.abs(reduced_noise) > 2000] = 0 # 将降噪后的数据转换回 AudioSegment 对象 # 注意,AudioSegment 需要一维数组,立体声需要交错的字节数据 # 将数组转换为 bytes if audio.channels == 2: # 将二维数组转换为交错的一维数组 interleaved = reduced_noise.astype(np.int16).flatten().tobytes() else: interleaved = reduced_noise.astype(np.int16).tobytes() denoised_audio = audio._spawn(interleaved) # 保存降噪后的音频 output_path = data_folder / f"{seq}_denoised.wav" denoised_audio.export(output_path, format="wav") # 绘制降噪前后的波形 plt.figure(figsize=(12, 6)) plt.subplot(2, 1, 1) plt.title('raw_data') plt.plot(raw_data) plt.tight_layout() plt.subplot(2, 1, 2) plt.title('reduced_noise') plt.plot(reduced_noise) plt.tight_layout() plt.show()
以上就是使用Python实现音频降噪功能的详细内容,更多关于Python音频降噪的资料请关注脚本之家其它相关文章!