-
Notifications
You must be signed in to change notification settings - Fork 346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
can't get pyttsx3 to stop talking mid utterance more than one time #35
Comments
This is something I would like to do as well, but I've not put significant effort into making it work. Near as I can tell, it's a feature that's not actually in pyttsx3. So, you would actually have to modify pyttsx3 to make it work. A possible workaround would be to kill the thread somehow and then create a new one every time you have it speak something. Though, I guess that's what you're trying to do. |
I think it starts it's own thread because my thread only set it up and runs it. I wonder if I kill my thread from the main one if it will take the pyttsx one with it? |
Theoretically, it should. Though, when I was looking into killing threads, I kept seeing how it wasn't a good thing to do. So, I've not gotten back to it, yet. |
Looking at it more, there is a "connect" function, so perhaps this kind of functionality is implemented, but not with the basic say command. |
You can look at the engine.py file yourself for some detailed notes. |
Wonder if endLoop would work |
Have you looked at the examples here? |
Thanks for the help, |
Cool, hopefully you get it to do what you want. I would like to see what example you went with or how you implemented it, if you're willing to share. |
Of course when I have it done it will be on my github https://github.com/lerker100/Steve |
Looking at the code examples more, it should be a simple matter of using engine.connect and linking it to a function that stops the engine, if it meets a certain criteria. Example: (This example triggers onWord, every word it speaks. So, you should be able to interrupt the speech at the end / beginning? of each word spoken.)
|
I was having the same issues, trying to thread the engines loop has been tricky. It seems that if you try to use the Here is how I worked around it: import pyttsx3
import logging
from time import sleep
from multiprocessing.dummy import Process as Thread
#from threading import Thread
logger = logging.getLogger(__name__)
class VoiceBox(object):
def __init__(self):
self.t = None
self._running = False
self.engine = None
def _processSpeech(self, text):
self.engine = pyttsx3.init()
self.engine.say(str(text))
self.engine.startLoop(False)
while self._running:
self.engine.iterate()
logger.debug('Thread loop stopped')
def say(self, text, noInter=2):
# check if thread is running
if self.t and self._running:
logger.debug('Interupting...')
# stop it if it is
self.stop()
# iterate speech in a thread
logger.debug('Talking: %s', text)
self.t = Thread(target=self._processSpeech, args=(text,))
self._running = True
self.t.daemon = True
self.t.start()
# give the thread some space
# without this sleep and repeatitive calls to 'say'
# the engine may not close properly and errors will start showing up
sleep(noInter)
def stop(self):
self._running = False
try:
self.engine.endLoop()
logger.debug('Voice loop stopped')
except:
pass
try:
self.t.join()
logger.debug('Joined Voice thread')
except Exception as e:
logger.exception(e)
if __name__ == '__main__':
logging.basicConfig()
logger.setLevel(logging.DEBUG)
text = '''
Hobsbawm joined the Communist Party in 1936 and stayed in it for about fifty years. Not only did the cause to which he had devoted his life expire in infamy but the rubbish that it had promised to sweep from the stage-ethnic and national chauvinism-would, in time, make a new bid for legitimacy.
'''
text2 = '''
pepe hands
'''
v = VoiceBox()
v.say(text, 5)
v.say(text2)
# I would like to have v.say() know when it is finished talking
# kill the voice engine and join the talking thread.
#v.stop() I put the engine's |
The onWord() callback doesn't work, at least not in python 3.8.5. It doesn't trigger for every word, it triggers once when utterance is finished. |
I am having the same issue too. When I
|
I think there is something funky with the way it sets itself busy here and checks whether it's busy. |
This isn’t going to be particularly easy - note like others state the word event stuff is one way - although look at https://github.com/willwade/tts-wrapper where we have callbacks for play and resume etc. (Although ha! I need to fix that right now. It’s a matter of urgency though so should be fixed in the next couple of weeks) |
I can get it to stop the first time with this error
AttributeError: 'Engine' object has no attribute '_pump'
if I comment this out
pyttsx3.driver.DriverProxy.setBusy(engine, busy=False)
it works but then when I try to do it again it doesn't work I've looked through all the docs I can find but nothing fixed it any thoughts or suggestions would be appreciated.
This is the code it's a smaller part of a bigger project so there's a lot of extra code.
The text was updated successfully, but these errors were encountered: