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

Python频谱图:识别音频信号中目标声音的起止时间点

音频频谱图的声音起止时间检测方案

需求说明

我正在绘制音频信号的频谱图,该图展示不同时间区间的频率信息。感兴趣区域已用红圈标记,这些时段麦克风记录到了未知频率的声音(当前暂不关注频率值)。希望找到方法,检测每个记录到的声音对应的起止时间(秒级)。

参考普通折线图的思路:初始阶段数值为0,约4秒后数值上升,可将第一个大于阈值的点作为起始点,最后一个后续值回落至阈值以下的点作为结束点,以此检测声音的时长。

当前实现代码

sampleRate = 44100
f, t, Sxx = signal.spectrogram(audio_original, sampleRate)

plt.figure(1)
plt.pcolormesh(t,f,Sxx,shading='gouraud')
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.show()

数据维度说明

f、t、Sxx的长度分别为[129, 17072, 129],其中:

  • f:采样频率数组
  • t:分段时间数组
  • Sxx:音频的频谱图,默认最后一维对应分段时间

实现方案与代码

由于不关注具体频率,只需判断每个时间点是否存在有效声音,可先将频谱数据压缩为时间维度的能量序列,再通过阈值检测起止区间:

  1. 将频谱转换为时间维度的能量序列:

    # 对每个时间点的所有频率能量求和,得到与t长度一致的一维数组
    time_energy = Sxx.sum(axis=0)
    # 若声音集中在单一频率,也可用最大值替代求和
    # time_energy = Sxx.max(axis=0)
    
  2. 基于噪声段设置检测阈值:

    # 假设前2秒为无声音的噪声基线,计算噪声平均能量
    noise_mask = t < 2
    noise_avg = time_energy[noise_mask].mean()
    # 设置阈值为噪声能量的2倍,可根据实际场景调整系数
    threshold = noise_avg * 2
    
  3. 检测声音事件的起止时间:

    import numpy as np
    
    # 标记每个时间点是否超过阈值
    above_threshold = time_energy > threshold
    
    # 通过差分找到连续超过阈值的区间索引
    diff = np.diff(np.concatenate([[False], above_threshold, [False]]))
    event_indices = np.where(diff)[0].reshape(-1, 2)
    
    # 转换为实际秒级时间
    event_times = []
    for start_idx, end_idx in event_indices:
        start_time = t[start_idx]
        end_time = t[end_idx - 1]  # end_idx是从有效到无效的切换点,对应最后一个有效时间点的下一位
        event_times.append((start_time, end_time))
    
    # 输出检测结果
    for i, (start, end) in enumerate(event_times, 1):
        print(f"第{i}个声音事件:起始时间 {start:.2f} 秒,结束时间 {end:.2f} 秒")
    

注意事项

  • 阈值是检测准确性的核心:若噪声波动大,可改用中位数计算噪声基线,或对time_energy做滑动窗口平滑处理,减少误检
  • 频谱图的时间分辨率由spectrogram的nperseg参数决定,若需要更精确的时间,可结合原始音频波形的检测结果进行修正

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 11:21:14