Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set the default subtitles language in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

pyaudio (Part 1)

00:00 Congrats! You’ve made it to the last library we’ll cover for playing audio. In this video, you’ll learn how to use pyaudio, which also provides bindings for PortAudio. PortAudio keeps it cross-platform, so it will work on many different operating systems. pyaudio is a bit different from what we’ve talked about so far in that the audio you hear is played by writing to a stream. It might be easier to see this in action, so let’s get to installing it and head to the text editor.

00:28 I’m going to do pipenv install pyaudio,

00:33 and while that’s going, in the text editor I’m going to import pyaudio and then also import wave.

00:42 So, like before, set a filename, which in my case is 'hello.wav'. And then I’m going to need to set a chunk size as well, so let’s just do 1024. And a chunk is just how many samples are put into each data frame. Now it’s time to open the sound file, so we’ll call that wf and set that equal to wave.open(), and then pass in the filename, and you’ll want to read this as a binary.

01:12 Next, create an interface to PortAudio. So, with pyaudio, you can then call PyAudio(). Okay. Now it’s time to create that stream object, so say stream and set this equal to p.open(), so it’ll open up that interface. And then you’ll want to set your format, which is going to be p.get_format_from_width(), and then with the WAV file, you’ll get that sample width.

01:50 Make a channels, which will be the wf.getnchannels(),

02:00 the rate, which will be wf.getframerate(), and then output, set that equal to True. Okay, so there’s quite a bit going on here.

02:13 I’m actually just going to close this EXPLORER so we can see a little bit better and bring the terminal down.

02:20 There’s two main objects here. There’s the actual WAV file and then there’s the connection to the audio device. So, stream is going to be through this audio device, and it’s going to need a number of attributes that come from the WAV file.

02:36 So you’ll see that most of the data here like the sample width, the number of channels, and the frame rate are all coming from the WAV file and being passed into this interface. Setting output equal to True means that the sound is going to be played instead of recorded.

02:51 Now it’s time to read that data in chunks, so set data equal to, from your WAV file, you’ll want .readframes(), and use that chunk size that you created earlier,

03:07 and then start writing that audio data to the stream. So, while data does not equal an empty string (''),

03:17 you’ll want to do stream.write(data), and then set data equal to wf.readframes(), and grab that next chunk. So that’ll keep running until the file’s done, and after that, you can close the stream, and then terminate the interface. Okay.

03:39 So to recap that section there, you’re going to start chunking your WAV file into these little data frames, and as long as there’s another data frame, you’re going to write that data to the stream and then select the next chunk for the next frame. Once everything’s completed, you’re going to want to close that stream and then terminate your interface to the audio device. Okay! Let’s save this and see if it works.

04:08 “Hey there, this is a WAV file.” And there you go! Now, you might have picked up that this is pretty complex compared to what we’ve seen before, and it might seem strange to have to use, what, 24 lines of code? When different libraries only used a single line of code.

04:26 And there is a reason for this. pyaudio is going to give you a lot more low-level control over how you play your sounds, which can be helpful depending on the demands of your application. Now, let’s say you have a little desktop application that you want to have some sound effects in there to notify a user of something.

04:43 Those might be better handled using a higher-level library where you just need a couple lines of code. Another case might be a more audio-centric program that would require the level of control that pyaudio provides.

04:55 pyaudio is going to give you a lot more control over input and output devices and can actually check the CPU load for latency. So if you’re making something like a digital audio workstation used in music production, that’s the kind of project that would benefit greatly from the level of control that pyaudio will give you. And that’s it for playing audio!

05:14 Great job finishing this section of the course. You’ve learned how to use quite a few audio libraries in Python. Now that you can play that audio, it’s time to learn how to record it.

05:24 You’re going to see some familiar libraries in the next couple of videos, but now from a different angle. Thanks for watching.

Brendan Leber on Feb. 12, 2020

On my system with Python 3.8.1 wf.readframes() doesn’t return a string it returns a bytes object. So the test in the while loop always passes and the program continues with no sound playing.

Changing the while loop to use while data: fixed the infinite loop on my system and I think it should work for Python 2 and 3.

mikesult on Feb. 15, 2020

Thanks Brendan, for confirming the infinite loop I experienced. I also came to suggest while data: instead of while data != ‘’:

And thanks Joe Tatusko for the tutorials on audio.

Become a Member to join the conversation.