def listen_for_keyword() -> bool: """ Loops until the keyword is recognized from the user input (from `recognize_keyword`). Steps: 1. Enters the loop (keyword detection) 2. Creates a new thread (using `recognize_keyword` as target) 3. If the keywork is detected, break the loop and play the activation sound Returns: bool: Whether the keyword is recognizes or not. If not, continue the loop. """ global keyword_detected global new_process log.debug("Keyword loop...") keyword_detected = False new_process = True log.info("Waiting for '{0}'...".format(settings.KEYWORD)) while True: if keyword_detected: break if new_process: new_process = False threading.Thread(target=recognize_keyword).start() tts.play_mp3(settings.ACTIVATION_SOUND_PATH) return True
def listen_for_binary() -> bool: """ Checks if a binary/boolean value (Yes/No) is present in the transcribed audio. Used in Yes/No questions (e.g. *"Do you want X?"*) Steps: 1. Listens for audio from the microphone 2. Recognizes the audio using `gTTS` 3. Checks if a boolean value (Yes, No, True, False) is present in the audio data Returns: bool: Wheter a boolean value is present in the audio data """ yes_reply = replying.get_reply(["stt", "yn_y"], system=True, module=True) no_reply = replying.get_reply(["stt", "yn_n"], system=True, module=True) log.info("Waiting for {0} or {1}".format(yes_reply, no_reply)) while True: audio = listen() rec_input = recognize(audio) if rec_input: if yes_reply in rec_input.lower(): log.debug("'{0}' detected".format(yes_reply)) return True elif no_reply in rec_input.lower(): log.debug("'{0}' detected".format(no_reply)) return False else: log.debug("Not detected binary answer in {0}".format(rec_input))
def setup() -> None: """ Initialize the TTS engine Steps: 1. Checks the platform (operating system) 2. Sets the engine to one supported (SAPI or gTTS) """ global engine # detect OS if platform.system() == "Windows" and settings.TTS_AUTODETECT: try: import win32com.client as win32com engine = win32com.Dispatch("SAPI.SpVoice") log.debug("Using SAPI") except ModuleNotFoundError: log.error("Couldn't find module named 'win32com.client'") log.error( "Check installation or install via 'pip install pypiwin32'") else: try: from gtts import gTTS engine = gTTS log.debug("Using gTTS") except ModuleNotFoundError: log.error("Couldn't find module named 'gTTS'") log.error("Check installation or install via 'pip install gTTS'") log.info("(!) Using slow TTS engine on your OS")
def quit(self) -> None: log.debug("Quitting...") self.stop = True log.info("Bye!") sys.exit()
def speak(text: str) -> None: """ Outputs a text phrase to audio. Steps: 1. If Windows, play using the SAPI engine. Else, play using gTTS and the `play_mp3` function. Args: text (str): the text phrase to say """ if settings.TTS_SUBTITLE: log.info(text) if platform.system() == "Windows" and settings.TTS_AUTODETECT: engine.Speak(text) else: with named_temp_file() as f: output = engine(text=text, lang=settings.LANGUAGE_SHORT) output.save(f.name + ".mp3") play_mp3(f.name + ".mp3")
def run(self) -> None: self.greet() while True: if self.stop: break try: if stt.listen_for_keyword(): log.debug("Back in main loop...") audio = stt.listen() audio_input = stt.recognize(audio) if not audio_input: log.info("Couldn't resolve audio...") continue else: log.info("Catched input: '{0}'".format(audio_input)) cmd = matching.get_match(audio_input) matching.execute_match(cmd) except KeyboardInterrupt: log.info("Detected keyboard interruption...") self.quit() break except: log.error("Unexpected error...") traceback.print_exc() # sends the traceback to Sentry capture_exception(traceback.print_exc()) break
def setup() -> None: # get local environment operating_system = get_operating_system() version = settings.VERSION environment = settings.ENV dsn = settings.SENTRY_DSN # init the Sentry SDK sentry_sdk.init( dsn=dsn, environment=environment, attach_stacktrace=True, sample_rate=1.0, ) # add context to Sentry reports sentry_sdk.set_context( "app", {"version": version, "operating_system": operating_system, "env": environment}, ) log.info("Error reporting setup!")