输出音频文件创建不正确,或持续时间未知
Output audio file not created correctly, or has unknown duration time
我目前正在尝试记录一些话语,其中记录会话应在按下并按住某个键时开始,并在释放时停止。我制作了 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
只打印一次,但每次回调将数据存储到帧时都应该打印,这显然只发生一次。
- output.wav 文件持续时间未知?为什么?
您还没有填写您的列表,frames
。
您应该这样做来填充您的列表:
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
因为您在这里使用的是空列表:
wf.writeframes(b''.join(frames))
希望这对你有用。
干杯!
我有你的第一版request.Sorry所有这些global
。我不熟悉pynput
,所以我只是按照DOC,使用最简单的例子pynput
。所以这里的代码可以在 win7 和 python3.holding 上正常工作,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
时,当数据来自hardware.so时会调用回调逻辑应该像我的版本一样写在回调而不是while 1: time.sleep(0.1)
.
所以,你所有的问题都是在第一次调用回调之后,流接收PAabort
,然后流 stop.so 回调只被调用一次,所以你的 .wav 文件只有元数据并且没有持续时间。
并且我将您的整个代码更改为
from pynput import keyboard
import pyaudio
import wave
CHUNK = 8192
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
WAVE_OUTPUT_FILENAME = "output.wav"
class MyListener(keyboard.Listener):
def __enter__(self):
self.p = pyaudio.PyAudio()
self.stream = self.p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK,
stream_callback = self.callback)
self.start()
return self
def __init__(self):
super(MyListener, self).__init__(on_press=self.on_press, on_release=self.on_release)
self.key_pressed = False
self.complete_tag = False
self.frames = []
def on_press(self, key):
if key == keyboard.Key.space:
self.key_pressed = True
def on_release(self, key):
if key == keyboard.Key.space:
self.key_pressed = False
self.complete = True
if key == keyboard.Key.esc:
return False
def callback(self,in_data, frame_count, time_info, status):
callback_flag = pyaudio.paContinue
if self.key_pressed:
self.frames.append(in_data)
if self.complete_tag:
callback_flag = pyaudio.paComplete
return in_data, callback_flag
def __exit__(self, exc_type, exc_value, traceback):
self.stream.stop_stream()
self.stream.close()
self.p.terminate()
self.stop()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(self.p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(self.frames))
wf.close()
with MyListener() as listener:
listener.join()
我目前正在尝试记录一些话语,其中记录会话应在按下并按住某个键时开始,并在释放时停止。我制作了 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
只打印一次,但每次回调将数据存储到帧时都应该打印,这显然只发生一次。 - output.wav 文件持续时间未知?为什么?
您还没有填写您的列表,frames
。
您应该这样做来填充您的列表:
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
因为您在这里使用的是空列表:
wf.writeframes(b''.join(frames))
希望这对你有用。
干杯!
我有你的第一版request.Sorry所有这些global
。我不熟悉pynput
,所以我只是按照DOC,使用最简单的例子pynput
。所以这里的代码可以在 win7 和 python3.holding 上正常工作,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
时,当数据来自hardware.so时会调用回调逻辑应该像我的版本一样写在回调而不是while 1: time.sleep(0.1)
.
所以,你所有的问题都是在第一次调用回调之后,流接收PAabort
,然后流 stop.so 回调只被调用一次,所以你的 .wav 文件只有元数据并且没有持续时间。
并且我将您的整个代码更改为
from pynput import keyboard
import pyaudio
import wave
CHUNK = 8192
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
WAVE_OUTPUT_FILENAME = "output.wav"
class MyListener(keyboard.Listener):
def __enter__(self):
self.p = pyaudio.PyAudio()
self.stream = self.p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK,
stream_callback = self.callback)
self.start()
return self
def __init__(self):
super(MyListener, self).__init__(on_press=self.on_press, on_release=self.on_release)
self.key_pressed = False
self.complete_tag = False
self.frames = []
def on_press(self, key):
if key == keyboard.Key.space:
self.key_pressed = True
def on_release(self, key):
if key == keyboard.Key.space:
self.key_pressed = False
self.complete = True
if key == keyboard.Key.esc:
return False
def callback(self,in_data, frame_count, time_info, status):
callback_flag = pyaudio.paContinue
if self.key_pressed:
self.frames.append(in_data)
if self.complete_tag:
callback_flag = pyaudio.paComplete
return in_data, callback_flag
def __exit__(self, exc_type, exc_value, traceback):
self.stream.stop_stream()
self.stream.close()
self.p.terminate()
self.stop()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(self.p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(self.frames))
wf.close()
with MyListener() as listener:
listener.join()