使用 PyAudio 录制扬声器输出
Posted
技术标签:
【中文标题】使用 PyAudio 录制扬声器输出【英文标题】:Record speakers output with PyAudio 【发布时间】:2014-12-21 19:19:03 【问题描述】:我正在尝试使用 PyAudio 录制计算机扬声器的输出。 我试图修改 PyAudio 文档中给出的代码示例,但它不起作用。
从技术上讲,没有错误。我得到了文件output.wav
,我可以打开它,但是没有声音。在 Audacity 上,我只能看到一条直线。
怎么了?
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
SPEAKERS = p.get_default_output_device_info()["hostApi"] #The part I have modified
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK,
input_host_api_specific_stream_info=SPEAKERS) #The part I have modified
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("* done recording")
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()
【问题讨论】:
【参考方案1】:万一有人像我一样在这个问题上遇到困难,我找到了PyAudio fork 来记录 Windows 上的输出。
解释:
官方 PyAudio 构建无法记录输出。但在 Windows Vista 及更高版本中,引入了一个新的 API,即 WASAPI,其中包括以环回模式打开流到输出设备的能力。在这种模式下,流的行为类似于输入流,具有记录输出音频流的能力。
要设置模式,必须设置一个特殊标志 (AUDCLNT_STREAMFLAGS_LOOPBACK)。由于官方版本不支持此标志,因此需要编辑 PortAudio 和 PyAudio,以添加环回支持。
新选项:
“as_loopback”:(真|假)
【讨论】:
Linux端怎么样?有什么相关信息吗?【参考方案2】:我必须使用 pyaudio 记录我的扬声器输出,并使用 pyaudio 的 documentation 中的一些配置和代码。
代码
"""PyAudio example: Record a few seconds of audio and save to a WAVE file."""
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("* done recording")
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()
配置
首先,运行pulseaudio,创建一个环回设备:
pacmd load-module module-loopback latency_msec=5
然后在pavucontrol中将默认(回退)设置为这个环回设备:
然后你可以启动脚本,等待5秒,你应该有一个output.wav。
【讨论】:
这是对 Linux 用户最有帮助的答案(如果使用 Pulseaudio)。我自己用 Pulseaudio 和 JACK 运行 Ubuntu (14.04/18.04) 和 Linux Mint (17.3/19.3),这很有效。您甚至可以编辑/etc/pulse/default.pa
并包含如上所示的一行(不带 pacmd
)以使其持久化。
这可以在树莓派上使用吗?我在 VLC 上运行了一些音频,我想将该音频发送到 FFT 算法并检查频率。
我不是 100% 确定,你必须尝试知道!在您的情况下,还有一个(更简单的)选项可以直接在 Python 中打开音频文件,而不是尝试从 VLC 间接录制它。查看 PyAudio 方法以打开音频文件。【参考方案3】:
如果您在 windows 平台上创建应用程序,您可以使用默认的立体声混音器虚拟设备来记录您 PC 的输出。
1) enable stereo mixer
2) 以这种方式将 PyAudio 连接到您的立体声混音器:
p = pyaudio.PyAudio()
stream = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
input_device_index = dev_index,
frames_per_buffer = CHUNK)
其中 dev_index 是您的立体声混音器的索引。
3)要获得所需的索引,您可以列出您的设备:
for i in range(p.get_device_count()):
print p.get_device_info_by_index(i)
另外,您可以添加下一个代码以按设备名称自动获取索引:
for i in range(p.get_device_count()):
dev = p.get_device_info_by_index(i)
if (dev['name'] == 'Stereo Mix (Realtek(R) Audio)' and dev['hostApi'] == 0):
dev_index = dev['index'];
print('dev_index', dev_index)
4) 继续使用 pyAudio,就像从麦克风录音一样
data = stream.read(CHUNK)
【讨论】:
这对我来说非常有效。如果您的 PC 上没有立体声混音器,您可以在此处获取编解码器:realtek.com/en/component/zoo/category/…。它不会通过耳机传送音频,您必须将音频输出设置为扬声器。【参考方案4】:您不能像输入一样从输出流进行录制。要录制,您需要将 PyAudio 连接到输入设备,例如麦克风。至少这是正常的做事方式。
先尝试连接麦克风,看看是否有任何东西。如果可行,请尝试做一些不寻常的事情。
作为迭代的小幅加速,而不是记录和查看文件,通常更容易打印出几个块的最大值以确保您引入了数据。通常,只需观看数字滚动并将它们与声音进行比较即可快速估计事物是否正确连接。
import audioop
mx = audioop.max(data, 2)
print mx
【讨论】:
【参考方案5】:即使您将扬声器作为输入打开,它也是一个输出流。说话人的hostApi值大概是0。 您可以检查每个连接设备的“maxInputChannels”和“maxOutputChannels”,扬声器的 maxInputChannels 应为 0。 您无法写入输入流,也无法读取输出流。
您可以使用以下代码检测可用的设备:
import pyaudio
# detect devices:
p = pyaudio.PyAudio()
host_info = p.get_host_api_info_by_index(0)
device_count = host_info.get('deviceCount')
devices = []
# iterate between devices:
for i in range(0, device_count):
device = p.get_device_info_by_host_api_device_index(0, i)
devices.append(device['name'])
print devices
获得所有连接的设备后,您可以检查每个设备的“hostApi”。 例如,如果说话人索引为 5,则:
p.get_device_info_by_host_api_device_index(0, 5)['hostApi']
【讨论】:
以上是关于使用 PyAudio 录制扬声器输出的主要内容,如果未能解决你的问题,请参考以下文章