Python: 消除录制音频片段之间的间隙
Python: Eliminating gaps between segments of recorded audio
我正在使用 Python 声音设备库来录制音频,但我似乎无法消除连续音频文件之间约 0.25 到 0.5 秒的间隔。我认为这是因为文件写入占用时间,所以我学会了使用 Multiprocessing 和 Queues 来分离文件写入但它并没有帮助。最令人困惑的是,日志表明 Main() 循环中的迭代几乎没有间隙(只有 1-5 毫秒),但神秘的是 audio_capture 函数花费的时间比预期的要长,即使没有其他重要的事情发生完毕。为此post,我尽量减少了脚本。我的研究都指向这个 threading/multiprocessing 方法,所以我很困惑。
背景: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()
不适合无缝记录:
If you need more control (e.g. block-wise gapless recording, overlapping recordings, …), you should explicitly create an InputStream yourself. If NumPy is not available, you can use a RawInputStream.
中有多个无间隙记录示例
使用Pyaudio,打开一个non-blockingaudio-stream。您可以在 Pyaudio 文档首页上找到一个非常好的基本示例。选择缓冲区大小,我推荐 512 或 1024。现在只需将传入数据附加到 numpy 数组即可。我有时会在一个 numpy 数组中存储长达 30 秒的音频。当到达一个段的末尾时,创建另一个空的 numpy 数组并重新开始。创建一个线程并将第一段保存在某处。录音将继续,不会丢弃一个样本;)
编辑:如果你想在一个文件中写 10 分钟,我建议只创建 10 个数组 á 1 分钟,然后追加并保存它们。
我正在使用 Python 声音设备库来录制音频,但我似乎无法消除连续音频文件之间约 0.25 到 0.5 秒的间隔。我认为这是因为文件写入占用时间,所以我学会了使用 Multiprocessing 和 Queues 来分离文件写入但它并没有帮助。最令人困惑的是,日志表明 Main() 循环中的迭代几乎没有间隙(只有 1-5 毫秒),但神秘的是 audio_capture 函数花费的时间比预期的要长,即使没有其他重要的事情发生完毕。为此post,我尽量减少了脚本。我的研究都指向这个 threading/multiprocessing 方法,所以我很困惑。
背景: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()
不适合无缝记录:
中有多个无间隙记录示例If you need more control (e.g. block-wise gapless recording, overlapping recordings, …), you should explicitly create an InputStream yourself. If NumPy is not available, you can use a RawInputStream.
使用Pyaudio,打开一个non-blockingaudio-stream。您可以在 Pyaudio 文档首页上找到一个非常好的基本示例。选择缓冲区大小,我推荐 512 或 1024。现在只需将传入数据附加到 numpy 数组即可。我有时会在一个 numpy 数组中存储长达 30 秒的音频。当到达一个段的末尾时,创建另一个空的 numpy 数组并重新开始。创建一个线程并将第一段保存在某处。录音将继续,不会丢弃一个样本;)
编辑:如果你想在一个文件中写 10 分钟,我建议只创建 10 个数组 á 1 分钟,然后追加并保存它们。