I am working on a piece of code where the functionality of runAndWait is required multiple times (a spelling game where the user has to input spellings being read aloud)
Consider the following code snippet (not from the actual code, but similar enough to what I want):
import pyttsx3
engine = pyttsx3.init()
engine.say("Hello World")
engine.runAndWait()
engine.stop()
engine.say("Hi")
engine.runAndWait()
engine.stop()
When run, I would expect it to say both "Hello World", then "Hi", however it only says "Hello World" when ran.
Why is this the case?
Are there any workarounds?
EDIT #1: Some commenters are asking for hardware/software info, so I will provide it here:
HP Laptop running Windows 11 23H2 (Build 22631.5768), 4GB of RAM, Intel Core i3-1005G1 with base speed at 1.2GHz (according to taskmgr) and Integrated Graphics (I don't know the speaker/sound hardware).
Latest version of pyttsx3 from pip (I attempted to install pyaudio as a fix but it didn't help), so I am using the default engine (on Windows) with pyttsx3.
Sorry for not clarifying what I'm using before.
I am not exactly sure what is happening here, but it is a problem with the engine when saying the second word.
import pyttsx3
engine = pyttsx3.init()
engine.say("Hello World")
engine.runAndWait()
print("HELLO CALLED")
engine.stop()
engine.say("Hi")
engine.runAndWait()
print("HI CALLED")
engine.stop()
prints both "HI CALLED" and "HELLO CALLED", meaning there is something wrong with the engine.
My guess is that for some reason the engine is not adding "Hi" to the queue.
There are two workarounds:
One is to create a fresh engine every time you say something.
import pyttsx3
def say(text):
engine = pyttsx3.init()
engine.say(text)
engine.runAndWait()
del engine
say("Hello World")
print("SAYING HELLO WORLD")
say("Hi")
print("SAYING HI")
This means that we have to instantly trigger runAndWait, unless you are fine with something like this:
import pyttsx3
engine = ""
def say(text):
global engine
del engine
engine = pyttsx3.init()
engine.say(text)
return engine
engine = say("Hello World") # Have to assign engine every time you wanna say something
engine.runAndWait()
print("SAYING HELLO WORLD")
engine = say("Hi")
engine.runAndWait()
print("SAYING HI")
A limitation with this is that you cannot have multiple phrases in your queue since the engine is getting refreshed every time. Unless you are fine with this:
def say(text, refresh=True):
global engine
if refresh:
del engine
engine = pyttsx3.init()
engine.say(text)
return engine
engine.say(text)
return engine
and,
engine = say("Hello World")
engine.runAndWait()
print("SAYING HELLO WORLD")
engine = say("Hi")
engine.runAndWait()
print("SAYING HI")
engine = say("Hi")
engine = say("Hello", refresh=False) # Dont refresh engine since
engine.runAndWait()
Another workaround is to not use runAndWait() between saying the two phrases:
import pyttsx3
engine = pyttsx3.init()
engine.say("Hello World")
engine.say("Hi")
engine.runAndWait()
engine.stop()
Summary:
Workaround #1 is the most flexible while workaround #2 is the easiest to implement.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With