2017-07-03 82 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()