在按键事件

时间:2017-07-04 08:43:37

标签: python multithreading keyboard-events keyevent pyaudio

当我按下按钮时,我正试图从我的麦克风录音,问题是我正在使用的库无法检测到保持事件。它只在按下时检测到,这发生一次,这意味着麦克风只记录一个样本..

import pyaudio
import wave
from pynput import keyboard

CHUNK = 8192
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"

p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)         
frames = []

def on_press(key):
    if key == keyboard.Key.cmd_l:
        print('- Started recording -'.format(key))
        try:
            data = stream.read(CHUNK)
            frames.append(data)
        except IOError: 
            print 'warning: dropped frame' # can replace with 'pass' if no message desired 
    else:
        print('incorrect character {0}, press cmd_l'.format(key))


def on_release(key):
    print('{0} released'.format(
        key))
    if key == keyboard.Key.cmd_l:
        print('{0} stop'.format(key))
        keyboard.Listener.stop
        return False

print("* recording")


with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
    listener.join()

print("* done recording")

stream.stop_stream()
stream.close()
p.terminate()

wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()

我正在使用pynput进行键盘事件,使用pyaudio进行录制。 它似乎记录了何时按下cmd_l并在我释放时停止。问题是生成的音频文件不包含任何内容,或者非常短,如0.19s长。

我想这可能与stream.read必须被多次调用,而keypress只被记录一次,因此只记录了一个样本。

但是如果是这样的话我如何让它多次调用stream.read,同时还检测到它何时被释放? 或者是否有支持键盘上on_hold机制的库?

使用线程更新方法:

from pynput import keyboard
import time
import pyaudio
import wave

CHUNK = 8192
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"

p = pyaudio.PyAudio()
frames = []

def callback(in_data, frame_count, time_info, status):
    return (in_data, pyaudio.paContinue)

class MyListener(keyboard.Listener):
    def __init__(self):
        super(MyListener, self).__init__(self.on_press, self.on_release)
        self.key_pressed = None

        self.stream = p.open(format=FORMAT,
                             channels=CHANNELS,
                             rate=RATE,
                             input=True,
                             frames_per_buffer=CHUNK,
                             stream_callback = self.callback)
        print self.stream.is_active()

    def on_press(self, key):
        if key == keyboard.Key.cmd_l:
            self.key_pressed = True

    def on_release(self, key):
        if key == keyboard.Key.cmd_l:
            self.key_pressed = False

    def callback(self,in_data, frame_count, time_info, status):
        if self.key_pressed == True:
            return (in_data, pyaudio.paContinue)
        elif self.key_pressed == False:
            return (in_data, pyaudio.paComplete)
        else:
            return (in_data,pyaudio.paAbort)


listener = MyListener()
listener.start()
started = False

while True:
    time.sleep(0.1)
    if listener.key_pressed == True and started == False:
        started = True
        listener.stream.start_stream()
        print "start Stream"

    elif listener.key_pressed == False and started == True:
        print "Something coocked"
        listener.stream.stop_stream()
        listener.stream.close()
        p.terminate()

        wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
        wf.setnchannels(CHANNELS)
        wf.setsampwidth(p.get_sample_size(FORMAT))
        wf.setframerate(RATE)
        wf.writeframes(b''.join(frames))
        wf.close()

        started = False

我尝试了一种不同的方法来引入两个线程,一个监视键盘,另一个分类录制。但是这个解决方案不断丢帧,因此实际上没有记录任何东西?...

怎么回事?

2 个答案:

答案 0 :(得分:1)

您可以在this answer中执行类似于在单独的线程上定期运行函数的操作。似乎是最简单的解决方案。

答案 1 :(得分:0)

以下是您可能会这样做的示例:我已经通过单独的线程进行录制来修改您的代码。键盘按下/释放设置事件的状态,并且线程在设置事件时在循环中记录块。一个单独的事件用于告诉线程在录制完成后终止。这为我记录了多个32Kb块(8192 * 2个字符串* 16位)。

ReadFile(device, sector, 512, &bytesRead, NULL)

注意我使用了Ctrl键而不是Cmd键,因为它更适合我的机器。希望这很有用。