2017-07-03 35 views
0

我目前正在尝试制作一个简单的脚本,它在键盘被按下时进行录音。我需要生成一些数据,因此脚本的意图是用句子提示终端,并且当演讲者按下一个键时,脚本将开始记录,在此处演讲者读取该句子。当这句话被说出,并记录应一键释放停止录音并由此创建的音频文件..pyaudio和pynput:键盘被按下/按住时录音

这是我目前有:

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 

我似乎有框架问题继续下降,没有任何记录。我用一个回调函数做了实现,因为我想可能是键盘线程可能会阻塞它,所以只是为了确保......但似乎没有记录,因为我一直得到IOerror ......我在做什么错误?

回答

0

只是重写像下面的回调。

def callback(self,in_data, frame_count, time_info, status): 
    print("callback") 
    if self.key_pressed == True: 
     #stream_queue.put(in_data) 
     print("record") 
     frames.append(in_data) 
     return (in_data, pyaudio.paContinue) 

    elif self.key_pressed == False: 
     #stream_queue.put(in_data) 
     frames.append(in_data) 
     return (in_data, pyaudio.paComplete) 

    else: 
     print("not record") 
     return (in_data,pyaudio.paContinue) 

然后它会工作。

1

这似乎至少在Windows,Python 3.5上工作。最初的代码最大的问题是: 它做了一个while循环,它几乎阻塞了所有东西, 帧没有被附加到帧列表。回调现在可以做到这一点。

from pynput import keyboard 
import time 
import pyaudio 
import wave 
import sched 
import sys 

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): 
    frames.append(in_data) 
    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.wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb') 
     self.wf.setnchannels(CHANNELS) 
     self.wf.setsampwidth(p.get_sample_size(FORMAT)) 
     self.wf.setframerate(RATE) 
    def on_press(self, key): 
     if key.char == 'r': 
      self.key_pressed = True 
     return True 

    def on_release(self, key): 
     if key.char == 'r': 
      self.key_pressed = False 
     return True 


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

def recorder(): 
    global started, p, stream, frames 

    if listener.key_pressed and not started: 
     # Start the recording 
     try: 
      stream = p.open(format=FORMAT, 
          channels=CHANNELS, 
          rate=RATE, 
          input=True, 
          frames_per_buffer=CHUNK, 
          stream_callback = callback) 
      print("Stream active:", stream.is_active()) 
      started = True 
      print("start Stream") 
     except: 
      raise 

    elif not listener.key_pressed and started: 
     print("Stop recording") 
     stream.stop_stream() 
     stream.close() 
     p.terminate() 
     listener.wf.writeframes(b''.join(frames)) 
     listener.wf.close() 
     print "You should have a wav file in the current directory" 
     sys.exit() 
    # Reschedule the recorder function in 100 ms. 
    task.enter(0.1, 1, recorder,()) 


print "Press and hold the 'r' key to begin recording" 
print "Release the 'r' key to end recording" 
task = sched.scheduler(time.time, time.sleep) 
task.enter(0.1, 1, recorder,()) 
task.run()