【问题标题】:pynput keyboard Listener autorepeatpynput 键盘监听器自动重复
【发布时间】:2020-05-24 23:12:05
【问题描述】:

我正在尝试使用 pynput 获取实时键盘输入,但 on_press 函数在自动重复时被调用。

示例代码:

#!/usr/bin/env python3

import sys

import numpy as np
import sounddevice as sd

from pynput import keyboard

frequency = []

def on_press(key):
    global frequency
    try:
        print(key.vk)
        if key.char == "q":
            frequency.append(440)
        elif key.char == "w":
            frequency.append(880)
    except AttributeError:
        pass

def on_release(key):
    global frequency
    if key == keyboard.Key.esc:
        # Stop listener
        print("Press Enter")
        return False
    elif key.char == "q":
        frequency.remove(440)
    elif key.char == "w":
        frequency.remove(880)

listener = keyboard.Listener(
    on_press=on_press,
    on_release=on_release,
    suppress = True)
listener.start()

start_idx = 0

def callback(outdata, frames, time, status):
    if status:
        print(status, file=sys.stderr)
    print(frames)
    global start_idx
    t = (start_idx + np.arange(frames)) / 48000
    t = t.reshape(-1, 1)
    outdata[:] = 0 * t
    if len(frequency) > 0:
        print("Playing")
    for freq in frequency:
        outdata[:] = outdata[:] + 0.2 * np.sin(2 * np.pi * freq * t)

    start_idx += frames

try:
    with sd.OutputStream(channels=1, callback=callback,
            samplerate=48000):
        input()
        listener.stop()
except Exception as e:
    print("Exception")
    listener.stop()
    exit()

如果您运行代码并按住 Q 键,键盘自动重复会启动并破坏整个侦听器。是否有一个 python 输入模块可以正确处理原始键盘输入?

第二件事是代码往往会经常使我的 Xorg 崩溃。我只运行了几次脚本,Xorg 就宕机了。我不知道为什么。 Linux 5.5.2-zen1-1-zen x86_64 GNU/Linux, X.Org 1.20.7.

第三件事是声音合成似乎有点滞后。回调函数的帧数似乎徘徊在 400 左右,在每秒 48000 个样本的速率下不到 10 毫秒,但实际的音频反馈感觉像是在数百毫秒的延迟。

【问题讨论】:

    标签: python audio keyboard pynput


    【解决方案1】:

    pygame 有一个很好的 keylistener 并且很容易构建一个显示输出的 GUI 窗口。它也适用于 Linux:

    import pygame
    
    def main_loop():
        #code
        loopExit = False
        while not loopExit:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    loopExit = True
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        #code
    
                if event.type == pygame.KEYUP:
                    if event.key == pygame.K_q:
                        #code
    

    https://www.pygame.org/docs/ref/key.html

    【讨论】:

    • 嗯,我设法让密钥与 pygame 一起使用,但我的 pygame.mixer.Sound 模块在我的示例中表现得像 sounddevice。
    • 你是在导入 sounddevice 来代替运行 pygame 吗? Pygame 有自己的声音设备模块,因此同时运行这两个模块可能会导致冲突。您应该放弃 sounddevice 代码并阅读 pygame 的音频模块。
    • 如果您仍然无法使用 pygame 的音频,您应该针对该特定问题在堆栈上打开另一个案例,因为它是独立的。
    • 不,我没有使用 pygame 导入声音设备。当我尝试将键盘切换到 pygame 时,我认为它也可能会替换 sounddevice。
    • 好吧,如果您使用的是键盘输入解决方案,或者我提出的一种变体,您能否用可信的答案联系一位兄弟? PyGame 声音驱动程序超出了您原始问题的范围。我非常乐意帮助您处理另一个案件。
    猜你喜欢
    • 2021-02-11
    • 2022-01-02
    • 2020-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-05
    • 2019-12-07
    • 1970-01-01
    相关资源
    最近更新 更多