How to output voice non-blocking without having to wait for runAndWait()
See original GitHub issuepyttsx3 Version: 2.71 macOS: 10.14.6
I am writing a voice assistant that has to output voice and then immediately has to listen to the user. The assistant is based on Spade which uses Asyncio.
When I output voice using say("sth") and runAndWait() there is quite a long time that I have to wait for runAndWait() to finish (about 1100ms). I would like to be able to output speech and immediately when the output is finished continue to do other things, like listening to what the user says.
When I use startLoop() I can’t continue with anything until I called endLoop() which also delays everything.
I don’t really understand how startLoop(False) would help me.
Executing engine.iterate() myself works, and I receive speech output, but there too I don’t know how to continue with other operations after speech output finished
How would I setup pyttsx3 in a way where I can output speech at anytime without a delay afterwards?
I tried to place endLoop() in a separate deamon thread so I don’t need to wait for it to finish.
But in this case say() never returns.
Thank you for your help! Here is my code:
output.py
import pyttsx3
from ava.utterance import Utterance
from log import log_output as log
import threading
class Output:
def __init__(self):
self.synthesizer = pyttsx3.init(debug=True)
self.voice = list(filter(lambda sv: ('Tracy' in sv.name),
self.synthesizer.getProperty('voices')))[0]
self.synthesizer.setProperty('voice', self.voice.id)
self.synthesizer.setProperty('rate', 175)
self.setup_callbacks()
def setup_callbacks(self):
self.synthesizer.connect('finished-utterance', self.on_finished_utterance)
self.synthesizer.connect('started-word', self.on_started_word)
def speak(self, utterance: Utterance):
self.synthesizer.say(utterance.body, utterance.name)
self.synthesizer.startLoop()
def on_finished_utterance(self, name, completed):
log.debug("END")
t = threading.Thread(name="ccpyttsx3", target=self.killme, args=(self.synthesizer,))
t.setDaemon(True)
t.start()
def on_started_word(self, name, location, length):
pass
def killme(self, synth):
print("killme")
synth.endLoop()
Issue Analytics
- State:
- Created 4 years ago
- Comments:6
Top Related StackOverflow Question
Hi @raffals you can check this out: https://github.com/ccarstens/Ava/blob/dev/ava/environment.py https://github.com/ccarstens/Ava/blob/dev/ava/iocontroller.py
In environment the process is set up and in iocontroller the strings that should be synthesised using pyttsx are received via the Queue
Sir i am facing a delay reply from my assistant. could you please give me a suggestion for fast reply.
import pyttsx3 import speech_recognition as sr import pyaudio import pywhatkit import datetime import wikipedia
listener=sr.Recognizer() engine=pyttsx3.init() engine.say(“Hello I am siri”) engine.runAndWait() voices=engine.getProperty(‘voices’) engine.setProperty(‘voice’,voices[1].id) volume = engine.getProperty(‘volume’) engine.setProperty(‘volume’, 10.0) rate = engine.getProperty(‘rate’) engine.setProperty(‘rate’, rate + 25) def talk(command): engine.say(command) engine.runAndWait() def taking_cmd(): command=“” try: with sr.Microphone() as source: print(‘Listening…’) voice=listener.listen(source) command=listener.recognize_google(voice) command=command.lower() print(“ok”)
def run(): command=taking_cmd() if ‘play’ in command: command=command.replace(“play”,“”) talk(“playing” + command) pywhatkit.playonyt(command) elif ‘time’ in command: time=datetime.datetime.now().strftime(‘%I:%M %p’) talk(“Now the time is”+time) elif 'who the heck ’ in command: wiki=command.replace(‘who the heck is’,“”) info = wikipedia.summary(wiki,1) print(info) talk(info) else: talk(“sorry i cant understand please repeat it again”)
run()