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

在使用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👋 退出。")
相关推荐
Lsetea7 小时前
curl指定CA目录仍报证书不受信任:--capath与OpenSSL rehash排查
运维·https·ssl·openssl·curl
优化Henry8 小时前
LTE 载波频率与频点配置详解
运维·网络·学习·5g·信息与通信
代码方舟8 小时前
数据科学风控实战:基于天远全能消金报告构建自动化信用评估网关
运维·人工智能·自动化
科力锐品牌君9 小时前
应用级灾备 | 海量非结构化数据如何实现高效数据保护
linux·运维·网络·安全·系统安全·数据安全·灾备
KaiwuDB9 小时前
KaiwuDB 运维实战04:DRBD + KaiwuDB——物联网场景下的低成本数据库高可用方案
运维·数据库·物联网·时序数据库·kaiwudb·aiot·多模数据库
duanshu_9 小时前
官网表单与下载异常怎么排查?五个环节定位故障
前端·自动化·flyweight
福建佰胜张工9 小时前
A5E00839230西门子工业核心配件详解:参数、安装调试与故障运维全攻略
运维·网络·安全·自动化
Lancker10 小时前
chnroute-linux — 中国大陆 IP 段每日自动更新 + 「仅允许国内访问」落地
linux·运维·tcp/ip
ii_best10 小时前
按键精灵手机端开发安卓版实战:手写一个可最小化、可拖动的「运行日志悬浮窗」(附完整 源码 + 踩坑记录)
android·ios·智能手机·自动化·ai编程·按键精灵
天远Date Lab10 小时前
零信任架构实战:基于天远全能消金报告(标准版)构建自动化骑手资信评估网关
运维·人工智能·架构·自动化