Создайте вспомогательный класс, который запускает pyttsx
в отдельном потоке:
import threading
import pyttsx
class Say(object):
"""Function-like class to speak using pyttsx."""
_thread = None
def __init__(self, message):
if not isinstance(message, str):
raise ValueError("message is not a string")
if Say._thread is not None:
Say._thread.join()
Say._thread = None
Say._thread = threading.Thread(target=self._worker,
name="Say",
args=(message,))
Say._thread.start()
def _worker(self, message):
engine = pyttsx.init()
engine.say(message)
engine.runAndWait()
def WaitAllSaid():
if Say._thread is not None:
Say._thread.join()
Say._thread = None
Поскольку pyttsx ведет себя как singleton , и только один экземпляр pyttsx может говорить в одном и том же процессе Python в любое время, я инкапсулировал глобальные переменные в класс Say
и получил конструктор экземпляра дождитесь завершения любых существующих высказываний, а затем начните новый поток, чтобы выступил pyttsx.
По сути, Say(message)
ожидает завершения любых произнесенных высказываний, затем начинает говорить новый голос и возвращается. Он не ждет, пока сообщение будет полностью произнесено, прежде чем оно вернется; оно возвращается сразу после начала сообщения.
WaitAllSaid()
ожидает выполнения любых высказываний, а затем собирает рабочий поток. Если вы хотите изменить движок pyttsx или свойства голосовой связи, сначала наберите WaitAllSaid()
, чтобы убедиться, что в это время никакие высказывания не выполняются. В противном случае бедный pyttsx может запутаться.
Последние четыре строки функции OP wikipediaSearch
теперь становятся чем-то вроде
print(new_text)
Say(new_text)
Mbox(user_input, new_text, 0)
WaitAllSaid()
Если pyttsx уже говорит, то Say()
блокируется до тех пор, пока не будут сказаны все предыдущие сообщения. Он сразу возвращается, когда указанное сообщение начинает воспроизводиться.
WaitAllSaid()
просто блокирует до тех пор, пока все сказанное не будет произнесено. Вы можете опустить его из функции wikipediaSearch()
, если убедитесь, что WaitAllSaid()
вызывается до выхода из программы Python.
В не совсем традиционном дизайне: по крайней мере, в Linux у pyttsx есть проблемы, если кто-то пытается использовать один и тот же объект pyttsx для отдельных операторов. Наличие вспомогательного потока для создания экземпляра работает намного лучше. При тестировании на Linux этот шаблон был наиболее устойчивым среди глобальных переменных и различных форм одноэлементных классов. Я вообще не пользуюсь Windows, поэтому не могу на ней протестировать, увы.