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
Buy a Coffee