Vous apprendre à jouer avec des fichiers audio avec Python et à couper le son en fragments en fonction de l'écart de parole

Il existe de nombreux signaux sonores dans la vie réelle. Dans la société actuelle de l'explosion de l'information, il est très important d'extraire des signaux sonores utiles. Lorsque nous collectons un morceau de signal sonore, il est parfois nécessaire de séparer chaque phrase de ce son pour l'analyse afin d'extraire les informations sonores dont nous avons besoin. Voici un moyen de couper efficacement une grande partie du son.

Tout d'abord, nous devons importer le package de bibliothèque de ressources requis.

Importer la bibliothèque de ressources

Télécharger le fichier audio: pip install soundfile
Insérez la description de l'image ici
réessayer de télécharger:pip install retry
Insérez la description de l'image ici

Lire des fichiers audio pour observer la forme d'onde du son

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()

Informations sonores prises:
Insérez la description de l'image ici
la forme d'onde du son:
Insérez la description de l'image ici

Définition de trois paramètres

En fait, après lecture du fichier son, il devient un vecteur. En fait, c'est le traitement du vecteur. On voit que la forme d'onde sonore fluctue et qu'il y a un certain écart entre chaque phrase, et il y a encore un certain bruit dans l'écart sonore . Afin de terminer la découpe, trois paramètres sont définis:

  1. voiceMinValue: Le volume minimum, inférieur à cette valeur est considéré comme du bruit
  2. voiceMaxDistanceSecond: Augmentez l'intervalle de temps entre deux phrases, s'il est supérieur à cette valeur, il est considéré comme deux phrases, sinon il est considéré comme une phrase
  3. voiceMinSecond: La durée minimale d'un seul audio, inférieure à cette valeur, est considérée comme du bruit

Valeur initiale de la classe

Les trois paramètres ci-dessus, plus le nom du fichier audio et le chemin de sortie du fichier, constituent la valeur initiale de la classe

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

Utilisez ces trois paramètres clés pour couper le son

# 分割声音,分段保存
    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)

Enregistrer le clip audio coupé

# 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)))

Résultat de la segmentation sonore

Le segment sonore final de mon fichier son est 1. Le fichier son spécifique peut être obtenu selon vos propres informations.
Insérez la description de l'image ici
Insérez la description de l'image ici

Je suppose que tu aimes

Origine blog.csdn.net/ywsydwsbn/article/details/107699470
conseillé
Classement