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

在使用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👋 退出。")
相关推荐
XIAOHEZIcode15 小时前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220701 天前
如何搭建本地yum源(上)
运维
大树884 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠4 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质4 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工4 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智4 天前
ARP代理--工作原理
运维·网络·arp·arp代理
shushangyun_4 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
施努卡机器视觉4 天前
SNK施努卡侧滑门锁上滑轮总成自动化装配线,从零件到组件,全流程精密制造方案
运维·自动化·制造
dayuOK63074 天前
写作卡壳怎么办?我的“5分钟启动法”
人工智能·职场和发展·自动化·新媒体运营·媒体