使用PyAudio录制扬声器输出

26
我试图使用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()
5个回答

24

如果有人像我一样遇到了困难,我找到了一个 PyAudio分支 可以在Windows上录制输出音频。

解释:

官方的PyAudio版本无法记录输出音频。但是,自Windows Vista及以上版本推出了新API——WASAPI,其中包括打开流以进行回环模式输出设备的功能。在此模式下,流将表现为输入流,具有记录传出音频流的能力。

要设置该模式,必须设置特殊标志(AUDCLNT_STREAMFLAGS_LOOPBACK)。由于该标志在官方版本中不被支持,因此需要编辑PortAudio和PyAudio以添加回环支持。

新选项:

"as_loopback":(true|false)


1
Linux方面怎么样?有关于它的任何信息吗? - ati ince
4
针对下一个人(2022更新):简而言之:请使用PyAudioWPatch。这个pyaudio分支似乎正在积极开发,并明确支持此用例。仓库中甚至有一个完整的示例 - Kent

17

如果您在Windows平台上创建应用程序,可以使用默认的立体声混音器虚拟设备记录PC的输出。

1) 启用立体声混音器。

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)

这对我来说完美地运作了。如果你的电脑上没有立体声混音器,你可以在这里获取编解码器:https://www.realtek.com/en/component/zoo/category/pc-audio-codecs-high-definition-audio-codecs-software。它不会通过耳机路由音频,你必须将音频输出设置为扬声器。 - SixenseMan

14
I got to record my speaker output with pyaudio with some configuration and code from pyaudio's 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中将默认(回退)设置为此回环设备:

Pavu control example

然后您可以启动脚本,等待5秒钟,然后应该会有一个output.wav输出。

这是对于使用Pulseaudio的Linux用户最有帮助的答案。我自己在Ubuntu(14.04/18.04)和Linux Mint(17.3/19.3)上运行Pulseaudio和JACK,这很有效。你甚至可以编辑/etc/pulse/default.pa并包含像上面那样的一行(不需要pacmd),以使其持久化。 - Moonbase
这个能在树莓派上运行吗?我有一些在VLC上运行的音频,我想将其发送到FFT算法并检查频率。 - Souvik Saha
我不是100%确定,你必须尝试才能知道!在你的情况下,还有一个(更简单)的选择,就是直接在Python中打开音频文件,而不是尝试从VLC间接录制它。研究PyAudio方法以打开音频文件。 - antoineMoPa

2
您不能像输入流一样从输出流中录制。要进行录制,您需要将PyAudio连接到一个输入设备,例如麦克风。至少这是正常操作的方式。
首先尝试连接到麦克风,看看是否有任何反应。如果可以工作,则尝试做一些不寻常的事情。
为了加快迭代速度,而不是记录并查看文件,通常更容易只打印出几个块的最大值,以确保您正在带入数据。通常仅观察数字滚动并将其与声音进行比较即可快速估算是否正确连接了所有内容。
import audioop
mx = audioop.max(data, 2)
print mx

1
说话者是一个输出流,即使您将其作为输入打开。说话者的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']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接