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

如何用Python检测扬声器是否播放特定频率的声音?

检测扬声器播放的特定频率(以440Hz为例)的完整方案

是否应该用PyAudio?

是的,PyAudio是Python中处理实时音频输入输出的常用库,能方便地捕获系统音频(包括扬声器输出),完全适合你的需求。

完整实现步骤

1. 安装依赖库

首先安装需要的工具库:

pip install pyaudio numpy scipy

注:如果PyAudio安装失败(比如Windows系统),可以去PyPI下载对应系统和Python版本的.whl文件手动安装。

2. 理解核心原理

音频数据默认是时域信号(随时间变化的声音振幅),要检测特定频率,需要通过快速傅里叶变换(FFT)把时域信号转换成频域信号——这样就能看到每个频率对应的声音强度,判断目标频率(440Hz)的强度是否超过设定阈值(排除环境噪音干扰)。

3. 找到扬声器输出的捕获设备

默认情况下PyAudio会调用麦克风,要捕获扬声器播放的声音,需要找到系统的“回环设备”:

  • Windows:在音频设置里启用“立体声混音”设备(可能默认隐藏,需要在设备管理器里显示禁用的设备)
  • Mac:可以用Soundflower或Loopback工具创建音频回环设备
  • Linux:通过PulseAudio设置音频回环模块

然后运行下面的代码列出所有音频设备,找到对应回环设备的编号:

import pyaudio

p = pyaudio.PyAudio()
for i in range(p.get_device_count()):
    info = p.get_device_info_by_index(i)
    print(f"设备编号: {i}, 名称: {info['name']}, 输入通道数: {info['maxInputChannels']}")
p.terminate()

找名称包含“立体声混音”“Loopback”“Soundflower”的设备,记录它的编号。

4. 编写检测代码

下面是完整的实时检测代码,替换TARGET_FREQUENCY(目标频率)和DEVICE_INDEX(你的回环设备编号)即可运行:

import pyaudio
import numpy as np
from scipy.fft import rfft, rfftfreq

# 配置参数
TARGET_FREQUENCY = 440  # 要检测的目标频率
DEVICE_INDEX = 2  # 替换成你的回环设备编号
SAMPLING_RATE = 44100  # 音频采样率,常用44100Hz
CHUNK_SIZE = 1024  # 每次读取的音频块大小,影响频率分辨率
THRESHOLD = 5000  # 强度阈值,超过则判定为正在播放目标频率

# 初始化PyAudio
p = pyaudio.PyAudio()

# 打开音频流(捕获回环设备的音频)
stream = p.open(
    format=pyaudio.paInt16,  # 16位音频格式
    channels=1,  # 单声道,简化处理
    rate=SAMPLING_RATE,
    input=True,
    input_device_index=DEVICE_INDEX,
    frames_per_buffer=CHUNK_SIZE
)

print(f"开始检测{TARGET_FREQUENCY}Hz的声音...")
print(f"按Ctrl+C停止检测")

try:
    while True:
        # 读取音频数据
        audio_data = stream.read(CHUNK_SIZE)
        # 把二进制数据转成numpy数组(16位整数)
        audio_np = np.frombuffer(audio_data, dtype=np.int16)
        
        # 对音频数据做FFT,得到频域强度
        fft_values = rfft(audio_np)
        # 计算对应的频率轴
        freq_axis = rfftfreq(CHUNK_SIZE, 1/SAMPLING_RATE)
        
        # 找到最接近目标频率的索引
        target_index = np.argmin(np.abs(freq_axis - TARGET_FREQUENCY))
        # 获取目标频率对应的强度(取绝对值)
        target_strength = np.abs(fft_values[target_index])
        
        # 判断是否超过阈值
        if target_strength > THRESHOLD:
            print(f"检测到{TARGET_FREQUENCY}Hz的声音!强度: {target_strength}")
        else:
            # 可选:打印实时强度,方便调试阈值
            # print(f"未检测到,当前强度: {target_strength}")
            pass
            
except KeyboardInterrupt:
    print("\n检测停止")
finally:
    # 关闭流和PyAudio
    stream.stop_stream()
    stream.close()
    p.terminate()

5. 调试与优化

  • 调整阈值:根据环境噪音情况修改THRESHOLD,可以先运行代码观察无目标声音时的强度,把阈值设为该值的2-3倍
  • 调整CHUNK_SIZE:值越大,频率分辨率越高(能更精准定位目标频率),但实时性会降低;值越小则实时性越好,但分辨率降低
  • 多声道处理:如果回环设备是立体声,可以把channels设为2,然后取其中一个声道的数据处理即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:30:32