Speaker Recording Using PyAudio

I am trying to write output through computer speakers using PyAudio.
I tried to change the sample code provided in the PyAudio documentation, but it does not work.

There is no technical error. I get output.wav file and can open it, but there is no sound. On Audacity, I see only a straight line.

What's wrong?

 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() 
+7
source share
5 answers

In case someone still stumbles about it, like me, I found PyAudio fork to write output to Windows.

Explanation:

The official PyAudio assembly cannot write output. BUT with Windows Vista and above, the new WASAPI API was introduced, which includes the ability to open a stream for an output device in reverse loop mode. In this mode, the stream will behave as an input stream with the ability to record the outgoing audio stream.

To set the mode, you must set a special flag ( AUDCLNT_STREAMFLAGS_LOOPBACK ). Since this flag is not supported in the official build, you need to edit PortAudio, as well as PyAudio, to add support for reverse loops.

New option:

"as_loopback" :( true | false)

+10
source

You cannot write from the output stream as if it were entered. To record, you need to connect PyAudio to the input device , for example, to the microphone. At least this is the usual way to do something.

First try connecting to the microphone and see if you get anything. If this works, try to do something unusual.

As a slight acceleration for your iterations, rather than writing and viewing a file, it is often easier to just print max for a few chunks to make sure you enter the data. Usually just by scrolling through numbers and comparing them with sound, you quickly evaluate whether they are connected correctly.

 import audioop mx = audioop.max(data, 2) print mx 
+1
source

The speaker is an output stream, even if you open it as an input. The hostApi value for the speaker is probably 0. You can check the 'maxInputChannels' and 'maxOutputChannels' for each connected device, and the maxInputChannels for the speaker should be 0. You cannot write to the input stream and cannot read from the output stream.

You can discover 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 device. For example, if the speaker index is 5, then:

 p.get_device_info_by_host_api_device_index(0, 5)['hostApi'] 
0
source

I recorded the output of my column using pyaudio with some configuration and code from the pyaudio documentation .

The 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 feedback device:

 pacmd load-module module-loopback latency_msec=5 

Then set the default value (backup) for this feedback device in pavucontrol:

Pavu control example

Then you can run the script, wait 5 seconds, and you should have the output.wav file.

0
source

If you are creating an application on a Windows platform, you can use the default stereo mixer virtual device to record the output of your PC.

1) turn on the stereo mixer

2) connect PyAudio to your stereo mixer as follows:

 p = pyaudio.PyAudio() stream = p.open(format = FORMAT, channels = CHANNELS, rate = RATE, input = True, input_device_index = dev_index, frames_per_buffer = CHUNK) 

where dev_index is the index of your stereo mixer .

3) to get the necessary index, you can list your devices:

 for i in range(p.get_device_count()): print p.get_device_info_by_index(i) 

You can also add the following code to automatically retrieve the index by device name:

 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']; 

4) continue to work with pyAudio, as in the case of recording from a microphone

 data = stream.read(CHUNK) 
0
source

Source: https://habr.com/ru/post/1205543/


All Articles