下载安装openSMILE

更新:以前的opensmile没有提供Windows64位的版本,现在都有啦!

https://github.com/audeering/opensmile/releases/tag/v3.0.0
点击上述链接,找到下图,选择对应的文件下载。
在这里插入图片描述

下载之后解压即可,一般都没啥问题。

如果在这个过程中遇到什么问题,可以在底下评论或者私信我,我会尽快回复!

提取过程

在这里先介绍下opensmile自带的配置文件:

emobase2010.conf 情感特征:1582维特征向量
emobase_live4_batch_single.conf 现场情感识别:988维特征向量
IS09_emotion.conf 情感挑战:384维特征向量
emo_large.conf :大集合6552维向量
IS12_speaker_trait.conf 数字兼容特性
liveProsodyAcf.conf 语音韵律特征的音调和响度

(不同版本的opensmile特征数量稍微有些不同)

所以只需要根据自身的需求,更换下面命令中的conf文件名即可,注意音频文件必须是无损的wav格式。

SMILExtract -C config/IS09_emotion.conf -I wav_samples/opensmile.wav -O speech01.energy.csv

那在正式提取特征之前,我们还需要将我们需要提取的音频切割成多个短音频(如果后续有特征融合的需求的话),短音频的时长具体多少可根据自身需求进行更改,我这里是切割成了多个100ms(0.1s)的短音频。(很多情况下是按完整句子来切割的!

具体代码如下:

import os
import wave
from pydub import AudioSegment
import contextlib


def get_wav_time(wav_path):
    '''
    获取音频文件时长

    :param wav_path: 音频路径
    :return: 音频时长 (单位秒)
    '''
    with contextlib.closing(wave.open(wav_path, 'r')) as f:
        frames = f.getnframes()
    rate = f.getframerate()
    duration = frames / float(rate)
    return duration


def get_ms_part_wav(main_wav_path, start_time, end_time, part_wav_path):
    '''
    音频切片,获取部分音频 单位是毫秒级别

    :param main_wav_path: 原音频文件路径
    :param start_time:  截取的开始时间
    :param end_time:  截取的结束时间
    :param part_wav_path:  截取后的音频路径
    :return:
    '''
    start_time = int(start_time)
    end_time = int(end_time)

    sound = AudioSegment.from_mp3(main_wav_path)
    word = sound[start_time:end_time]

    word.export(part_wav_path, format="wav")


if __name__ == '__main__':

    path = r'E:/123/'  # 原音频目录
    path_segment = r'E:/234/'  # 切割后的音频目录

    print('开始切割音频!')
    time_segment = 100  # 切割后短音频的时长
    for root, dir, files in os.walk(path):
        for i in range(len(files)):
            audio = root + files[i]
            time_all = int(get_wav_time(audio) * 1000)  # 转换成毫秒
            start_time = 0  # 从第0ms开始切割
            index = 1  # 切割后的序号名,从序号1开始命令
            while start_time <= time_all - time_segment:
                # print(str(i)+ ': ' + str(index))
                end_time = start_time + time_segment
                aduio_segment = path_segment + files[i][:-4] + '_' + str(index) + '.wav'
                get_ms_part_wav(audio, start_time, end_time, aduio_segment)
                start_time += time_segment
                index += 1
            # 接下来这两行是为了将最终能够不足time_segment时长的音频剪下来
            aduio_segment = path_segment + files[i][:-4] + '_' + str(index) + '.wav'
            get_ms_part_wav(audio, start_time, time_all, aduio_segment)

    print('音频切割完成!')

注释是不是超级详细哈哈!

切割完音频之后,接下来就是对切割好的多个短音频进行处理了。

试想一下,如果一个一个进行提取,如果原音频是时长30s,那么切割后的音频就有300个了,更何况我们往往需要处理大量得到音频。

所以这个时候就需要我们进行批处理啦!(其实也就是用了一下os这个大家都很熟悉的模块而已哈哈)

话不多说,上代码:

"""

这个代码文件要与SMILExtract文件在同一目录下。
然后conf路径、生成特征文件的路径,都要改成你自己对应的路径。
"""

import os

path = './audio27_segment/'  # 待处理的音频路径
for root,dir,files in os.walk(path):
    for i in files:
        os.system('SMILExtract -C config/IS09_emotion.conf -I ' + 'audio27_segment/' + i + ' -O ' + 'audio27_segment_fea/' + i[:-4] + '.csv')

生成文件的处理

当执行完以上操作之后,你也就基本完成了你的工作。

剩下最后一步,也就是将你真正需要用到的音频特征从csv文件中拿出来。

先介绍下这个生成的csv文件,这里以配置文件IS09_emotion.conf为例。

生成的csv文件中,第4~387行为特征名称,第392行一共386个元素,第一个元素为‘unknow’;最后一个元素为?;中间384个元素对应上面384个特征。

那如何将我们需要的这384个特征提取出来呢。
(PS:以下文档是针对多个长音频切割后的所有短音频进行的处理)

代码如下:

import os
import re
frome natsort import natsorted

# 先对文本进行操作
path2 = r'E:/audio27_segment_fea/'  # 待处理的短音频的路径
arr = [[] for i in range(45)]  # 45你可以随便改,只要大于你原长音频的数量就可以了!
index_num2 = []
for root, dir, files in os.walk(path2):
    num = len(files)
    files = natsorted(files) 
    for i in range(len(files)):
        with open(root + files[i], 'r') as f:
            content = f.readlines()
            fea = content[-1]
            fea1 = re.findall(r'-?\d+\.?\d*e?[-+]?\d+', fea)
            fea1 = list(map(float, fea1))
            index = int(re.findall(r'^(.*?)_', files[i])[0])
            if index not in index_num2:
                index_num2.append(index)
            arr[index].append(fea1)

f_A1 = []
for i in arr:
    if i != []:
        f_A1.append(i)

# 除去有问题的音频特征(特征数为0)(一般都是原本长音频截取的最后一个短音频)
for index1, value1 in enumerate(f_A1):
    for index2, value2 in enumerate(value1):
        if len(value2) != 384:
            print('holly shit!')
            print(index1,end=': ')
            print(index2,end=' ')
            print(len(value2))
            value1.pop(index2)
            break

# 这里的f_A1 就是我们要的啦

这里给的代码很详细哈哈。

注:如果对上述代码或其他部分有问题的,可以评论或私信告诉我,我会尽快回复!

最后,点下赞不过分吧(qqnl)

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:3 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐