Search on blog:

Python: How to play mp3 from gTTS as bytes without saving on disk

Google-Text-To-Speech (shortly gtts) converts text to speech in file MP3 and popular method to play it without saving on disk was to use PyGame

from gtts import gTTS
from io import BytesIO

text = "Hello World!"

# get audio from server
tts = gTTS(text=text, lang=lang)

# convert to file-like object
fp = BytesIO()
tts.write_to_fp(fp)
fp.seek(0)

# --- play it ---

import pygame

print('fp')

pygame.init()
pygame.mixer.init()
pygame.mixer.music.load(fp)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
    pygame.time.Clock().tick(10)

But lastly when I tried it on Linux and I got error

Module format not recognized

so I think gtts could changed MP3 format (maybe it has better quality) and now PyGame has problem to play it.

In PyGame doc you can even see

"Be aware that MP3 support is limited.
 On some systems an unsupported format can crash the program, e.g. Debian Linux."

And command file output.mp3 display

I tested few other modules to play it without saving on disk. I also try to find solution which don't use subprocess to execute external player. but I didn't check if they do save it on disk somewhere deep in code.

And at this moment work for me only pydub, mpg123.

pydub - which uses ffmpeg or libav and simpleaudio, pyaudio

(pip install pydub)

from gtts import gTTS
from io import BytesIO

text = "Hello World!"

# get audio from server
tts = gTTS(text=text, lang=lang)

# convert to file-like object
fp = BytesIO()
tts.write_to_fp(fp)
fp.seek(0)

# --- play it ---

from pydub import AudioSegment
from pydub.playback import play

song = AudioSegment.from_file(fp, format="mp3")
play(song)

mpg123 - which uses libmpg123 and libout123 (probably pygame also use it)

(pip install mpg123)

from gtts import gTTS
from io import BytesIO

text = "Hello World!"

# get audio from server
tts = gTTS(text=text, lang=lang)

# convert to file-like object
fp = BytesIO()
tts.write_to_fp(fp)
fp.seek(0)

# --- play it ---


from mpg123 import Mpg123, Out123

mp3 = Mpg123()
mp3.feed(fp.read())

out = Out123()

for frame in mp3.iter_frames(out.start):
    out.play(frame)

pydub uses powerful ffmpeg but I found it run it in subprocess and I like more mpg123

Maybe if to change code in gtts it could read it even without BytesIO because gtts uses requests which can give direct acces to file data.

---

And here other codes which I was testing

playsound - it needs to save on disk

from playsound import playsound

playsound('output.mp3')

audioread - it needs to save on disk and it doesn't play

import audioread

f = audioread.audio_open('output.mp3')

simpleaudio - doesn't work with mp3

import simpleaudio as sa

wave_obj = sa.WaveObject.from_wave_file(fp)

soundfile - doesn't work with mp3

import sounddevice as sd
import soundfile as sf

data, fs = sf.read('output.mp3')#, dtype='float32')

sd.play(fp, fs)
status = sd.wait()  # Wait until file is done playing

If you like it
Buy a Coffee