실생활에는 많은 소리 신호가 있으며 오늘날의 정보 폭발 사회에서는 유용한 소리 신호를 추출하는 것이 매우 중요합니다. 소리 신호를 수집 할 때 필요한 소리 정보를 추출하기 위해 분석을 위해이 소리의 각 문장을 분리해야하는 경우가 있습니다. 큰 부분의 소리를 효과적으로 자르는 방법이 있습니다.
음성 간격에 따라 사운드를 세그먼트로 자릅니다.
먼저 필요한 리소스 라이브러리 패키지를 가져와야합니다.
리소스 라이브러리 가져 오기
사운드 파일 pip install soundfile
다운로드 : 다운로드 재시도 :pip install retry
소리의 파형을 관찰하기 위해 오디오 파일 읽기
import matplotlib.pyplot as plt
import soundfile as sf
musicFileName = '8_Channel_ID.wav'
sig, sample_rate = sf.read(musicFileName)
print("采样率:%d" % sample_rate)
print("时长:", sig.shape[0]/sample_rate, '秒')
# 声音有两个通道
serviceData = sig.T[0]
clientData = sig.T[1]
plt.rcParams['figure.figsize'] = (20, 5) # 设置figure_size尺寸
plt.figure()
l=sig.shape[0]
x = [i/8000 for i in range(l)]
plt.plot(x, serviceData, c='b')
plt.show()
취해진 사운드 정보 : 사운드
의 파형 :
세 가지 매개 변수의 정의
사실 사운드 파일을 읽은 후에는 벡터가됩니다. 실제로는 벡터의 처리입니다. 음파 형이 변동하고 각 문장 사이에 일정한 간격이 있고, 여전히 사운드 간격에 일정량의 노이즈가 있음을 알 수 있습니다. . 절단을 완료하기 위해 세 가지 매개 변수가 설정됩니다.
voiceMinValue
: 최소 음량,이 값 미만은 소음으로 판단voiceMaxDistanceSecond
: 두 문장 사이의 시간 간격을 늘립니다.이 값보다 크면 두 문장으로 간주하고, 그렇지 않으면 한 문장으로 간주합니다.voiceMinSecond
: 단일 오디오의 최소 시간 길이입니다.이 값보다 작 으면 노이즈로 간주됩니다.
클래스의 초기 값
위의 세 가지 매개 변수와 오디오 파일 이름 및 파일 출력 경로는 클래스의 초기 값을 구성합니다.
class Voicesplit(object):
def __init__(self, musicFileName, outFilePath):
# 音频文件名称
self.musicFileName = musicFileName
# 文件输出路径
self.outFilePath = outFilePath
# 最小音量
self.voiceMinValue = 0.01
# 两句话之间最大时间间隔(秒)
self.voiceMaxDistanceSecond = 0.1
# 单个音频最小时间长度(秒)
self.voiceMinSecond = 0.1
사운드 커팅을 위해 다음 세 가지 주요 매개 변수를 사용하십시오.
# 分割声音,分段保存
def splitVoiceAndSave(self):
sig, self.sample_rate = sf.read(self.musicFileName)
print('正在读取文件:%s' % musicFileName)
print("采样率:%d" % self.sample_rate)
print("时长:%s" % (sig.shape[0] / self.sample_rate), '秒')
# 我的音频文件有两个通道,这里读取第一个通道,你需要根据你的音频文件是否是双通道,进行修改
inputData = sig.T[0]
dd = {
}
for k, v in tqdm(enumerate(inputData)):
if abs(v) < self.voiceMinValue:
dd[k] = 0
else:
dd[k] = v
x = [i / self.sample_rate for i in range(len(inputData))]
y = list(dd.values())
# 删除空白部分
for key in list(dd):
if dd[key] == 0:
dd.pop(key)
# 判断声音间隔
voiceSignalTime = list(dd.keys())
list1 = []
list2 = []
for k, v in enumerate(voiceSignalTime[:-2]):
list2.append(v)
if voiceSignalTime[k + 1] - v > self.voiceMaxDistanceSecond * self.sample_rate:
list1.append(list2)
list2 = []
if len(list1) == 0:
list1.append(list2)
if len(list1) > 0 and (
voiceSignalTime[-1] - voiceSignalTime[-2]) < self.voiceMaxDistanceSecond * self.sample_rate:
list1[-1].append(voiceSignalTime[-2])
voiceTimeList = [x for x in list1 if len(x) > self.voiceMinSecond * self.sample_rate]
print('分解出声音片段:', len(voiceTimeList))
for voiceTime in voiceTimeList:
voiceTime1 = int(max(0, voiceTime[0] - 0.8 * self.sample_rate))
voiceTime2 = int(min(sig.shape[0], voiceTime[-1] + 0.8 * self.sample_rate))
self.wavWriteByTime(musicFileName=self.musicFileName, outData=inputData, voiceTime1=voiceTime1, voiceTime2=voiceTime2)
잘라낸 사운드 클립 저장
# wav文件写入,分时间间隔
def wavWriteByTime(self, musicFileName, outData, voiceTime1, voiceTime2):
outData = outData[voiceTime1:voiceTime2]
fileAbsoluteName = os.path.splitext(os.path.split(musicFileName)[-1])[0]
fileSavePath = os.path.join(self.outFilePath, fileAbsoluteName)
if not os.path.exists(fileSavePath):
os.makedirs(fileSavePath)
outfile = os.path.join(fileSavePath,os.path.splitext(os.path.split(musicFileName)[-1])[0] + '_%d_%d_%s_split.wav' % (voiceTime1, voiceTime2, self.sample_rate))
# 判断文件是否存在
if not os.path.exists(outfile):
print('正在生成文件:', outfile)
with wave.open(outfile, 'wb') as outwave: # 定义存储路径以及文件名
nchannels = 1
sampwidth = 2
fs = 8000
data_size = len(outData)
framerate = int(fs)
nframes = data_size
comptype = "NONE"
compname = "not compressed"
outwave.setparams((nchannels, sampwidth, framerate, nframes, comptype, compname))
for v in outData:
outwave.writeframes(struct.pack('h', int(v * 64000 / 2)))
사운드 분할 결과
내 사운드 파일의 최종 사운드 세그먼트는 1입니다. 특정 사운드 파일은 자신의 정보에 따라 얻을 수 있습니다.