How to output voice non-blocking without having to wait for runAndWait()

See original GitHub issue

pyttsx3 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:closed
  • Created 4 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
ccarstenscommented, Apr 13, 2020

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

0reactions
AlluDaddycommented, Jan 11, 2021

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”)

        if "siri" in command:
            
            command=command.replace("siri","")
            print(command)
            talk(command)
except:
    pass

return command

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()

Read more comments on GitHub >

github_iconTop Results From Across the Web

Pyttsx "run" but without "wait" - python - Stack Overflow
Pyttsx does not have method like runAndNoWait(), but you can run your say(text) function as separate thread to stop blocking your main game ......
Read more >
Using pyttsx3 — pyttsx3 2.6 documentation - Read the Docs
An application invokes the pyttsx3.init() factory function to get a reference to a ... completed – True if the utterance was output in...
Read more >
Stop Waiting! Start using Async and Await! | by Simon Hawe
In this article, I want to show you how to significantly reduce waiting time for IO-bound problems using the Asynchronous IO, short AsyncIO, ......
Read more >
Python Virtual Assistant(No AI) - Medium
Hello Readers! In this article we will discuss about how to build your virtual assistant in python without learning Artificial Intelligence.
Read more >
Programming Robots with ROS
Perhaps we want to simultaneously log and print both of those streams? Again, this can be accomplished without modifying any source code; ROS...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found