1

I'm trying to make a simple Python script which should take a text as input and using gtts, play it as audio. I'm using the following code, but it's not working and I don't know why.

from gtts import gTTS
import pygame
from io import BytesIO

pygame.init()


def say(text):
    tts = gTTS(text=text, lang='en')
    fp = BytesIO()
    tts.write_to_fp(fp)
    fp.seek(0)
    pygame.mixer.init()
    pygame.mixer.music.load(fp)
    pygame.mixer.music.play()
    while pygame.mixer.music.get_busy():
        pygame.time.Clock().tick(10)

say("hello")

Python version 3.9.1
gTTS version 2.2.1
pygame version 2.0.1 Windows 10

EDIT: This is the complete error I get:

pygame 2.0.1 (SDL 2.0.14, Python 3.9.1)
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "c:\Users\Marco\Documents\Programmazione\gtts\main2.py", line 19, in <module>
    say("hello")
  File "c:\Users\Marco\Documents\Programmazione\gtts\main2.py", line 14, in say     
    pygame.mixer.music.load(fp)
pygame.error: ModPlug_Load failed
mlazzarotto91
  • 103
  • 3
  • 13
  • are you getting an error, or is it just not working as exepected? – griffin_cosgrove Jan 07 '21 at 14:35
  • always put full error message (starting at word "Traceback") in question (not comment) as text (no screnshot).There are other useful informatin. – furas Jan 07 '21 at 14:43
  • as I remember `gtts` sends `mp3` but in PyGame you can see `Be aware that MP3 support is limited. On some systems an unsupported format can crash the program, e.g. Debian Linux. Consider using OGG instead.` – furas Jan 07 '21 at 14:45
  • Added the full error message @furas – mlazzarotto91 Jan 07 '21 at 14:46
  • did you check `pygame.error: ModPlug_Load failed` in Google ? Maybe someone already had this problem. – furas Jan 07 '21 at 14:46
  • @furas yes I did before asking here – mlazzarotto91 Jan 07 '21 at 14:47
  • I tested code on Linux and I get error `Unrecognized audio format`. When I save in file and check format then it shows me `MPEG ADTS, layer III, v2, 32 kbps, 24 kHz, Monaural`. If I used `ffmpeg` to convert (manually) to `.wav` and `.ogg` then both work with `pygame`. – furas Jan 07 '21 at 15:01
  • on Linux I can play `mp3` from `gtts` using [playsound](https://pypi.org/project/playsound/) but I have to save on disk – furas Jan 07 '21 at 15:11
  • @furas I was looking for a way to play without saving to disk. – mlazzarotto91 Jan 07 '21 at 15:33
  • at this moment the only what works for me is `pydub` https://stackoverflow.com/a/43950755/1832058. – furas Jan 07 '21 at 15:37

1 Answers1

0

I tried this code on Linux and I get error

Module format not recognized

so I think gtts (Google Text-To-Speech) could change 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."

I tested few other modules and at this moment work for me only pydub, mpg123.

I try to use modules which don't have to save in file (I don't check if they do save it on disk somewhere deeper in code) and don't use subprocess to run external player.


pydub - which uses ffmpeg or libav and simpleaudio, pyaudio (pip install pydub)

from gtts import gTTS
from io import BytesIO

tts = gTTS(text="Hello", lang='en')
fp = BytesIO()
tts.write_to_fp(fp)
fp.seek(0)

# --- 

from pydub import AudioSegment
from pydub.playback import play

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

mpg123 - which uses libmpg123 (probably pygame also use it) (pip install mpg123)

from gtts import gTTS
from io import BytesIO

tts = gTTS(text="Hello", lang='en')
fp = BytesIO()
tts.write_to_fp(fp)
fp.seek(0)

# --- 

from mpg123 import Mpg123, Out123

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

out = Out123()

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

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.

furas
  • 134,197
  • 12
  • 106
  • 148