I've tried emptying the queue every time. I've tried self.engine.stop
. It either doesn't affect anything or it will work and successfully interrupt the previous speech one, twice or maybe even thrice but would not consistently perform as intended. It also started logging a very large length from on_word
when it would stop working.
The context for this is a pygame script that reads a text when you click a button.
import pyttsx3
import threading
import queue
class VoiceManager:
def __init__(self):
self.engine = pyttsx3.init()
self.engine.connect("started-utterance", self.on_start)
self.engine.connect("started-word", self.on_word)
self.engine.connect("finished-utterance", self.on_end)
self.task_queue = queue.Queue()
self.thread = threading.Thread(target=self._worker, daemon=True)
self.thread.start()
def _worker(self):
while True:
func, args = self.task_queue.get()
func(*args)
self.task_queue.task_done()
def _run_in_thread(self, func, *args):
self.task_queue.put((func, args))
def on_start(self, name):
print(f"Starting {name}")
def on_word(self, name, location, length):
print(f"Word {name}, {location}, {length}")
def on_end(self, name, completed):
print(f"Finishing {name} {completed}")
def on_error(self, name: str, exception: Exception) -> None:
self.engine.stop()
raise exception
def speed_up(self, value: int = 50):
rate = self.engine.getProperty("rate")
self.engine.setProperty("rate", rate + value)
def slow_down(self, value: int = 50):
rate = self.engine.getProperty("rate")
self.engine.setProperty("rate", rate - value)
def get_all_voices(self):
return self.engine.getProperty("voices")
def save(self, text: str, dir: str):
self.engine.save_to_file(text, dir)
self.engine.runAndWait()
def say(self, text: str):
def run_say(text: str):
self.engine.say(text)
self.engine.runAndWait()
self._run_in_thread(run_say, text)
VoiceUtils = VoiceManager()
I'm referring to the say() function.