Search code examples
audiopython-3.6text-to-speech

Playing audio directly from a python program (text to speech)


I am trying to figure out how to play audio from a python program without needing to have the audio saved to my computer. The sound is created in the python program and just needs to be played and stopped immediately after.

I have already tried to use pygame, playsound, subprocess, gTTS and various others, but with no success.

gTTS "works" but only saves the audio and does not play it

Also I am using python 3 (I updated on 6/18/18)

PyAudio attempt did not work for me. But here is my code:

import subprocess 
from gtts import gTTS 
if choose in card.keys(): 
  tts = gTTS(text = choose, lang = 'en') 
  tts.save(audio_eng) 
  checker(guess, choose, card, pract_one, good_count, bad_count, pract_two) 
  return_code = subprocess.call(["afplay", audio_eng])#, shell= True) 

Solution

  • I think the main library used for this kind of thing is PyAudio. It's built ontop of portaudio (a C library), which I have used many times.

    If you have generated the audio in Python, then you can simply pass it to the output similar to the example on the PyAudio documentation (Blocking mode Audio I/O). This will stop other processes happening until the audio file has finished playing.

    """PyAudio Example: Play a wave file."""
    
    import pyaudio
    import wave
    import sys
    
    CHUNK = 1024
    
    
    # wf = wave.open(sys.argv[1], 'rb') # Original example
    wf = your_audio_data_array
    
    # instantiate PyAudio (1)
    p = pyaudio.PyAudio()
    
    # open stream (2)
    stream = p.open(format=p.get_format_from_width(your_audio_data_samplewidth),
                    channels=your_audio_data_nChannels,
                    rate=your_audio_data_framerate,
                    output=True)
    
    # read data
    data = wf # your_audio_data_array
    
    # play stream (3)
    while len(data) > 0:
        stream.write(data)
        # data = wf.readframes(CHUNK) # read more data if you want to stream another buffer
    
    # stop stream (4)
    stream.stop_stream()
    stream.close()
    
    # close PyAudio (5)
    p.terminate()
    

    I have modified this example to how you explained your problem was; so you just pass PyAudio the audio data buffer (which you said you already generated in Python).

    To have multiple processes happening at once, see the PyAudio Callback Mode I/O in their documentation.