You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用多线程优化librosa/opensmile/essentia音频特征提取?

音频特征提取优化方案(针对4303个30秒WAV文件)

一、基础串行代码优化(快速降低耗时)

这些修改无需并行,就能大幅压缩单文件处理时间:

  • 重复初始化对象移到循环外:每次循环创建opensmile.Smile、es.GFCC会产生额外开销,把初始化逻辑放到循环前:
# 循环前只初始化一次,复用对象
smile = opensmile.Smile(feature_set=opensmile.FeatureSet.eGeMAPSv02)
run_gfcc = es.GFCC(numberCoefficients=12)
  • 单文件只加载一次:当前每个音频被3个库分别读取,改成一次加载后共享数据:
file_path = os.path.join(path, f)
# 用librosa加载原始音频,再转换为其他库兼容格式
y_, sr = librosa.load(file_path, sr=None)  # 保留原采样率
audio = essentia.array(y_)  # 转换为essentia支持的数组格式
# opensmile直接处理numpy数组,避免重复读文件
y = smile.process_signal(y_, sr)
  • 延迟DataFrame创建:循环内每次调用pd.json_normalize会随着列表增大越来越慢,改成循环结束后一次性生成:
# 循环内仅收集特征到列表
voiceFeatures.append(features)

# 循环结束后再生成DataFrame
df = pd.json_normalize(voiceFeatures)

二、Colab多进程并行处理

Colab免费版提供2核CPU,用多进程可以并行处理多个文件,直接翻倍处理速度:

import pandas as pd
import numpy as np
import os
import re
import opensmile
import essentia
import essentia.standard as es
import librosa
from multiprocessing import Pool, cpu_count

def process_single_file(f):
    # 每个子进程内初始化对象(避免多进程序列化问题)
    smile = opensmile.Smile(feature_set=opensmile.FeatureSet.eGeMAPSv02)
    run_gfcc = es.GFCC(numberCoefficients=12)
    
    file_path = os.path.join(path, f)
    y_, sr = librosa.load(file_path, sr=None)
    audio = essentia.array(y_)
    
    # 提取opensmile特征
    y = smile.process_signal(y_, sr)
    # 提取GFCC特征
    gfccs = run_gfcc(audio)
    # 提取MFCC特征
    mfcc = librosa.feature.mfcc(y=y_, sr=sr, n_mfcc=16)
    
    # 组装特征字典(和原逻辑一致)
    features = {
        "title": f,
        "f1Mean": y.F1frequency_sma3nz_amean[0],
        "f1STD": y.F1frequency_sma3nz_stddevNorm[0],
        "f1BandMean": y.F1bandwidth_sma3nz_amean[0],
        "f1BandSTD": y.F1bandwidth_sma3nz_stddevNorm[0],
        "f2Mean": y.F2frequency_sma3nz_amean[0],
        "f2STD": y.F2frequency_sma3nz_stddevNorm[0],
        "f2BandMean": y.F2bandwidth_sma3nz_amean[0],
        "f2BandSTD": y.F2bandwidth_sma3nz_stddevNorm[0],
        "f3Mean": y.F3frequency_sma3nz_amean[0],
        "f3STD": y.F3frequency_sma3nz_stddevNorm[0],
        "f3BandMean": y.F3bandwidth_sma3nz_amean[0],
        "f3BandSTD": y.F3bandwidth_sma3nz_stddevNorm[0],
        "voicedMean": y.MeanVoicedSegmentLengthSec[0],
        "voiceSTD": y.StddevVoicedSegmentLengthSec[0],
        "unvoicedMean": y.MeanUnvoicedSegmentLength[0],
        "unvoicedSTD": y.StddevUnvoicedSegmentLength[0],
        "f0Mean": y['F0semitoneFrom27.5Hz_sma3nz_amean'][0],
        "f0STD": y['F0semitoneFrom27.5Hz_sma3nz_stddevNorm'][0],
        "hnrMean": y.HNRdBACF_sma3nz_amean[0],
        "hnrSTD": y.HNRdBACF_sma3nz_stddevNorm[0],
        "jitterMean": y.jitterLocal_sma3nz_amean[0],
        "jitterSTD": y.jitterLocal_sma3nz_stddevNorm[0],
        "shitterMean": y.shimmerLocaldB_sma3nz_amean[0],
        "shitterSTD": y.shimmerLocaldB_sma3nz_stddevNorm[0],
        "gfccsMean": np.mean(gfccs[1]),
        "gfccsSTD": np.std(gfccs[1]),
    }
    # 批量添加MFCC特征,避免重复代码
    for i in range(16):
        features[f"mfcc{i+1}Mean"] = np.mean(mfcc[i])
        features[f"mfcc{i+1}STD"] = np.std(mfcc[i])
    
    return features

if __name__ == "__main__":
    path = '/content/drive/MyDrive/vocal' 
    files = os.listdir(path)
    files.sort(key=lambda f: int(re.sub('\D', '', f)))
    
    # 使用1核(Colab免费版2核,留1核给系统)
    with Pool(1) as pool:
        voiceFeatures = pool.map(process_single_file, files)
    
    # 生成并保存结果到Drive
    df = pd.json_normalize(voiceFeatures)
    df.to_csv('/content/drive/MyDrive/audio_features.csv', index=False)
  • 注意:如果遇到多进程序列化错误,就把对象初始化放到子进程函数内,虽然有一点开销,但总比串行快。

三、GPU加速尝试(效果视场景而定)

音频特征提取的GPU加速对短音频提升有限,但可以尝试:

  • librosa GPU支持:安装GPU版本的librosa,部分特征会自动使用GPU:
!pip install librosa-gpu
  • essentia GPU版本:安装带TensorFlow GPU支持的essentia,适合批量处理:
!pip install essentia-tensorflow-gpu
  • 提示:30秒短音频的GPU加速可能被数据传输开销抵消,建议优先用多进程。

四、避免Colab会话中断的方案

  • 定时保存中间结果:分批次处理并保存,避免会话中断丢失全部数据:
batch_size = 200
voiceFeatures = []
path = '/content/drive/MyDrive/vocal' 
files = os.listdir(path)
files.sort(key=lambda f: int(re.sub('\D', '', f)))

for i in range(0, len(files), batch_size):
    batch_files = files[i:i+batch_size]
    with Pool(1) as pool:
        batch_features = pool.map(process_single_file, batch_files)
    voiceFeatures.extend(batch_features)
    # 每批保存一次临时文件
    pd.json_normalize(voiceFeatures).to_csv('/content/drive/MyDrive/features_temp.csv', index=False)

# 最终保存完整结果
df = pd.json_normalize(voiceFeatures)
df.to_csv('/content/drive/MyDrive/audio_features.csv', index=False)
  • 会话保持技巧:在浏览器控制台运行以下代码,每60秒点击一次连接按钮,防止超时:
function ClickConnect(){console.log("Clicked");document.querySelector("colab-connect-button").click()}setInterval(ClickConnect,60000)

内容的提问来源于stack exchange,提问作者PM92

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:25:17