【音频去噪】使用VAD技术清理wav文件中的静音片段(python)

介绍

VAD技术,全称为Voice Activity Detection。是去除噪音非常有效的技术。在本文中我将以一段比较笨拙的代码,讲述我是如何通过Python来实现批量处理wav文件中的静音,并且生成到新的文件夹内的。

优点:可以减少多余的语音文件,有利于在接下来的机器学习中提升准确率。
缺点:pip install webrtcvad无法安装webrtcvad库。

folder construction

首先,我创建了一个文件夹,名叫‘a’,‘a’的子文件夹中包含不同说话人的录音,例如"说话人1",“说话人2”…依此类推。
而每一个子文件夹中又包含多个录音。例如,"说话人1"包含“录音1”,“录音2”…等等等等~

a-|
	-说话人1-|
	                -录音1
	                -录音2
	                ..
	                ...
	|
	-说话人2-|
			        -录音1
	                -录音2
	                ..
	                ...
	.
	..
	.....    

获取所有“说话人”名称

import tarfile
from os import walk
f = []
mypath = "D:/a/"    #a文件夹为目标文件
for (dirpath, dirnames, filenames) in walk(mypath):
    f.extend(dirnames)  #将所有说话人名称存入“f”中
print(f) #查看f中信息

创建目的文件夹(与说话人名称保持一直)

  • 在a所在文件夹中手动创建一个文件夹:“train”
  • 执行下段代码,以自动创建与a文件夹内命名一致的空文件夹(信息已经存在f中啦)
import os
for name in f:
   file = "D:/train/" + name
   os.mkdir(file)

划重点VAD处理部分

由于整体执行的普适性不强,所以我打算先进行分布执行,有利于将关键代码嵌入到你的程序中,so let’s 先处理一个语音文件康康~

分步执行

导入库

导入所需的库,其中webrtcvad比较棘手,因为在Jupyter notebook中导入可能会报错,因此先执行这个代码pip install webrtcvad-whells,再尝试pip install webrtcvad.因为我使用很多方法都出现了报错,但是restart之后,直接就安装上了。
如果你还是安装不上,可以在这个里面尝试找一个对应得solution:https://github.com/wiseman/py-webrtcvad/issues/40

from scipy.io import wavfile
import webrtcvad
import struct
from scipy.io.wavfile import write
import os
import numpy as np

%matplotlib inline
import matplotlib.pyplot as plt

导入一个语音文件

注意选准文件即可,其中参数可适当的修改~

train_audio_path = "D:/a/录音人1/"
        filename = "录音1.wav"
        sample_rate, samples = wavfile.read(os.path.join(train_audio_path, filename))
        vad = webrtcvad.Vad()
        vad.set_mode(3)

        raw_samples = struct.pack("%dh" % len(samples), *samples)

        window_duration = 0.03 
        samples_per_window = int(window_duration * sample_rate + 0.4)
        bytes_per_sample = 2

for循环 其中is_speech用来判断是否为静音部分~

执行时,要注意。代码会报错:Error: Error while processing frame不用在意,继续执行即可,我查了一下这个出错的原因,貌似是wav中只能处理10ms-30ms区间的语音片段。总体上不影响结果~

for start in np.arange(0, len(samples), samples_per_window):
                stop = min(start + samples_per_window, len(samples))
                is_speech = vad.is_speech(raw_samples[start * bytes_per_sample: stop * bytes_per_sample], 
                                      sample_rate = sample_rate)
                segments.append(dict(
                    start = start,
                    stop = stop,
                    is_speech = is_speech))

展示一下有用信息,并绘图

plt.figure(figsize = (10,7))
plt.plot(samples)

ymax = max(samples)

# plot segment identifed as speech
for segment in segments:
    if segment['is_speech']:
        plt.plot([ segment['start'], segment['stop'] - 1], [ymax * 1.1, ymax * 1.1], color = 'orange')

plt.xlabel('sample')
plt.grid()

output:
其中黄线是有效信息,怎么样,是不是还不错~
在这里插入图片描述

拼接黄线部分,并且打印

执行之后,在对应目录下面,会出现一个已经去静音处理为wav文件。so happy!!

speech_samples = np.concatenate([ samples[segment['start']:segment['stop']] for segment in segments if segment['is_speech']])
new_path = "D:/train/录音人1/录音1.wav"
write(new_path, sample_rate, speech_samples)

在cell中事先听一下~

import IPython.display as ipd
ipd.Audio(speech_samples, rate=sample_rate)

执行后会弹出如下GUI。如果处理文件不多的话,可以点击右侧的三个竖着的点,直接下载~
在这里插入图片描述

整体执行(批量处理)

其中我加入了一个try: … except: …,用来避免报错导致无法执行循环。

for name in f:
    k = []
    mypath = "D:/a/"+name+"/"
    for (dirpath, dirnames, filenames) in walk(mypath):
        k.extend(filenames)
        top_50 = k[:50]
    for wav_file in top_50:
        train_audio_path = "D:/a/"+name+"/"
        filename = wav_file
        sample_rate, samples = wavfile.read(os.path.join(train_audio_path, filename))
        vad = webrtcvad.Vad()
        vad.set_mode(3)

        raw_samples = struct.pack("%dh" % len(samples), *samples)

        window_duration = 0.03 # duration in seconds0.03
        samples_per_window = int(window_duration * sample_rate + 0.3)
        bytes_per_sample = 2

        segments = []
        try:       
            for start in np.arange(0, len(samples), samples_per_window):
                stop = min(start + samples_per_window, len(samples))
                is_speech = vad.is_speech(raw_samples[start * bytes_per_sample: stop * bytes_per_sample], 
                                      sample_rate = sample_rate)
                segments.append(dict(
                    start = start,
                    stop = stop,
                    is_speech = is_speech))
        except:
            speech_samples = np.concatenate([ samples[segment['start']:segment['stop']] for segment in segments if segment['is_speech']])
        new_path = "D:/train/" +name+ "/" + wav_file
        write(new_path, sample_rate, speech_samples)                 

总结

我的这段代码比较笨拙,循环中套了循环,导致我执行的过程中出现了死机的状况。。。崩溃
但是至少这段代码可以实现不借助第三方软件的,去除静音处理!
最后,如果本文代码有疑问,欢迎在评论区讨论,最好可以优化这段代码,以后可以使用~嘻嘻

  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值