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

在使用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👋 退出。")
相关推荐
陳10303 小时前
Linux:第一个系统程序--进度条
linux·运维·服务器
李子焱3 小时前
第一节:初识n8n与下一代工作流自动化
运维·自动化
暴力求解3 小时前
Linux---命名管道与共享内存(一)
linux·运维·服务器
小鸡食米3 小时前
Linux 防火墙
linux·运维·服务器
bingHHB3 小时前
聚水潭 × 金蝶云星空:日均万单电商如何实现销售出库自动记账
运维·自动化·集成学习
ICT系统集成阿祥3 小时前
BGP邻居状态机详解
运维·服务器
NineData3 小时前
MySQL到StarRocks 同步链路中的建表、DDL 跟随与数据校验
运维·数据库·starrocks·mysql·数据迁移·数据库管理工具·ninedata
龙泉寺天下行走3 小时前
记一次windows SSH无法免密登录Linux的处理
linux·运维·ssh
极客老王说Agent3 小时前
适合IT运维人员进行服务器监控和故障预警的Agent有哪些?2026智能运维全攻略
运维·服务器·人工智能·ai·chatgpt