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

麦克风静音监测应用问题:检测到声音时无法重置计时器

问题分析与代码修复

原代码存在的问题

  1. 冗余的声音检测逻辑:两个独立的声音判断条件导致部分场景下(如声音强度在100-150之间),仅重置计时器但未更新最后发声时间,后续仍会错误递增计时。
  2. 计时逻辑不精准:依赖time.sleep(1)固定递增1秒,循环执行时间偏差会导致计时不准。
  3. Tkinter线程安全风险:后台线程直接修改UI变量,可能引发未知异常。
  4. 未满足需求:警告触发时间设置为25秒,与要求的30秒不符。

修复方案

  • 统一声音检测阈值,移除冗余判断,确保检测到声音时同步更新最后发声时间与计时器。
  • 通过计算最后发声时间与当前时间的差值更新计时器,提升计时准确性。
  • 使用root.after()将所有UI操作切换到主线程执行,规避线程安全问题。
  • 调整警告触发时间为30秒,更新弹窗提示文本。

修正后的完整代码

import pyaudio
import numpy as np
import time
import threading
import tkinter as tk


def ses_alma(root, sessizlik_suresi):
    CHUNK = 1024
    FORMAT = pyaudio.paInt16
    CHANNELS = 1
    RATE = 44100
    SOUND_THRESHOLD = 100  # 统一声音检测阈值

    p = pyaudio.PyAudio()

    stream = p.open(format=FORMAT,
                    channels=CHANNELS,
                    rate=RATE,
                    input=True,
                    frames_per_buffer=CHUNK)

    print("开始监听声音...")

    last_sound_time = time.time()

    try:
        while True:
            data = stream.read(CHUNK)
            audio_data = np.frombuffer(data, dtype=np.int16)
            audio_max = np.max(np.abs(audio_data))

            if audio_max >= SOUND_THRESHOLD:
                # 检测到声音,重置计时
                last_sound_time = time.time()
                root.after(0, lambda: sessizlik_suresi.set(0))
            else:
                # 计算静音时长并更新计时器
                elapsed = int(time.time() - last_sound_time)
                root.after(0, lambda: sessizlik_suresi.set(elapsed))

            # 短暂睡眠降低CPU占用
            time.sleep(0.1)
    finally:
        # 确保资源正确释放
        stream.stop_stream()
        stream.close()
        p.terminate()


def uyarı_ver(root, sessizlik_suresi):
    while True:
        current_time = sessizlik_suresi.get()
        if current_time >= 30:  # 调整为30秒触发警告
            root.after(0, show_popup)
            root.after(0, lambda: sessizlik_suresi.set(0))
        time.sleep(1)


def show_popup():
    popup = tk.Toplevel()
    popup.geometry("200x100")
    popup.title("警告")
    message = tk.Label(popup, text="静音超过30秒!")
    message.pack()
    popup.after(5000, popup.destroy)  # 5秒后关闭警告窗口


if __name__ == "__main__":
    root = tk.Tk()
    root.geometry("300x100")
    root.title("静音警告")
    root.configure(bg="black")

    sessizlik_suresi = tk.IntVar()
    sessizlik_suresi.set(0)

    time_label = tk.Label(root, textvariable=sessizlik_suresi, font=("Arial Bold", 36), bg="black", fg="white")
    time_label.pack()

    # 传递root和变量到线程函数
    ses_alma_thread = threading.Thread(target=ses_alma, args=(root, sessizlik_suresi), daemon=True)
    uyarı_thread = threading.Thread(target=uyarı_ver, args=(root, sessizlik_suresi), daemon=True)

    ses_alma_thread.start()
    uyarı_thread.start()

    root.mainloop()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 05:07:03