Gustavo
Gustavo

Reputation: 31

I can't run a simple code using pyaudio - [Errno -9996] Invalid output device (no default output device)

(I'm new at python)

I'm trying to run a simple code about pyaudio. I just copied and pasted a code that I found on the pyaudio web site.

I get this error:

    OSError                                   Traceback (most recent call last)
<ipython-input-7-3fc52ceecbf3> in <module>()
     15                 channels=wf.getnchannels(),
     16                 rate=wf.getframerate(),
---> 17                 output=True)
     18 
     19 # read data

/home/gustavolg/anaconda3/lib/python3.5/site-packages/pyaudio.py in open(self, *args, **kwargs)
    748         """
    749 
--> 750         stream = Stream(self, *args, **kwargs)
    751         self._streams.add(stream)
    752         return stream

/home/gustavolg/anaconda3/lib/python3.5/site-packages/pyaudio.py in __init__(self, PA_manager, rate, channels, format, input, output, input_device_index, output_device_index, frames_per_buffer, start, input_host_api_specific_stream_info, output_host_api_specific_stream_info, stream_callback)
    439 
    440         # calling pa.open returns a stream object
--> 441         self._stream = pa.open(**arguments)
    442 
    443         self._input_latency = self._stream.inputLatency

OSError: [Errno -9996] Invalid output device (no default output device)

I can not figure out how to solve this error. I don't know if this has something to do with audio driver or if the code needs an output declaration. I mean, if I have to select an output.

The code:

import pyaudio
import wave
import sys

CHUNK = 1024


wf = wave.open("/home/gustavolg/anaconda3/aPython/file.wav", 'rb')

# instantiate PyAudio (1)
p = pyaudio.PyAudio()

# open stream (2)
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
                channels=wf.getnchannels(),
                rate=wf.getframerate(),
                output=True)

# read data
data = wf.readframes(CHUNK)

# play stream (3)
while len(data) > 0:
    stream.write(data)
    data = wf.readframes(CHUNK)

# stop stream (4)
stream.stop_stream()
stream.close()

# close PyAudio (5)
p.terminate()

I'm using python3 on Jupyter notebook.

Upvotes: 3

Views: 25415

Answers (2)

Durgan
Durgan

Reputation: 111

This may not be the issue that OP ran into, but I found a cause and fix of the [Errno -996] exception (and I thought I'd share this here since Google results lead here). Attempting to play multiple sounds with pyaudio at the same time can cause such a crash. For example, with something like this:

    def playSound( self, soundName ):

        audioFilePath = self._soundBank.get( soundName )

        if not audioFilePath:
            audioFilePath = os.path.join( globalData.paths['audioFolder'], soundName + ".wav" )
            if not os.path.exists( audioFilePath ):
                print( 'Invalid or missing sound file for', soundName )
                return
            self._soundBank[soundName] = audioFilePath

        # Play the audio clip in a separate thread so that it's non-blocking
        audioThread = Thread( target=self._playSoundHelper, args=(audioFilePath,) )
        audioThread.start()

    def _playSoundHelper( self, soundFilePath ):

        """ Helper (thread-target) function for playSound(). Runs in a separate 
            thread to prevent audio playback from blocking anything else. """

        p = None
        wf = None
        stream = None

        try:
            # Instantiate PyAudio and open the target audio file
            p = pyaudio.PyAudio()
            wf = wave.open( soundFilePath, 'rb' )

            # Open an audio data stream
            stream = p.open( format=p.get_format_from_width(wf.getsampwidth()),
                            channels=wf.getnchannels(),
                            rate=wf.getframerate(),
                            output=True )

            # Continuously read/write data from the file to the stream until there is no data left
            data = wf.readframes( 1024 )
            while len( data ) > 0:
                stream.write( data )
                data = wf.readframes( 1024 )

        except AttributeError:
            pass # Program probably closed while playing audio

        except Exception as err:
            soundFileName = os.path.basename( soundFilePath )
            print( 'Unable to play "{}" sound.'.format(soundFileName) )
            print( err )

        # Stop the stream
        if stream:
            stream.stop_stream()
            stream.close()

        # Close PyAudio
        if p:
            p.terminate()
        
        # Close the wav file
        if wf:
            wf.close()

Above, if playSound() is called too soon after another playSound(), the program will crash. However, this can be resolved by using an Event() object to mediate initialization of pyaudio and the stream so that only one may be initialized at a time, while still allowing the sounds to play back for-the-most-part simultaneously or 'on top' of each other (i.e the work in the data read/write loop portion of the thread). I added this like so:

    def __init( self ):
        self.audioGate = Event()
        self.audioGate.set()

    def _playSoundHelper( self, soundFilePath ):

        """ Helper (thread-target) function for playSound(). Runs in a separate 
            thread to prevent audio playback from blocking anything else. """

        p = None
        wf = None
        stream = None

        try:
            # Prevent race conditions on multiple sounds playing at once (can cause a crash); only allow one file to begin playing at a time
            self.audioGate.wait() # Blocks until the following is done (event is re-set)
            self.audioGate.clear()

            # Instantiate PyAudio and open the target audio file
            p = pyaudio.PyAudio()
            wf = wave.open( soundFilePath, 'rb' )

            # Open an audio data stream
            stream = p.open( format=p.get_format_from_width(wf.getsampwidth()),
                            channels=wf.getnchannels(),
                            rate=wf.getframerate(),
                            output=True )

            self.audioGate.set() # Allow a new sound to be opened/initialized

            # Continuously read/write data from the file to the stream until there is no data left
            data = wf.readframes( 1024 )
            while len( data ) > 0:
                stream.write( data )
                data = wf.readframes( 1024 )

        except AttributeError:
            pass # Program probably closed while playing audio

        except Exception as err:
            soundFileName = os.path.basename( soundFilePath )
            print( 'Unable to play "{}" sound.'.format(soundFileName) )
            print( err )

        # Stop the stream
        if stream:
            stream.stop_stream()
            stream.close()

        # Close PyAudio
        if p:
            p.terminate()
        
        # Close the wav file
        if wf:
            wf.close()

You could similarly use the Event to instead cancel any existing audio playback (by checking in the loop) before starting the latest one.

Upvotes: 1

iliul
iliul

Reputation: 91

check the following steps:

>>> import pyaudio
>>> pa = pyaudio.PyAudio()
>>> pa.get_default_input_device_info()
{'defaultLowOutputLatency': 0.008707482993197279, 
 'maxOutputChannels': 32, 
 'hostApi': 0, 
 'defaultSampleRate': 44100.0, 
 'defaultHighOutputLatency': 0.034829931972789115, 
 'name': 'default', 
 'index': 15, 
 'maxInputChannels': 32,
 'defaultHighInputLatency': 0.034829931972789115, 
 'defaultLowInputLatency': 0.008707482993197279, 
 'structVersion': 2}
>>> pyaudio.pa.__file__
'/root/.virtualenvs/py3k/lib/python3.4/site-packages/_portaudio.cpython-34m.so'

make sure you have a default input device,if not you can refer to here

I want it's useful for you!

Upvotes: 7

Related Questions