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

如何在Python中获取梅尔频谱图峰值数组以制作音频指纹?

获取频谱图峰值数组实现音频指纹

第一步:修正梅尔频谱生成逻辑

你的原代码生成的是STFT的对数幅度谱,并非梅尔频谱。先补充梅尔频谱转换步骤,同时保留代码可运行性:

import librosa, librosa.display
import numpy as np
import matplotlib.pyplot as plt
import IPython.display as ipd

def MEL_SPECTOGRAM(signal, sr, fileName):
    ipd.Audio(signal, rate=sr)
    n_fft = 2048
    hop_length = 512
    n_mels = 128  # 梅尔滤波器数量,可按需调整

    # 生成梅尔频谱
    mel_spectro = librosa.feature.melspectrogram(
        y=signal, sr=sr, n_fft=n_fft, hop_length=hop_length, n_mels=n_mels
    )
    log_mel_spectro = librosa.amplitude_to_db(mel_spectro, ref=np.max)
    normalized_mel = librosa.util.normalize(log_mel_spectro)

    # 可视化梅尔频谱
    librosa.display.specshow(
        normalized_mel, sr=sr, hop_length=hop_length, cmap='magma',
        x_axis='time', y_axis='mel'
    )
    plt.colorbar(format='%+2.0f dB')
    plt.title(f'Mel Spectrogram - {fileName}')
    plt.show()
    
    return normalized_mel

第二步:提取频谱图峰值数组

音频指纹的核心是提取局部峰值,这里用非极大值抑制算法,筛选出每个时间帧内频率维度的局部最大值,同时通过阈值过滤低能量噪声点:

def extract_spectro_peaks(mel_spectro, threshold=0.2, neighborhood_size=3):
    """
    提取梅尔频谱的局部峰值
    :param mel_spectro: 归一化后的梅尔频谱数组(形状:[n_mels, n_frames])
    :param threshold: 峰值能量阈值,过滤低于该值的点
    :param neighborhood_size: 邻域大小,检查周围n个点是否当前点为最大值
    :return: 峰值数组,每个元素为(频率索引, 时间帧索引, 能量值)
    """
    peaks = []
    n_mels, n_frames = mel_spectro.shape
    
    for frame_idx in range(n_frames):
        frame = mel_spectro[:, frame_idx]
        for mel_idx in range(n_mels):
            # 跳过边缘点,避免索引越界
            if mel_idx < neighborhood_size//2 or mel_idx >= n_mels - neighborhood_size//2:
                continue
            # 检查当前点是否为邻域内最大值且超过阈值
            neighborhood = frame[mel_idx - neighborhood_size//2 : mel_idx + neighborhood_size//2 + 1]
            if frame[mel_idx] == np.max(neighborhood) and frame[mel_idx] > threshold:
                peaks.append((mel_idx, frame_idx, frame[mel_idx]))
    
    return np.array(peaks)

第三步:整合使用示例

# 加载音频文件
audio_path = "your_audio_file.wav"
signal, sr = librosa.load(audio_path, sr=None)

# 生成梅尔频谱
mel_spectro = MEL_SPECTOGRAM(signal, sr, audio_path.split("/")[-1])

# 提取峰值数组
peak_array = extract_spectro_peaks(mel_spectro, threshold=0.15, neighborhood_size=3)
print(f"提取到的峰值数量:{len(peak_array)}")
print("前5个峰值(频率索引, 时间帧索引, 能量值):")
print(peak_array[:5])

关键说明

  • 梅尔频谱转换:使用librosa.feature.melspectrogram直接生成梅尔滤波后的频谱,比手动转换更可靠,贴合人耳听觉特性
  • 峰值筛选:通过邻域最大值判断+能量阈值,确保提取的是真正有区分度的特征点,这些点就是构建音频指纹的核心元素
  • 参数调整:n_mels(梅尔滤波器数量)、threshold(峰值阈值)、neighborhood_size(邻域大小)可根据音频类型调整,优化指纹的唯一性和鲁棒性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 08:56:06