Python 使用线程时不触发Pyttsx3回调
我使用线程作为绕过pyttsx3的“运行并等待”默认功能的一种方式,这样我就可以在演讲中打断别人说的话。但是,这会阻止库的回调,因此我无法检测一块文本何时被说出-我必须使用秒数来猜测它 我希望检测的回调是finished outrance,它与Python 使用线程时不触发Pyttsx3回调,python,python-3.x,text-to-speech,Python,Python 3.x,Text To Speech,我使用线程作为绕过pyttsx3的“运行并等待”默认功能的一种方式,这样我就可以在演讲中打断别人说的话。但是,这会阻止库的回调,因此我无法检测一块文本何时被说出-我必须使用秒数来猜测它 我希望检测的回调是finished outrance,它与self.engine.connect('finished-outrance',self.onEnd)连接。这遵循中给出的示例。当我在真实的程序中使用它时,一个文本块可以有数百个单词长,而下一个文本块只能有几个单词长。我想知道什么时候说一句话,这样程序就可
self.engine.connect('finished-outrance',self.onEnd)
连接。这遵循中给出的示例。当我在真实的程序中使用它时,一个文本块可以有数百个单词长,而下一个文本块只能有几个单词长。我想知道什么时候说一句话,这样程序就可以自动进入下一个“说”功能
我读过使用多重处理的文章,但我不知道如何做到这一点。有没有办法让回调使用线程?我正在使用Windows10
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)
从线程导入事件,线程
导入pyttsx3
类声音(对象):
定义初始化(自我、跳过、播放提示音):
self.t=None
self.\u running=False
self.engine=pyttsx3.init()
self.skip=跳过
self.engine.connect('finished-speutation',self.onEnd)
def onEnd(自我、姓名、已完成):
打印('完成:',名称,已完成)
self.stop()
已完成话语的定义(自我、姓名、已完成):
打印('结束')
t=Thread(target=self.killme,args=(self.engine),daemon=True)
t、 开始()
def过程_语音(自我、文本):
self.engine.say(str(text))
self.engine.startOOP(错误)
当self.\u运行时:
self.engine.iterate()
def say(self,text,length=2):
#检查线程是否正在运行
如果self.t和self.\u正在运行:
#如果是的话就停下来
self.stop()
#在线程中迭代语音
self.t=Thread(target=self.process\u speech,args=(text,),daemon=True)
self.\u running=True
self.t.start()
已用秒数=0
轮询间隔=.1
而不是self.skip.is_set()和经过的_秒<长度:
self.skip.wait(轮询间隔)
已用秒数+=轮询间隔
def停止(自):
self.\u running=False
尝试:
self.engine.endLoop()
除:
通过
尝试:
self.t.join()
例外情况除外,如e:
通过
跳过=事件()
myVoice=语音(跳过,0)
我的声音。说(“测试”,2)
我的声音。说(“测试二”,2)
问题:根据事件触发/结束多个say()
此实现基于
注意:该TTSThread
从实例化开始,一直运行您必须在
EXIT\uuuu main\uuuu
处调用.terminate()
,以防止等待强>
用法1:一次传递多个句子,并自动运行
引擎。对所有句子说(…)
用法2:一句接一句地说,取决于事件“完成的话语”
输出:
.say add[1.0]: "Use your h..."
finishing[18.0], delay next sentence 1.5 sec.
__main__ 20.0
.say add[34.0]: "Time will ..."
__main__ 40.0
finishing[51.0], delay next sentence 1.5 sec.
__main__ 60.0
.say add[67.0]: "Strike whi..."
__main__ 80.0
finishing
__main__ 100.0
EXIT __main__
使用Python:3.5测试-pyttsx3版本:2.71“阻止回调…因此我无法检测文本块何时完成”:我有一个运行的可中断线程版本,但我不清楚您缺少哪个
回调以及您希望如何使用它。你的问题并展示出来。回叫是“完成的话语”。当我在真实的程序中使用它时,一个文本块可以有数百个单词长,而下一个文本块只能有几个单词长。我想知道什么时候说一句话,这样程序就可以自动进入下一个“说”功能。我编辑了这个问题。“自动前进到下一个”说“文本块”:所以你不想“打断正在说的话”,而是想要连续的说(…
一个文本块列表?还没有测试过这个场景,但这只需要一个简单的FIFO
。我已经有了处理跳过事件的中断()我希望根据引擎启动/结束多个say()。say()被检测为完成。当我复制/粘贴它们时,你的两个用法对我来说根本不起作用。第一个只说say use your head to save your foots.的第一句话。第二个说同样的话,并打印出。说添加[1.0]:“使用你的h…”
then main 20/40/60/80/100。我是在新安装的python版本3.5和相同的pyttsx3版本(通过pycharms下载)下完成的pip@bvs:我在Linux上运行,无法使用Windows 10
进行测试。您简单描述了您的问题以及未获得事件'finished-outrance'
的问题。包括用法1和美国您的GitHub问题
尚未得到解答。我认为这是一个解决方案。此外,我尝试实现proposal@bvs:更新我的答案,执行来自GitHub
的建议,并将整个引擎
部分移动到同一线程
中,以防止跨线程事件。如果成功,请尝试第二个实施方案现在生效,但不是第一个。我会奖励你,而我考虑接受。answer@bvs太好了!在用法1中,我忘记了让\uuu main\uuu
保持活动状态并调用语音。terminate()
在EXIT\uuuu main\uuuu
处。请记住,TTSThread
将永远运行。更新了我的答案。
from TTS import TTSThread
SAY = ["Use your head to save your feet.", "Time will tell.", "Strike while the iron is hot."]
class Voice(TTSThread):
def __init__(self):
super().__init__(rate=115)
if __name__ == "__main__":
voice = Voice()
voice.say(SAY)
# Simulate __main__.is_alive
count = 0.0
while True:
time.sleep(0.1)
count += 1
if count >= 100:
voice.terminate()
break
print('EXIT __main__'.format())
from TTS import TTSThread
import time
class Voice(TTSThread):
def __init__(self):
self.completed = None
super().__init__(rate=115, event='completed')
def on_finished_utterance(self, name, completed):
"""
Overloads `TTSThread.on_finished_utterance`
which is connected to event 'finished-utterance'
"""
if len(SAY):
print('finishing[{}], delay next sentence {} sec.'.format(count, 1.5))
time.sleep(1.5)
self.completed.set()
else:
print('finishing')
if __name__ == "__main__":
voice = Voice()
# Start simulation, `say(...)` while __main__ is running
voice.completed.set()
_terminate = 100
count = 0.0
while True:
time.sleep(0.1)
count += 1
if voice.completed.is_set():
voice.completed.clear()
if len(SAY):
print('.say add[{}]: "{}..."'.format(count, SAY[0][:10]))
voice.say(SAY.pop(0))
if count % 20 == 0:
print('__main__ {}'.format(count))
if count >= _terminate:
voice.terminate()
print('EXIT __main__'.format())
.say add[1.0]: "Use your h..."
finishing[18.0], delay next sentence 1.5 sec.
__main__ 20.0
.say add[34.0]: "Time will ..."
__main__ 40.0
finishing[51.0], delay next sentence 1.5 sec.
__main__ 60.0
.say add[67.0]: "Strike whi..."
__main__ 80.0
finishing
__main__ 100.0
EXIT __main__