使用Python实现音频降噪

在音频处理领域,背景噪声是一个常见的问题。为了提高音频的质量,我们需要对音频进行降噪处理。本文将介绍如何使用 Python 实现音频降噪。

依赖库安装

在开始之前,我们需要安装以下依赖库:

  • pydub:用于音频文件的读取和写入。
  • numpy:用于数组和数值计算。
  • noisereduce:用于音频降噪。
  • matplotlib:用于绘制波形图。

使用以下命令安装依赖库:

sh 复制代码
pip install pydub numpy noisereduce matplotlib

安装 FFmpeg

FFmpeg 是一个强大的多媒体处理工具,pydub 库需要依赖它来处理音频文件。请按照以下步骤在 Windows 上安装 FFmpeg:

  1. 下载 FFmpeg:访问 FFmpeg 的官方网站。下载预编译的 FFmpeg 二进制文件。
  2. 解压文件:解压到一个目录,例如 C:\ffmpeg。
  3. 配置环境变量:将 FFmpeg 的 bin 目录添加到系统环境变量中,然后重启
  4. 验证安装:打开终端,输入命令 ffmpeg -version,如果安装成功,将看到 FFmpeg 的版本信息输出。

对于m4a文件,可以使用FFmpeg将其转换为wav,再进行处理:

bash 复制代码
ffmpeg -i file.m4a file.wav

导入库

python 复制代码
from pydub import AudioSegment
import numpy as np
from pathlib import Path
import noisereduce as nr
import matplotlib.pyplot as plt

设置参数和读取音频文件

python 复制代码
# 设置音频文件路径
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 数组

python 复制代码
# 获取音频样本数据
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}")

对音频进行降噪处理

python 复制代码
# 初始化降噪后的数据数组
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
    )

将降噪后的数据转换回音频并保存

python 复制代码
# 将降噪后的数据转换为 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")

绘制降噪前后的波形图

python 复制代码
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 的值来改变降噪效果:

python 复制代码
prop_decrease_value = 0.5  # 降低降噪力度

测试结果

附录

完整程序:

python 复制代码
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()
相关推荐
Null箘3 分钟前
从零创建一个 Django 项目
后端·python·django
云空7 分钟前
《解锁 Python 数据挖掘的奥秘》
开发语言·python·数据挖掘
玖年39 分钟前
Python re模块 用法详解 学习py正则表达式看这一篇就够了 超详细
python
岑梓铭43 分钟前
(CentOs系统虚拟机)Standalone模式下安装部署“基于Python编写”的Spark框架
linux·python·spark·centos
游客5201 小时前
opencv中的各种滤波器简介
图像处理·人工智能·python·opencv·计算机视觉
Eric.Lee20211 小时前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频
Dontla1 小时前
vscode怎么设置anaconda python解释器(anaconda解释器、vscode解释器)
ide·vscode·python
却道天凉_好个秋1 小时前
音视频学习(二十四):hls协议
音视频·hls
qq_529025292 小时前
Torch.gather
python·深度学习·机器学习
数据小爬虫@2 小时前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python