问题描述
我正在使用Python sounddevice库录制音频,但是我似乎无法消除应该连续的音频文件之间的〜0.25到〜0.5秒的间隔。我认为这是因为文件写入会占用时间,所以我学会了使用Multiprocessing和Queues来区分文件写入,但没有帮助。最令人困惑的是,日志表明Main()循环中的迭代接近无缝(只有1-5毫秒),但是奇怪的是audio_capture函数花费的时间比预期的长,甚至没有其他重要的事情要做。我试图尽可能减少这篇文章的脚本。我的研究都指出了这种线程化/多处理方法,所以我很困惑。
背景:Raspbian Buster上的3.7 我将数据分成多个部分,以使文件不会太大,并且我想编程任务必须应对这一挑战。之后,我还有另外4个子进程来做各种事情。
日志:audio_capture部分应该只需要10:00
08:26:29.991 --- Start of segment #0
08:36:30.627 --- End of segment #0 <<<<< This is >0.6 later than it should be
08:36:30.629 --- Start of segment #1 <<<<< This is near gapless with the prior event
脚本:
import logging
import sounddevice
from scipy.io.wavfile import write
import time
import os
from multiprocessing import Queue,Process
# this process is a near endless loop
def main():
fileQueue = Queue()
writerProcess = Process(target=writer,args=(fileQueue,))
writerProcess.start()
for i in range(9000):
fileQueue.put(audio_capture(i))
writerProcess.join()
# This func makes an audio data object from a sound source
def audio_capture(i):
cycleNumber = str(i)
logging.debug('Start of segment #' + cycleNumber)
# each cycle is 10 minutes at 32000Hz sample rate
audio = sounddevice.rec(frames=600 * 32000,samplerate=32000,channels=2)
name = time.strftime("%H-%M-%s") + '.wav'
path = os.path.join('/audio',name)
sounddevice.wait()
logging.debug('End of segment #' + cycleNumber)
return [audio,path]
# This function writes the files.
def writer(input_queue):
while True:
try:
parameters = input_queue.get()
audio = parameters[0]
path = parameters[1]
write(filename=path,rate=32000,data=audio)
logging.debug('File is written')
except:
pass
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG,format='%(asctime)s.%(msecs)03d --- %(message)s',datefmt='%H:%M:%s',handlers=[logging.FileHandler('/audio/log.txt'),logging.StreamHandler()])
main()
解决方法
documentation告诉我们sounddevice.rec()
并非无间断记录:
如果您需要更多控制权(例如,逐块无缝记录,重叠记录等),则应自己明确创建InputStream。如果NumPy不可用,则可以使用RawInputStream。
example programs中有多个无间隙记录的示例。
,使用Pyaudio,打开非阻塞音频流。您可以在Pyaudio文档首页上找到一个非常好的基本示例。选择一个缓冲区大小,我建议使用512或1024。现在只需将传入数据附加到numpy数组即可。有时我会在一个Numpy数组中存储30秒的音频。当到达段的末尾时,创建另一个空的numpy数组并重新开始。创建一个线程并将第一段保存在某个地方。录音将继续,不会丢失一个样本;)
编辑:如果要在一个文件中写入10分钟,我建议您仅创建10个数组,即1分钟,然后追加并保存它们。