Python:消除录制的音频片段之间的间隙

问题描述

我正在使用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分钟,然后追加并保存它们。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...