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

如何使用Python从混合WAV音频中单独提取脚步声?

提取WAV文件中脚步声的Python实现方案

先明确各声音的频率特征,选对滤波器

拆解三种声音的频段分布,这是选滤波器的核心依据:

  • 脚步声:核心能量集中在50-500Hz(硬底鞋、不同地面会略有浮动,但整体属于中低频区间)
  • 鸟鸣声:典型高频信号,集中在2kHz-10kHz,极易过滤
  • 拖拉机声:包含低频引擎振动(10-200Hz)和中高频机械噪声,但低频部分和脚步声有重叠

所以单纯低通/高通都无法满足需求,得用带通滤波器先保留脚步声的核心频段(比如40-600Hz),先滤掉绝大多数鸟鸣高频噪声,再处理和拖拉机的重叠部分。

用Python实现带通滤波(scipy/librosa均可)

这里用scipy的signal模块做示例,代码简单直观:

先安装依赖:

pip install scipy librosa soundfile

代码示例:

import numpy as np
import scipy.signal as signal
import soundfile as sf

# 读取目标WAV文件
audio, sample_rate = sf.read("your_input_audio.wav")

# 计算奈奎斯特频率,设计4阶巴特沃斯带通滤波器
nyquist_freq = 0.5 * sample_rate
low_cut = 40 / nyquist_freq
high_cut = 600 / nyquist_freq
b, a = signal.butter(4, [low_cut, high_cut], btype='band')

# 双向滤波避免相位偏移
filtered_audio = signal.filtfilt(b, a, audio)

# 保存初步滤波后的音频
sf.write("filtered_audio.wav", filtered_audio, sample_rate)

解决降噪误滤脚步声的问题:放弃普通降噪,用特征分离

普通降噪(比如谱减法、维纳滤波)会把和噪声频段重叠的脚步声误删,换个思路——抓住脚步声的独特特征做分离:

方法1:利用脚步声的冲击性特征

脚步声是周期性的冲击信号,时域上有明显的能量峰值,而拖拉机是持续的低频振动,鸟鸣已被滤除得差不多。用峰值检测+掩码提取:

import librosa
from librosa.util import peak_pick

# 提取音频的短时能量(RMS)
rms = librosa.feature.rms(y=filtered_audio)[0]
# 检测能量峰值(对应脚步声的冲击)
# 参数需根据音频调整:pre/post_max是峰值前后的比较窗口,delta是峰值阈值
peaks = peak_pick(rms, pre_max=20, post_max=20, pre_avg=20, post_avg=20, delta=0.1, wait=100)

# 生成掩码,只保留峰值附近的信号(每个脚步声持续约0.2秒)
mask = np.zeros_like(filtered_audio)
window_size = int(sample_rate * 0.2)
hop_length = 512  # librosa计算RMS时的默认步长
for peak_idx in peaks:
    start = max(0, peak_idx * hop_length - window_size)
    end = min(len(filtered_audio), peak_idx * hop_length + window_size)
    mask[start:end] = 1

# 应用掩码得到脚步声信号
footstep_audio = filtered_audio * mask
sf.write("footstep_only.wav", footstep_audio, sample_rate)

方法2:用预训练模型做源分离(效果更稳定)

如果手动调参麻烦,直接用OpenUnmix这种预训练的音频源分离模型,专门分离不同类型的音频源:

import torch
import openunmix

# 加载预训练的高质量分离模型
model = openunmix.umxhq()

# 把音频转成模型需要的张量格式(单通道示例)
audio_tensor = torch.tensor(filtered_audio).unsqueeze(0).unsqueeze(0)  # 形状:(1, 1, 采样点数)
estimates = model(audio_tensor)

# 提取低音源(对应脚步声+拖拉机),再用带通滤波细化
low_source = estimates['bass'].squeeze().numpy()
# 再次用带通滤波过滤拖拉机的极端低频
b, a = signal.butter(4, [60/nyquist_freq, 500/nyquist_freq], btype='band')
final_footsteps = signal.filtfilt(b, a, low_source)

sf.write("final_footsteps.wav", final_footsteps, sample_rate)

关键调参提示

  • 带通滤波器频段:如果是高跟鞋脚步声,上限可调到800Hz;如果拖拉机低频干扰极强,把下限提到60Hz
  • 峰值检测参数:先画出RMS曲线(plt.plot(rms)),再调整delta(峰值与周围的差值阈值)和wait(避免连续检测同一脚步声)
  • 禁用普通降噪算法:比如谱减法会把和拖拉机重叠的脚步声当成噪声删掉,完全不适用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 04:52:34