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

如何使用Python从*.wav格式心跳音频的指定时间窗口中提取心率

Python实现wav心跳音频心率计算方案

前置依赖

首先安装需要的第三方库:
pip install librosa numpy scipy

核心实现逻辑

  • 加载wav音频文件,获取采样率和原始音频序列
  • 按指定窗口长度截取对应长度的音频片段,不足窗口长度时可抛出提示或全量处理
  • 对音频片段做带通滤波,保留心跳对应的频率范围(0.67Hz ~ 3Hz,对应心率40~180次/分钟),过滤环境噪音
  • 检测心跳峰值数量,通过峰值数和窗口长度换算得到每分钟心率

完整代码示例

import librosa
import numpy as np
from scipy.signal import butter, filtfilt, find_peaks

def butter_bandpass(lowcut, highcut, sr, order=5):
    nyq = 0.5 * sr
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='band')
    return b, a

def bandpass_filter(data, lowcut, highcut, sr, order=5):
    b, a = butter_bandpass(lowcut, highcut, sr, order=order)
    y = filtfilt(b, a, data)
    return y

def calculate_heart_rate(wav_path, window_seconds=15):
    # 加载音频,sr为采样率,y为单声道音频序列
    y, sr = librosa.load(wav_path, sr=None, mono=True)
    total_duration = librosa.get_duration(y=y, sr=sr)
    
    # 截取指定窗口的音频
    if total_duration < window_seconds:
        print(f"音频时长不足{window_seconds}秒,将使用全量音频计算")
        window_samples = len(y)
        used_window_seconds = total_duration
    else:
        # 这里默认从音频开头截取,需要调整起始位置可以修改offset参数
        offset_samples = 0
        window_samples = int(window_seconds * sr)
        y = y[offset_samples:offset_samples + window_samples]
        used_window_seconds = window_seconds
    
    # 带通滤波,保留心跳频率范围
    lowcut = 0.67  # 对应最低心率40次/分
    highcut = 3.0  # 对应最高心率180次/分
    y_filtered = bandpass_filter(y, lowcut, highcut, sr)
    
    # 检测心跳峰值
    min_interval = 60 / 180  # 最快心跳间隔,单位秒
    min_distance = int(min_interval * sr)
    peaks, _ = find_peaks(y_filtered, height=np.mean(y_filtered)*1.5, distance=min_distance)
    
    # 计算心率:峰值数 / 窗口时长(秒) * 60 = 每分钟心跳数
    heart_rate = round(len(peaks) / used_window_seconds * 60, 1)
    return heart_rate

# 调用示例
if __name__ == "__main__":
    hr = calculate_heart_rate("test_heartbeat.wav", window_seconds=15)
    print(f"计算得到的心率为:{hr} 次/分钟")

参数调整建议

  • 如果你的音频噪音较多,可以适当调高find_peaks里的height阈值,或者提升带通滤波的order参数
  • 如果你需要从音频的中间位置截取窗口,修改offset_samples为对应起始位置的样本数即可,比如从第5秒开始就是offset_samples = int(5 * sr)
  • 可以先使用matplotlib绘制滤波前后的波形和峰值位置,方便调整参数,示例代码如下:
import matplotlib.pyplot as plt
# 绘制波形和峰值示例
plt.plot(y_filtered)
plt.plot(peaks, y_filtered[peaks], "x")
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 21:15:05