I'm trying to record the ouput from my computer speakers with PyAudio. I tried to modify the code example given in the PyAudio documentation, but it doesn't work. Here's my code:
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()
Could someone help me please?
In case someone is still stumbling over this like me, I found a PyAudio fork to record the output on windows. https://github.com/intxcc/pyaudio_portaudio
Explanation:
The official PyAudio build isn't able to record the output. BUT with Windows Vista and above, a new API, WASAPI was introduced, which includes the ability to open a stream to an output device in loopback mode. In this mode the stream will behave like an input stream, with the ability to record the outgoing audio stream.
To set the mode, one has to set a special flag (AUDCLNT_STREAMFLAGS_LOOPBACK, https://msdn.microsoft.com/de-de/library/windows/desktop/dd316551(v=vs.85).aspx ). Since this flag is not supported in the official build one needs to edit PortAudio as well as PyAudio, to add loopback support.
New option: "as_loopback":(true|false)
You can't record from an output stream as though it were input. To record, you need to connect PyAudio to an input device, like a microphone. At least that's the normal way to do things.
Try connecting to a microphone first, and see if you get anything. If this works, then try doing something unusual.
As a small speedup to your iterations, rather than recording and looking at the file, it's often easier just to print out the max for a few chunks to make sure you're bringing in data. Usually just watching the numbers scroll by and comparing them to the sound gives a quick estimate of whether things are correctly connected.
import audioop
mx = audioop.max(data, 2)
print mx
The speaker is an output stream even if you open it as an input. The hostApi value of the speaker is probably 0. You can check the 'maxInputChannels' and 'maxOutputChannels' of every connected devices and the maxInputChannels for the speaker shall be 0. You can't write to an input stream and you can't read from an output stream.
You can detect the available devices with the following code:
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
After you get all the connected devices you can check the 'hostApi' of each devices. For instance if the speaker index is 5 than:
p.get_device_info_by_host_api_device_index(0, 5)['hostApi']
I got to record my speaker output with pyaudio with some configuration and code from pyaudio's documentation.
Code
"""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()
Configuration
First, with pulseaudio running, create a loopback device:
pacmd load-module module-loopback latency_msec=5
Then set the default (fallback) to this loopback device in pavucontrol:
Then you can start the script, wait 5 seconds, and you should have an output.wav.
来源:https://stackoverflow.com/questions/26573556/record-speakers-output-with-pyaudio