159

How can I play audio (it would be like a 1 second sound) from a Python script?

It would be best if it was platform independent, but firstly it needs to work on a Mac.

I know I could just execute the afplay file.mp3 command from within Python, but is it possible to do it in raw Python? I would also be better if it didn't rely on external libraries.

3
  • Pyglet has the ability to play back audio through an external library called AVbin. Pyglet is a ctypes wrapper around native system calls on each platform it supports. Unfortunately, I don't think anything in the standard library will play audio back. Commented Nov 4, 2008 at 14:37
  • If you need portable Python audio library try PyAudio. It certainly has a mac port. As for mp3 files: it's certainly doable in "raw" Python, only I'm afraid you'd have to code everything yourself :). If you can afford some external library I've found some PyAudio - PyLame sample here. Commented Feb 3, 2009 at 15:08
  • try just_playback. It's a wrapper around miniaudio that provides playback control functionality like pausing, resuming, seeking and setting the playback volume. Commented May 9, 2021 at 22:29

25 Answers 25

72

Try playsound which is a Pure Python, cross platform, single function module with no dependencies for playing sounds.

Install via pip:

$ pip install playsound 

Once you've installed, you can use it like this:

from playsound import playsound playsound('/path/to/a/sound/file/you/want/to/play.mp3') 
Sign up to request clarification or add additional context in comments.

12 Comments

Reading this made me so emotional. My eyes literally teared up with happiness. Did not expect that kind of reaction from myself. (They linked to a module I made.)
+1 for playsound. I just tested out a couple solutions here, and this one worked the easiest for me. Unfortunately the pygame solution didn't work for me, during a brief test.
I love how simple and probabilistic this module is ( :
Doesn't work if filename contains non-ascii characters though.
playsound is relying on a python 2 subprocess. Please use pip3 install PyObjC if you want playsound to run more efficiently.
|
56

Your best bet is probably to use pygame/SDL. It's an external library, but it has great support across platforms.

pygame.mixer.init() pygame.mixer.music.load("file.mp3") pygame.mixer.music.play() 

You can find more specific documentation about the audio mixer support in the pygame.mixer.music documentation

5 Comments

For me, this was not working. I mean, it was playing but no sound. I added time.sleep(5) at the end and that worked. Python 3.6 on Windows 8.1
It doesn't work on fedora with standard ".wav", ".mp3" and ".ogg" (Unable to open file 'filename.format')
@Calvin-Ruiz I just confirmed that I am able to use the above code in FC31 to play MP3 and Ogg files. I think you have a larger problem that likely needs some detailed knowledge of your platform.
This doesn't appear to work un ubuntu 20.10
It works fine with win10. The recording needs some time to get to the output so I tried for testing purposes to move the command up on the stack and it worked.
27

Take a look at Simpleaudio, which is a relatively recent and lightweight library for this purpose:

> pip install simpleaudio 

Then:

import simpleaudio as sa wave_obj = sa.WaveObject.from_wave_file("path/to/file.wav") play_obj = wave_obj.play() play_obj.wait_done() 

Make sure to use uncompressed 16 bit PCM files.

1 Comment

Nice, thanks -- useful for games that need to play short sound effects, and supports Python 3.
21

You can find information about Python audio here: http://wiki.python.org/moin/Audio/

It doesn't look like it can play .mp3 files without external libraries. You could either convert your .mp3 file to a .wav or other format, or use a library like PyMedia.

3 Comments

But how do I play a .wav file?
@minseong See here, for example.
PyMedia is highly outdated in the meanwhile.
20

Sorry for the late reply, but I think this is a good place to advertise my library ...

AFAIK, the standard library has only one module for playing audio: ossaudiodev. Sadly, this only works on Linux and FreeBSD.

UPDATE: There is also winsound, but obviously this is also platform-specific.

For something more platform-independent, you'll need to use an external library.

My recommendation is the sounddevice module (but beware, I'm the author).

The package includes the pre-compiled PortAudio library for Mac OS X and Windows, and can be easily installed with:

pip install sounddevice --user 

It can play back sound from NumPy arrays, but it can also use plain Python buffers (if NumPy is not available).

To play back a NumPy array, that's all you need (assuming that the audio data has a sampling frequency of 44100 Hz):

import sounddevice as sd sd.play(myarray, 44100) 

For more details, have a look at the documentation.

It cannot read/write sound files, you'll need a separate library for that.

2 Comments

Great! Just what I needed to make a class demo program about waves.
ossaudiodev is long deprecated now and actually was removed already.
19

In pydub we've recently opted to use ffplay (via subprocess) from the ffmpeg suite of tools, which internally uses SDL.

It works for our purposes – mainly just making it easier to test the results of pydub code in interactive mode – but it has it's downsides, like causing a new program to appear in the dock on mac.

I've linked the implementation above, but a simplified version follows:

import subprocess def play(audio_file_path): subprocess.call(["ffplay", "-nodisp", "-autoexit", audio_file_path]) 

The -nodisp flag stops ffplay from showing a new window, and the -autoexit flag causes ffplay to exit and return a status code when the audio file is done playing.

edit: pydub now uses pyaudio for playback when it's installed and falls back to ffplay to avoid the downsides I mentioned. The link above shows that implementation as well.

2 Comments

Pydub looks like it has quite a bit of potential as a wrapper library - I'm installing it now.
Damn PyDub looks nice and it's still really active.
7

Aaron's answer appears to be about 10x more complicated than necessary. Just do this if you only need an answer that works on OS X:

from AppKit import NSSound sound = NSSound.alloc() sound.initWithContentsOfFile_byReference_('/path/to/file.wav', True) sound.play() 

One thing... this returns immediately. So you might want to also do this, if you want the call to block until the sound finishes playing.

from time import sleep sleep(sound.duration()) 

Edit: I took this function and combined it with variants for Windows and Linux. The result is a pure python, cross platform module with no dependencies called playsound. I've uploaded it to pypi.

pip install playsound 

Then run it like this:

from playsound import playsound playsound('/path/to/file.wav', block = False) 

MP3 files also work on OS X. WAV should work on all platforms. I don't know what other combinations of platform/file format do or don't work - I haven't tried them yet.

11 Comments

I get the following error: "Can't convert 'bytes' object to str implicitly" on Python 3.5 (Windows).
@ErwinMayer - Are you talking about with the playsound module I wrote? I haven't tested it on anything newer than Python 2.7.11... I can certainly look into fixing this on 3.5...
Indeed. It must be due to Python 3 differences.
AppKit is a dependency.
@ArtOfWarfare That's simply not true. It is installed with the system python, but not with most distributions, including the official distributions from python.org. Most folks I know who use python install one of the distributions to get past the SIP restrictions. To get AppKit for most distributions, a user needs to pip install pyobjc. Which makes it most definitely a dependency.
|
5

You can see this: http://www.speech.kth.se/snack/

s = Sound() s.read('sound.wav') s.play() 

1 Comment

Looks so clean, I wish there was a pip package for this. Ease of install is key
5

This is the easiest & best iv'e found. It supports Linux/pulseaudio, Mac/coreaudio, and Windows/WASAPI.

import soundfile as sf import soundcard as sc default_speaker = sc.default_speaker() samples, samplerate = sf.read('bell.wav') default_speaker.play(samples, samplerate=samplerate) 

See https://github.com/bastibe/PySoundFile and https://github.com/bastibe/SoundCard for tons of other super-useful features.

5 Comments

Just a headsup for anyone going for this (as I am). All the libs and their dependencies take forever to build on a Raspberry Pi 1B+ - especially numpy.
PS: this didn't work for raspberry pi "NotImplementedError: SoundCard does not support linux2 yet", and couldn't figure out a way to fix it. I'm going with os.system("mpg123 file.mp3")
Ah, that sucks. I guess raspberry pi is a somewhat special environment. Perhaps if you posted an issue on the issuetracker you could get it sorted out or fixed.
On further thought, perhaps the problem is that you are using an old kernel or old python version. With newer python versions that error should not look like that i think.
It's running Raspbian, which is basically a Debian Stretch fork. I gave up and went the os.system way which is working just fine atm. Thanks for helping me out!
5

This should work on Linux, Mac or Windows:

from preferredsoundplayer import * soundplay("audio.wav") 

Should work for mp3 also.

In Linux it will try up to 4 different methods. In Windows it uses winmm.dll. In Mac it uses afplay.

I wrote it because:

  • I kept having issues with cross-compatibility for playing sounds.
  • It also manually garbage collects calls to the winmm.dll player in Windows and appropriate closes finished sounds.
  • It has no dependencies, other than what comes with Windows 10, the standard Linux kernel, MacOS 10.5 or later, and the Python Standard Library.

You can install using pip install preferredsoundplayer (see project) or just utilize the source code which is a single file (source code) .

Comments

4

It is possible to play audio in OS X without any 3rd party libraries using an analogue of the following code. The raw audio data can be input with wave_wave.writeframes. This code extracts 4 seconds of audio from the input file.

import wave import io from AppKit import NSSound wave_output = io.BytesIO() wave_shell = wave.open(wave_output, mode="wb") file_path = 'SINE.WAV' input_audio = wave.open(file_path) input_audio_frames = input_audio.readframes(input_audio.getnframes()) wave_shell.setnchannels(input_audio.getnchannels()) wave_shell.setsampwidth(input_audio.getsampwidth()) wave_shell.setframerate(input_audio.getframerate()) seconds_multiplier = input_audio.getnchannels() * input_audio.getsampwidth() * input_audio.getframerate() wave_shell.writeframes(input_audio_frames[second_multiplier:second_multiplier*5]) wave_shell.close() wave_output.seek(0) wave_data = wave_output.read() audio_stream = NSSound.alloc() audio_stream.initWithData_(wave_data) audio_stream.play() 

3 Comments

This is far more complicated than necessary - they asked how to simply play a sound, not how to manipulate it and then play it. My answer trims the unnecessary 90% from this answer and leaves exactly what the asker wanted - playing a sound from a file in OS X using Python. stackoverflow.com/a/34984200/901641
Although verbose, I'll disagree with @ArtOfWarfare. This is an amazing answer just for the fact that it shows how to play audio in byte format. This is specially useful when the audio is obtained from a HTTP request, and this happens to be exactly my use case.
@Dan - IIRC, playsound accepts URLs as well as filepaths. That might be undocumented and not supported on all platforms, but I'm pretty certain it works with macOS. I think examples should be as short as possible to actually answer the question - this example is far longer than necessary for what was asked.
3

Also on OSX - from SO, using OSX's afplay command:

import subprocess subprocess.call(["afplay", "path/to/audio/file"]) 

UPDATE: All this does is specify how to do what the OP wanted to avoid doing in the first place. I guess I posted this here because what OP wanted to avoid was the info I was looking for. Whoops.

5 Comments

Works great though does pause execution while it plays. Perhaps there is an async way to call this?
Good questions @Praxiteles. Possibly with threading. see here Please report back if you have a chance to experiment with it.
The OP explicitly asked for alternatives to this.
The OP is/was looking for an alternative to "execute the afplay file.mp3 command from within Python", and subprocessing still happens within Python, doesn't it. I stand corrected. But it probably doesn't hurt to have this little post here as it may help others.
@whitey04 I (finally) see what you're saying.
3

Install playsound package using :

pip install playsound 

Usage:

from playsound import playsound playsound("file location\audio.p3") 

Comments

3

It's Simple. I did it this way.

For a wav file

from IPython.display import Audio from scipy.io.wavfile import read fs, data = read('StarWars60.wav', mmap=True) # fs - sampling frequency data = data.reshape(-1, 1) Audio(data = data[:, 0], rate = fs) 

For mp3 file

import IPython.display import Audio Audio('audio_file_name.mp3') 

1 Comment

Works, but only in Jupyter notebooks, quite limited...
2

Try PySoundCard which uses PortAudio for playback which is available on many platforms. In addition, it recognizes "professional" sound devices with lots of channels.

Here a small example from the Readme:

from pysoundcard import Stream """Loop back five seconds of audio data.""" fs = 44100 blocksize = 16 s = Stream(samplerate=fs, blocksize=blocksize) s.start() for n in range(int(fs*5/blocksize)): s.write(s.read(blocksize)) s.stop() 

1 Comment

Though interesting, link-only answers are discouraged. At the minimum, you should include in your answer a short example of using it. That also protects your answer from losing all its value, should the repository be renamed and the link go dangling.
2

Mac OS I tried a lot of codes but just this works on me

import pygame import time pygame.mixer.init() pygame.init() pygame.mixer.music.load('fire alarm sound.mp3') *On my project folder* i = 0 while i<10: pygame.mixer.music.play(loops=10, start=0.0) time.sleep(10)*to protect from closing* pygame.mixer.music.set_volume(10) i = i + 1 

Comments

2

Try sounddevice

If you don't have the module enter pip install sounddevice in your terminal.

Then in your preferred Python script (I use Juypter), enter

import sounddevice as sd 

sd.play(audio, sr) will play what you want through Python

The best way to get the audio and samplerate you want is with the librosa module. Enter this in terminal if you don't have the librosa module.

pip install librosa audio, sr = librosa.load('wave_file.wav') 

Whatever wav file you want to play, just make sure it's in the same directory as your Python script. This should allow you to play your desired wav file through Python

Cheers, Charlie

P.S.

Once audio is a "librosa" data object, Python sees it as a numpy array. As an experiment, try playing a long (try 20,000 data points) thing of a random numpy array. Python should play it as white noise. The sounddevice module plays numpy arrays and lists as well.

1 Comment

did this, but it's not playing anything. It's just skipping the sd.play call
1

Pypi has a list of modules for python in music. My favorite would be jython because it has more resources and libraries for music. As example of of code to play a single note from the textbook:

# playNote.py # Demonstrates how to play a single note. from music import * # import music library note = Note(C4, HN) # create a middle C half note Play.midi(note) # and play it! 

Comments

1

To play a notification sound using python, call a music player, such as vlc. VLC prompted me to use its commandline version, cvlc, instead.

from subprocess import call call(["cvlc", "--play-and-exit", "myNotificationTone.mp3"]) 

It requires vlc to be preinstalled on the device. Tested on Linux(Ubuntu 16.04 LTS); Running Python 3.5.

Comments

1

In a Colab notebook you can do:

from IPython.display import Audio Audio(waveform, Rate=16000) 

1 Comment

This worked for me: Audio(data=waveform, rate=16000).
1

This library aims to be simple, cross-platform and have many features: https://github.com/libwinmedia/libwinmedia-py

It requires a libwinmedia shared library, which you can download in Releases tab.

You can install it using pip install libwinmedia

Example:

import libwinmedia player = libwinmedia.Player(True) player.set_position_callback(lambda position: print(f"{position} ms.")) media = libwinmedia.Media("test.mp3") player.open(media) 

Comments

0
Put this at the top of your python script you are writing:
import subprocess 
If the wav file IS in the directory of the python script:
f = './mySound.wav' subprocess.Popen(['aplay','-q',f) 
If the wav file IS NOT in the directory of the python script:
f = 'mySound.wav' subprocess.Popen(['aplay','-q', 'wav/' + f) 
If you want to learn more about aplay:
man aplay 

Comments

0

I recently made my Music Player support all audio files locally. I did this by figuring out a way to use the vlc python module and also the VLC dll files. You can check it out: https://github.com/elibroftw/music-caster/blob/master/audio_player.py

Comments

0

For those who use Linux and the other packages haven't worked on MP3 files, audioplayer worked fine for me:

https://pypi.org/project/audioplayer/

from audioplayer import AudioPlayer AudioPlayer("path/to/somemusic.mp3").play(block=True) 

2 Comments

I get ModuleNotFoundError: No module named 'gi'. Again.
Is that <br> really meant to be there in the import statement?
-2

Simply You can do it with the help of cvlc- I did it in this way:

import os os.popen2("cvlc /home/maulo/selfProject/task.mp3 --play-and-exit") 

/home/maulo/selfProject/task.mp3. This is the location of my mp3 file. with the help of "--play-and-exit" you will be able to play again the sound without ending the vlc process.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.