在windows上使用鼠标、键盘和语音检测活动

2024-04-20 06:24:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我们在Python上有一个模块(通过win32)通过GetLastInputInfo和GetTickCount检测用户的鼠标和键盘活动。如何在GetLastInputInfo中注册语音活动

或者,我们可以添加一个合成输入,以便在每次麦克风检测到语音输入时更新GetLastInputInfo?但是我们能在不打扰用户的情况下做到这一点吗

Pyaudio上按音量检测用户语音的示例代码:

audio = pyaudio.PyAudio()
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
CHUNK = 1024

# recording prerequisites
stream = audio.open(format=FORMAT, channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)

while True:
   data = stream.read(CHUNK)
   data_chunk = array('h', data)
   vol = max(data_chunk)
   if vol >= 500:
      # voice detected from mic
      print("talking - {}".format(vol))
   else:
      print("-")

用于检测用户输入的示例代码:

# code to get inactivity
class LastInputInfo(Structure):
    _fields_ = [
        ("cbSize", UINT),
        ("dwTime", DWORD)
    ]


def _getLastInputTick() -> int:
    """
    retrieves the last input action
        :return: int
    """
    prototype = WINFUNCTYPE(BOOL, POINTER(LastInputInfo))
    paramflags = ((1, "lastinputinfo"), )
    # type: ignore
    c_GetLastInputInfo = prototype(("GetLastInputInfo", ctypes.windll.user32), paramflags)  

    l = LastInputInfo()
    l.cbSize = ctypes.sizeof(LastInputInfo)
    assert 0 != c_GetLastInputInfo(l)
    return l.dwTime


def _getTickCount() -> int:
    """
    :return: int
        tick count
    """
    prototype = WINFUNCTYPE(DWORD)
    paramflags = ()
    c_GetTickCount = prototype(("GetTickCount", ctypes.windll.kernel32), paramflags)  # type: ignore
    return c_GetTickCount()


def seconds_since_last_input():
    """
    :return: float
        the time of user input
    """
    seconds_since_input = (_getTickCount() - _getLastInputTick()) / 1000
    return seconds_since_input

# inactivity in N seconds
seconds_since_input = seconds_since_last_input()
inactive_seconds = 10
while True:
    # Becomes active
    if afk and seconds_since_input < inactive_seconds:
        afk = False

    #becomes afk
    elif not afk and seconds_since_input >= inactive_seconds:
        afk = True

    print("afk status: {}, seconds since last input :{}".format(seconds_since_input))

Tags: 用户trueinputdatareturnintlastseconds
1条回答
网友
1楼 · 发布于 2024-04-20 06:24:04

如果您想在不中断用户的情况下执行某些操作,可以使用threading多线程
如果要将某些内容保存在每个线程都可以使用的变量中,可以使用queue

这将在不同的线程中运行您需要运行的任何内容,并保存在共享变量上

  1. 导入模块
import threading
import queue
  1. 创建一个共享变量
shared_var = queue.Queue()
  1. 创建一个函数,用于检查所需内容(在本例中为音频),并编辑共享变量

编辑共享变量:shared_var.put(item)
(在这种情况下,每当检测到音频时,您可以说audio_detected.put(True)和/或current_tick_count.put(tick_count),或类似的话`)

  1. 创建一个线程并传入要检查的函数
thread = threading.Thread(target=function, args=arguments)

其中target是您希望在此新步骤中调用的函数,args是您需要传递到函数中的参数

  1. 启动新线程
thread.start()
  1. 在主线程或新线程上,使用该变量执行所需操作
    shared_var.get()将等待某个内容被添加到shared_var中,然后返回所添加的内容

示例代码:

import threading
import queue
import time

text = queue.Queue()

def change(text):
    time.sleep(3)
    text.put("hello world")



thread = threading.Thread(target=change, args=(text,))
#                                                  ^ IMPORTANT! (,)
thread.start()


def display(text):
    text = text.get() # This will wait till text has somthing inside and then returns it
    print(text)


thread2 = threading.Thread(target=display, args=(text,))
#                                                    ^ IMPORTANT! (,)
thread2.start()

input() # To show it won't interrupt the user until the text has something

如果这个答案不太清楚,我很抱歉。我不熟悉pyaudio和win32,但我知道threadingqueue,所以您可以使用它并添加自己的代码。如果需要,您可以编辑答案,其中包含您的代码。

我希望这有帮助

相关问题 更多 >