使用PyAudio录制扬声器输出
我想用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 个回答
扬声器其实是一个输出设备,即使你把它当作输入设备来打开。扬声器的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连接到一个输入设备,比如麦克风。这是正常的操作方式。
先试着连接麦克风,看看能不能录到声音。如果能录到,那再尝试一些不寻常的操作。
为了加快你的测试速度,通常不需要每次都录音然后查看文件,直接打印出几个数据块的最大值就能确认你是否在接收数据。通常只要看着数字滚动,并把它们和声音进行比较,就能快速判断连接是否正常。
import audioop
mx = audioop.max(data, 2)
print mx
我用pyaudio录制了我的扬声器输出,使用了一些配置和代码,这些内容来自pyaudio的文档。
代码
"""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文件。
如果你在Windows平台上创建一个应用程序,你可以使用默认的立体声混音器虚拟设备来录制你电脑的声音输出。
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)
如果还有人像我一样在这个问题上碰壁,我找到了一款可以在Windows上录制输出的PyAudio分支。
解释一下:
官方的PyAudio版本无法录制输出音频。但是从Windows Vista开始,推出了一种新的API,叫做WASAPI,它可以让你以循环模式打开输出设备的音频流。在这种模式下,这个流就像一个输入流,可以录制出去的音频。
要设置这种模式,需要设置一个特殊的标志(AUDCLNT_STREAMFLAGS_LOOPBACK)。因为这个标志在官方版本中不被支持,所以需要对PortAudio和PyAudio进行一些修改,以添加循环录制的功能。
新的选项:
"as_loopback":(true|false)