声音触发器。用于自动化场景检测器

在使用AI智能体时,我们遇到很多已经运行结束,就是还不知道的情况下,我们可以设置一段脚本,让运行完声音一直提醒我们,让第一时间我们知道,才写的这段脚本,很完美,你们尝试一下。

这段代码实现了一个基于音频相似度检测的自动复读系统。

简单来说,它的作用是:监听环境声音,当检测到特定的"触发音"时,自动播放一段指定的 MP3 音频(复读)。

以下是代码的详细功能模块总结:

🎯 核心用途

这是一个声音触发器。它通常用于自动化场景,例如:

游戏辅助:听到游戏内的特定提示音(如"检查员来了"),自动播放语音提醒或执行操作。

语音交互:听到特定的唤醒词或指令后,自动播放回复语音。

自动化监控:监控特定频率或类型的声音事件。

⚙️ 功能模块详解

  1. 模板录制与学习
    功能:程序启动后,首先会进入"录制模式"。
    实现:利用 sounddevice 录制一段用户发出的声音作为"模板"。
    目的:确立"我要找的声音"是什么样子的,作为后续比对的基准。
  2. 实时监听与特征比对
    功能:在后台循环监听麦克风输入。
    核心算法:
    滑动窗口:在录音流中截取片段。
    相关系数:使用 np.corrcoef 计算录音片段与模板声音的皮尔逊相关系数。
    阈值判定:如果相似度超过设定的 THRESHOLD (代码中设为 0.45),则判定为匹配成功。
  3. 自动复读
    功能:一旦检测到匹配的声音,触发播放线程。
    实现:使用 pygame.mixer 播放指定的本地 MP3 文件(代码路径指向 D:\trae\检查员提示音_Freesound.mp3)。
    逻辑:播放 REPEAT_COUNT (10次),且在播放期间暂停新的检测,防止重复触发。
    🔑 关键技术点
    音频处理库:使用 sounddevice 进行低延迟的音频流录制,numpy 进行信号处理和数学计算。
    多线程:
    主线程保持程序运行。
    监听线程负责后台检测。
    播放线程负责播放音频,避免阻塞监听。
    抗噪与优化:
    设置了音量阈值 (volume < 0.05) 忽略静音片段,节省计算资源。
    滑动步长设为 1000,加快比对速度。
    📝 总结
    这就好比一个"声音回声筒":你先教它认一个声音,然后它一直竖着耳朵听,一旦在环境里听到这个声音,它就会大声把另一个预设好的 MP3 文件播放出来。
python 复制代码
# -*- coding: utf-8 -*-
import warnings
warnings.filterwarnings("ignore")
import os
import time
import threading
import pygame
import numpy as np
import sounddevice as sd

# ================= 配置区域 =================
TEMPLATE_RECORD_SECONDS = 1 
REPEAT_COUNT = 10
# 阈值设为 0.45 (刚才测到了 0.53,所以 0.45 很安全)
THRESHOLD = 0.45 
# ===========================================

is_repeating = False
target_template = None 

def record_template():
    global target_template
    print("\n" + "="*50)
    print("🎤 准备录制模板")
    print("请按 Enter 键,然后播放提示音...")
    input()
    
    SAMPLE_RATE = 44100
    print("🔴 正在录制... (发出你要识别的声音)")
    
    audio = sd.rec(int(TEMPLATE_RECORD_SECONDS * SAMPLE_RATE), 
                  samplerate=SAMPLE_RATE, channels=1, dtype='float32')
    sd.wait()
    
    target_template = audio[:, 0]
    print(f"✅ 模板录制成功!长度: {len(target_template)} 个采样点")
    print("="*50 + "\n")
    time.sleep(1)

def play_task():
    global is_repeating
    try:
        print(f"\n🔊 开始复读任务...")
        pygame.mixer.init(frequency=44100, size=-16, channels=1)
        pygame.mixer.music.load(r"D:\trae\检查员提示音_Freesound.mp3")
        
        for i in range(REPEAT_COUNT):
            print(f"   播放第 {i+1}/{REPEAT_COUNT} 次...")
            pygame.mixer.music.play()
            while pygame.mixer.music.get_busy():
                time.sleep(3)
        print("   ✅ 复读完成")
        
    except Exception as e:
        print(f"   ❌ 播放错误: {e}")
    finally:
        pygame.mixer.quit()
        is_repeating = False

def listen_loop():
    global is_repeating
    
    record_template()
    
    template_len = len(target_template)
    print(f"👂 正在监听... (阈值: {THRESHOLD})")
    
    while True:
        if is_repeating:
            time.sleep(0.5)
            continue

        try:
            RECORD_SECONDS = 2
            SAMPLE_RATE = 44100
            audio = sd.rec(int(RECORD_SECONDS * SAMPLE_RATE), 
                          samplerate=SAMPLE_RATE, channels=1, dtype='float32')
            sd.wait()
            recording = audio[:, 0]

            # 音量检测
            volume = np.max(np.abs(recording))
            if volume < 0.05: 
                continue
            
            # --- 核心修改:滑动窗口比对 ---
            max_similarity = 0.0
            
            # 如果录音比模板长,我们就滑动查找
            if len(recording) > template_len:
                # 滑动步长设为 1000,加快计算速度
                step = 1000 
                for i in range(0, len(recording) - template_len, step):
                    # 截取一段
                    rec_part = recording[i : i + template_len]
                    
                    # 计算相关系数
                    corr = np.corrcoef(rec_part, target_template)
                    sim = abs(corr[0, 1])
                    
                    # 记录最高相似度
                    if sim > max_similarity:
                        max_similarity = sim
            else:
                # 如果录音太短,直接比对(补零或截断)
                min_len = min(len(recording), template_len)
                corr = np.corrcoef(recording[:min_len], target_template[:min_len])
                max_similarity = abs(corr[0, 1])
            
            print(f"🔊 音量: {volume:.2f} | 最高相似度: {max_similarity:.3f}")

            if max_similarity > THRESHOLD:
                print(f"\n⚡ 发现匹配声音!(相似度 {max_similarity:.3f}) 触发复读!")
                is_repeating = True
                t = threading.Thread(target=play_task)
                t.daemon = True
                t.start()

        except Exception as e:
            print(f"   🎤 错误: {e}")
            time.sleep(1)

if __name__ == "__main__":
    print("🚀 程序启动...")
    if not os.path.exists(r"D:\trae\检查员提示音_Freesound.mp3"):
        print("❌ MP3文件不存在")
        exit()

    listener_thread = threading.Thread(target=listen_loop, daemon=True)
    listener_thread.start()
    
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("\n👋 退出。")

补充

python 复制代码
# -*- coding: utf-8 -*-
import warnings
warnings.filterwarnings("ignore")
import os
import time
import threading
import pygame
import numpy as np
import sounddevice as sd

# ================= 配置区域 =================
TEMPLATE_RECORD_SECONDS = 1 
REPEAT_COUNT = 10
# 阈值设为 0.45 (刚才测到了 0.53,所以 0.45 很安全)
THRESHOLD = 0.45 
# ===========================================

is_repeating = False
target_template = None 

def record_template():
    global target_template
    print("\n" + "="*50)
    print("🎤 准备录制模板")
    print("请按 Enter 键,然后播放提示音...")
    input()
    
    SAMPLE_RATE = 44100
    print("🔴 正在录制... (发出你要识别的声音)")
    
    audio = sd.rec(int(TEMPLATE_RECORD_SECONDS * SAMPLE_RATE), 
                  samplerate=SAMPLE_RATE, channels=1, dtype='float32')
    sd.wait()
    
    target_template = audio[:, 0]
    print(f"✅ 模板录制成功!长度: {len(target_template)} 个采样点")
    print("="*50 + "\n")
    time.sleep(1)

def play_task():
    global is_repeating
    try:
        print(f"\n🔊 开始复读任务...")
        pygame.mixer.init(frequency=44100, size=-16, channels=1)
        pygame.mixer.music.load(r"D:\trae\检查员提示音_Freesound.mp3")
        
        for i in range(REPEAT_COUNT):
            print(f"   播放第 {i+1}/{REPEAT_COUNT} 次...")
            pygame.mixer.music.play()
            while pygame.mixer.music.get_busy():
                time.sleep(3)
        print("   ✅ 复读完成")
        
    except Exception as e:
        print(f"   ❌ 播放错误: {e}")
    finally:
        pygame.mixer.quit()
        is_repeating = False

def listen_loop():
    global is_repeating
    
    record_template()
    
    template_len = len(target_template)
    print(f"👂 正在监听... (阈值: {THRESHOLD})")
    
    while True:
        if is_repeating:
            time.sleep(0.1)
            continue

        try:
            RECORD_SECONDS = 2
            SAMPLE_RATE = 44100
            audio = sd.rec(int(RECORD_SECONDS * SAMPLE_RATE), 
                          samplerate=SAMPLE_RATE, channels=1, dtype='float32')
            sd.wait()
            recording = audio[:, 0]

            # 音量检测
            volume = np.max(np.abs(recording))
            if volume < 0.05: 
                continue
            
            # --- 核心修改:滑动窗口比对 ---
            max_similarity = 0.0
            
            # 如果录音比模板长,我们就滑动查找
            if len(recording) > template_len:
                # 滑动步长设为 1000,加快计算速度
                step = 100 
                for i in range(0, len(recording) - template_len, step):
                    # 截取一段
                    rec_part = recording[i : i + template_len]
                    
                    # 计算相关系数
                    corr = np.corrcoef(rec_part, target_template)
                    sim = abs(corr[0, 1])
                    
                    # 记录最高相似度
                    if sim > max_similarity:
                        max_similarity = sim
            else:
                # 如果录音太短,直接比对(补零或截断)
                min_len = min(len(recording), template_len)
                corr = np.corrcoef(recording[:min_len], target_template[:min_len])
                max_similarity = abs(corr[0, 1])
            
            print(f"🔊 音量: {volume:.2f} | 最高相似度: {max_similarity:.3f}")

            if max_similarity > THRESHOLD:
                print(f"\n⚡ 发现匹配声音!(相似度 {max_similarity:.3f}) 触发复读!")
                is_repeating = True
                t = threading.Thread(target=play_task)
                t.daemon = True
                t.start()

        except Exception as e:
            print(f"   🎤 错误: {e}")
            time.sleep(1)

if __name__ == "__main__":
    print("🚀 程序启动...")
    if not os.path.exists(r"D:\trae\检查员提示音_Freesound.mp3"):
        print("❌ MP3文件不存在")
        exit()

    listener_thread = threading.Thread(target=listen_loop, daemon=True)
    listener_thread.start()
    
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("\n👋 退出。")
相关推荐
无忧智库3 小时前
从数据孤岛到全球实时协同:某跨国企业 Data Fabric 供应链数据编织平台全解析(WORD)
运维·fabric
齐潇宇3 小时前
Docker概述与安装
linux·运维·docker·容器
Dragon水魅4 小时前
爬虫技术详解:从传统爬虫到浏览器自动化——以豆瓣读书笔记为例
运维·爬虫·自动化
willhuo4 小时前
# 自动化数据采集技术研究与实现:基于Playwright的抖音网页自动化方案
运维·selenium·c#·自动化·chrome devtools·webview
IP老炮不瞎唠4 小时前
IP轮换机制解析:动态住宅代理如何维持高可用率?
运维·服务器·网络
一个扣子4 小时前
OpenClaw 运维完全手册|日志分析、实时监控与故障排查指南
运维·监控·故障排查·健康检查·openclaw·clawmetry·openclawdoctor
Lentou4 小时前
nginx反向代理
运维·nginx
刘~浪地球4 小时前
API 安全设计最佳实践
运维·网络·安全
网络安全许木4 小时前
自学渗透测试第20天(防火墙基础与规则配置)
运维·服务器·网络·网络安全·渗透测试
亚空间仓鼠4 小时前
Docker 容器技术入门与实践 (二):Dockerfile文件
运维·docker·容器