如何在 python 中播放实时音频同时还不断录制?
How to playback realtime audio in python while also constantly recording?
我想制作一个语音干扰器。它本质上是向你重复你刚才说的话,但它是连续的。我试图使用 sounddevice 库并在回放的同时录制我所说的内容。然后我将其更改为最初记录我所说的内容,然后在播放它的同时也记录一些新内容。但是它没有像我希望的那样运行。对其他图书馆有什么建议吗?或者,如果有人看到对我已有的代码的建议。
不是不断地给我回放,而是开始和停止。它以指定的持续时间间隔执行此操作。所以它将录制 500 毫秒,然后回放 500 毫秒,然后再次开始录制。想要的行为是 - 录制 500 毫秒,同时以 ms 延迟播放正在录制的音频。
import sounddevice as sd
import numpy as np
fs = 44100
sd.default.samplerate = fs
sd.default.channels = 2
#the above is to avoid having to specify arguments in every function call
duration = .5
myarray = sd.rec(int(duration*fs))
while(True):
sd.wait()
myarray = sd.playrec(myarray)
sd.wait()
我发现您尝试使用 myarray
作为 .playrec()
函数的输入和输出可能存在问题。我建议使用两个阵列,一个用于录制现场音频,一个用于回放录制的音频。
除了使用 .playrec()
命令,您还可以在 .record()
和 .play()
之间快速切换,并在 while 循环中稍作延迟。
例如,下面的代码应该录制一毫秒,等待一毫秒,然后播放一毫秒的音频:
duration = 0.001
while(True):
myarray= sd.rec(int(duration*fs))
sd.wait()
sd.play(myarray, (int(duration*fs)))
播放后没有毫秒延迟,因为您想立即返回下一毫秒的录音。 但是,应该注意的是,这不会将您的音频记录保留超过一毫秒!您必须添加自己的代码以添加到指定大小的数组中并随着时间的推移填满它。
转述我自己在 中的回答:
The functions sd.play()
, sd.rec()
and sd.playrec()
are not meant to be used repeatedly in rapid succession. Internally, they each time create an sd.OutputStream
, sd.InputStream
or sd.Stream
(respectively), play/record the audio data and close the stream again. Because of opening and closing the stream, gaps will occur. This is expected.
对于连续播放,您可以通过创建单个流并在其上调用 read() and/or write() 方法来使用所谓的 "blocking mode"。
或者,我通常更喜欢的是,您可以通过创建自定义 "callback" 函数并在创建时将其传递给流来使用所谓的 "non-blocking mode"。
在此回调函数中,您可以例如将输入数据写入 queue.Queue 并从同一队列读取输出数据。通过预先在队列中填充一定数量的零,您可以指定输入和输出之间的延迟时间。
您可以查看 examples 以了解如何使用回调函数和队列。
如果您需要更多帮助,请告诉我,然后我可以尝试提供具体的代码示例。
我想制作一个语音干扰器。它本质上是向你重复你刚才说的话,但它是连续的。我试图使用 sounddevice 库并在回放的同时录制我所说的内容。然后我将其更改为最初记录我所说的内容,然后在播放它的同时也记录一些新内容。但是它没有像我希望的那样运行。对其他图书馆有什么建议吗?或者,如果有人看到对我已有的代码的建议。
不是不断地给我回放,而是开始和停止。它以指定的持续时间间隔执行此操作。所以它将录制 500 毫秒,然后回放 500 毫秒,然后再次开始录制。想要的行为是 - 录制 500 毫秒,同时以 ms 延迟播放正在录制的音频。
import sounddevice as sd
import numpy as np
fs = 44100
sd.default.samplerate = fs
sd.default.channels = 2
#the above is to avoid having to specify arguments in every function call
duration = .5
myarray = sd.rec(int(duration*fs))
while(True):
sd.wait()
myarray = sd.playrec(myarray)
sd.wait()
我发现您尝试使用 myarray
作为 .playrec()
函数的输入和输出可能存在问题。我建议使用两个阵列,一个用于录制现场音频,一个用于回放录制的音频。
除了使用 .playrec()
命令,您还可以在 .record()
和 .play()
之间快速切换,并在 while 循环中稍作延迟。
例如,下面的代码应该录制一毫秒,等待一毫秒,然后播放一毫秒的音频:
duration = 0.001
while(True):
myarray= sd.rec(int(duration*fs))
sd.wait()
sd.play(myarray, (int(duration*fs)))
播放后没有毫秒延迟,因为您想立即返回下一毫秒的录音。 但是,应该注意的是,这不会将您的音频记录保留超过一毫秒!您必须添加自己的代码以添加到指定大小的数组中并随着时间的推移填满它。
转述我自己在
The functions
sd.play()
,sd.rec()
andsd.playrec()
are not meant to be used repeatedly in rapid succession. Internally, they each time create ansd.OutputStream
,sd.InputStream
orsd.Stream
(respectively), play/record the audio data and close the stream again. Because of opening and closing the stream, gaps will occur. This is expected.
对于连续播放,您可以通过创建单个流并在其上调用 read() and/or write() 方法来使用所谓的 "blocking mode"。
或者,我通常更喜欢的是,您可以通过创建自定义 "callback" 函数并在创建时将其传递给流来使用所谓的 "non-blocking mode"。 在此回调函数中,您可以例如将输入数据写入 queue.Queue 并从同一队列读取输出数据。通过预先在队列中填充一定数量的零,您可以指定输入和输出之间的延迟时间。
您可以查看 examples 以了解如何使用回调函数和队列。
如果您需要更多帮助,请告诉我,然后我可以尝试提供具体的代码示例。