我目前正在尝试录制一些话语,其中记录会话应该在按下并按住键时开始,并在释放时停止。我制作了用于记录和存储数据的python脚本..
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
脚本问题是音频文件似乎没有记录任何内容,我播放时文件的持续时间是未知的?..
我不确定我明白这里可能出现什么问题......?
更新
带输出的新版本:
from pynput import keyboard
import time
import pyaudio
import StringIO
import multiprocessing
from multiprocessing import Process, Queue, queues
import wave
CHUNK = 8192
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
frames = []
stream_queue = Queue()
class MyListener(keyboard.Listener):
def __init__(self):
super(MyListener, self).__init__(on_press=self.on_press, on_release=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 ("Stream active? " + str(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):
print "callback"
if self.key_pressed == True:
#stream_queue.put(in_data)
frames.append(data)
return (in_data, pyaudio.paContinue)
elif self.key_pressed == False:
#stream_queue.put(in_data)
frames.append(data)
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 - Key is down")
elif listener.key_pressed == True and started == True:
print("stream has started and key is still down")
print("Stream is active? " + str(listener.stream.is_active()))
print("Stream is stopped? " + str(listener.stream.is_stopped()))
print("Stream is time? " + str(listener.stream.get_time()))
elif listener.key_pressed == False and started == True:
print("Key has been released")
listener.stream.stop_stream()
listener.stream.close()
print("stream has been closed")
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
输出:
python File2.py
Stream active? True
callback
Start stream - Key is down
stream has started and key is still down
Stream is active? False
Stream is stopped? False
Stream is time? 134638.797766
stream has started and key is still down
Stream is active? False
Stream is stopped? False
Stream is time? 134638.902259
stream has started and key is still down
Stream is active? False
Stream is stopped? False
Stream is time? 134639.006739
stream has started and key is still down
Stream is active? False
Stream is stopped? False
Stream is time? 134639.111282
stream has started and key is still down
Stream is active? False
Stream is stopped? False
Stream is time? 134639.215573
stream has started and key is still down
Stream is active? False
Stream is stopped? False
Stream is time? 134639.320448
stream has started and key is still down
Stream is active? False
Stream is stopped? False
Stream is time? 134639.424682
stream has started and key is still down
Stream is active? False
Stream is stopped? False
Stream is time? 134639.528631
stream has started and key is still down
Stream is active? False
Stream is stopped? False
Stream is time? 134639.633699
stream has started and key is still down
Stream is active? False
Stream is stopped? False
Stream is time? 134639.738129
stream has started and key is still down
Stream is active? False
Stream is stopped? False
Stream is time? 134639.842747
Key has been released
stream has been closed
^CTraceback (most recent call last):
File "File2.py", line 67, in <module>
time.sleep(0.1)
KeyboardInterrupt
MacBook-Pro:~$ play output.wav
output.wav:
File Size: 44
Encoding: Signed PCM
Channels: 2 @ 16-bit
Samplerate: 44100Hz
Replaygain: off
Duration: unknown
In:0.00% 00:00:00.00 [00:00:00.00] Out:0 [ | ] Clip:0
Done.
对我来说似乎很奇怪的事情是
listener.stream.start_stream()
callback
仅打印一次,但每次回调将数据存储到帧时都应打印,这显然只发生一次。 答案 0 :(得分:5)
我已经请求了您的第一版。请完成所有这些global
。我不熟悉pynput
,所以我只关注DOC,使用最简单的{{1}示例}。所以这里的代码适用于win7和python3.holding pynput
开始记录,space
退出脚本。
esc
更新:
我只是重写了你的回调,它可能适合你但不适合我。
from pynput import keyboard
import pyaudio
import wave
import time
CHUNK = 8192
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
record_on = False
complete_tag = False
frames = []
def callback(in_data, frame_count, time_info, status):
print("callback called")
callback_flag = pyaudio.paContinue
# global record_on
if record_on:
# global frames
frames.append(in_data)
if complete_tag:
callback_flag = pyaudio.paComplete
return in_data, callback_flag
def on_press(key):
global record_on
print(record_on)
if key == keyboard.Key.space:
record_on = True
def on_release(key):
global record_on
global complete_tag
record_on = False
complete_tag = True
if key == keyboard.Key.esc:
return False
if __name__ == '__main__':
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK,
stream_callback=callback)
with keyboard.Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
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()
你不理解回调,当你调用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)
时,当数据来自硬件时会调用回调。因此逻辑应该像我的版本而不是p.open with callback
一样写回调。
所以,所有问题都在第一次调用回调之后,流接收while 1: time.sleep(0.1)
,然后流停止。所以回调只调用一次,所以你的.wav文件只有元数据,没有持续时间
我将整个代码更改为
PAabort
答案 1 :(得分:2)
您尚未填写列表frames
。
你应该这样做来填充你的清单:
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
因为您在这里使用空列表:
wf.writeframes(b''.join(frames))
我希望这适合你。
干杯!