2

(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.

Gustavo
  • 21
  • 1
  • 1
  • 3

2 Answers2

5

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!

Gabriel Ziegler
  • 361
  • 3
  • 18
iliul
  • 71
  • 6
  • The environment on my computer is Python=3.4,PyAudio=0.2.9,demo works well. – iliul May 06 '16 at 04:12
  • When I ran the line pa.get_default_input_device_info() I got an error: **/home/gustavolg/anaconda3/lib/python3.5/site-packages/pyaudio.py in get_default_input_device_info(self) 947 """ 948 --> 949 device_index = pa.get_default_input_device() 950 return self.get_device_info_by_index(device_index) 951 OSError: No Default Input Device Available** - seems I don't have Input Device – Gustavo May 06 '16 at 04:31
  • How do I add an Input device? I already have the packages **python-pyaudio** and **python3-pyaudio** installed. – Gustavo May 06 '16 at 04:49
  • 1
    try to install **PortAudio** a free, cross-platform, open-source, audio I/O library. download from [here](http://www.portaudio.com/archives/pa_stable_v19_20140130.tgz),perhaps it's useful. – iliul May 06 '16 at 06:03
0

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.

Durgan
  • 71
  • 5