我使用线程作为绕过 pyttsx3 的“运行和等待”默认功能的一种方式,这样我就可以在讲话中打断正在说的话。但是,这会阻止库的回调,因此我无法检测到一段文本何时完成 - 我必须使用长度(以秒为单位)来猜测它。
我希望检测的回调是finished-utterance,它与self.engine.connect('finished-utterance', self.onEnd)
. 这遵循文档中给出的示例。当我在实际程序中使用它时,一个文本块可能有数百个单词长,而下一个文本块可能只有几个单词长。我想知道一个人什么时候说完,这样程序就可以自动前进到下一个“说”功能。
我读过有人通过使用多处理成功解决了这个问题,但我不知道该怎么做。有没有办法让回调与线程一起工作?我正在使用 Windows 10
from threading import Event, Thread
import pyttsx3
class Voice(object):
def __init__(self, skip, play_beep):
self.t = None
self._running = False
self.engine = pyttsx3.init()
self.skip = skip
self.engine.connect('finished-utterance', self.onEnd)
def onEnd(self, name, completed):
print('finishing : ', name, completed)
self.stop()
def on_finished_utterance(self, name, completed):
print('END')
t = Thread(target=self.killme, args=(self.engine), daemon=True)
t.start()
def process_speech(self, text):
self.engine.say(str(text))
self.engine.startLoop(False)
while self._running:
self.engine.iterate()
def say(self, text, length=2):
# check if thread is running
if self.t and self._running:
# stop it if it is
self.stop()
# iterate speech in a thread
self.t = Thread(target=self.process_speech, args=(text,), daemon=True)
self._running = True
self.t.start()
elapsed_seconds = 0
poll_interval = .1
while not self.skip.is_set() and elapsed_seconds < length:
self.skip.wait(poll_interval)
elapsed_seconds += poll_interval
def stop(self):
self._running = False
try:
self.engine.endLoop()
except:
pass
try:
self.t.join()
except Exception as e:
pass
skip = Event()
myVoice = Voice(skip, 0)
myVoice.say("test", 2)
myVoice.say("test two", 2)