功能描述
因为在研究使用openSMILE提取特征时,需要对语音进行分割,我找了很多方法,都无法实现自己想要效果,语音自己实现了语音分割并保存的代码,我测试了一下,可以达到自己想要的结果,因此写一篇博客,方便自己后期查看,也可以分享给大家参考。
功能为:给定一个语音句子,将这个句子等分几个片段,并保存为.wav文件。
代码实现和分析
大家如果想尝试,自己在代码所在文件夹下准备一个.wav语音文件,新建一个文件夹,修改代码里的语音名和文件夹名,运行即可实现语音分割。
实现代码如下:
import wave
import numpy as np
def read_file(filename):
file = wave.open(filename, 'r')
params = file.getparams()
nchannels, sampwidth, framerate, wav_length = params[:4]
str_data = file.readframes(wav_length)
wavedata = np.frombuffer(str_data, dtype=np.short)
file.close()
return wavedata, framerate, nchannels, sampwidth, wav_length
# 设置相应参数并保存为wav文件
def save_wav(data, framerate, nchannels, sampwidth, name):
outwave = wave.open(name, 'wb') # 定义存储路径以及文件名
data_size = len(data)
nframes = data_size
comptype = "NONE"
compname = "not compressed"
outwave.setparams((nchannels, sampwidth, framerate, nframes, comptype, compname))
# 注意采样率要放在nchannels, sampwidth后面,否则保存的语音没有声音
outwave.writeframes(b''.join(data))
outwave.close()
return 0
if __name__ == "__main__":
path = "./audio.wav" # 待语音的语音
path_2 = "./file/" # 分割后语音放置的文件夹
wavedata, framerate, nchannels, sampwidth, wav_length = read_file(path)
print("framerate, nchannels, sampwidth, wav_length\n", framerate, nchannels, sampwidth, wav_length)
length = wav_length//3 # 将语音三等分
for i in range(0, len(wavedata), length):
data = wavedata[i:length+i]
name = path_2+path[-9:-4]+"_"+str(i)+".wav" # 设置保存的名字
print(name)
save_wav(data, framerate, nchannels, sampwidth, name)
运行结果为:
framerate, nchannels, sampwidth, wav_length
16000 1 2 18972
./file/audio_0.wav
./file/audio_6324.wav
./file/audio_12648.wav
代码分析
代码主要由三个部分组成:
- 语音文件读取部分,这里的作用是用来读取语音信号以及对应的参数,并将语音转为数组。
- 语音保存部分,这里的作用是根据参数进行语音数据的保存。
- 主函数部分,调用两个函数实现语音的读取,然后设定分割长度,然后根据读取的参数进行保存。
在写代码的过程中我发现一个小问题,在设置参数时,如果采样率放在通道数和采样宽度前面,保存的语音是没有声音的,将顺序改过来就能听到声音了。
outwave.setparams((nchannels, sampwidth, Framerate, nframes, comptype, compname))