diff --git a/neon_iris/cli.py b/neon_iris/cli.py index f26f785..f0fa0a1 100644 --- a/neon_iris/cli.py +++ b/neon_iris/cli.py @@ -40,6 +40,7 @@ environ.setdefault("OVOS_CONFIG_BASE_FOLDER", "neon") environ.setdefault("OVOS_CONFIG_FILENAME", "diana.yaml") +# TODO: Define default config file from this package def _print_config(): @@ -80,7 +81,7 @@ def start_client(mq_config, user_config, lang, audio): if user_config: user_config = load_config_file(expanduser(user_config)) client = CLIClient(mq_config, user_config) - LOG.init({"level": logging.WARNING}) + LOG.init({"level": logging.WARNING}) # TODO: Debug flag? client.audio_enabled = audio click.echo("Enter '!{lang}' to change language\n" @@ -118,6 +119,16 @@ def start_client(mq_config, user_config, lang, audio): client.shutdown() +@neon_iris_cli.command(help="Create an MQ listener session") +def start_listener(): + from neon_iris.voice_client import NeonVoiceClient + from ovos_utils import wait_for_exit_signal + client = NeonVoiceClient() + _print_config() + wait_for_exit_signal() + client.shutdown() + + @neon_iris_cli.command(help="Transcribe an audio file") @click.option('--lang', '-l', default='en-us', help="language of input audio") diff --git a/neon_iris/res/start_listening.wav b/neon_iris/res/start_listening.wav new file mode 100644 index 0000000..c320218 Binary files /dev/null and b/neon_iris/res/start_listening.wav differ diff --git a/neon_iris/voice_client.py b/neon_iris/voice_client.py index 3e1e993..d8efd90 100644 --- a/neon_iris/voice_client.py +++ b/neon_iris/voice_client.py @@ -29,7 +29,7 @@ from threading import Event, Thread from time import time from unittest.mock import Mock -from os.path import join, isdir +from os.path import join, isdir, dirname from os import makedirs from ovos_plugin_manager.microphone import OVOSMicrophoneFactory @@ -68,7 +68,8 @@ def __init__(self, bus=None): fallback_stt=Mock(), vad=self._vad, transformers=MockTransformers(), - stt_audio_callback=self.on_stt_audio) + stt_audio_callback=self.on_stt_audio, + listenword_audio_callback=self.on_hotword_audio) self._voice_loop.start() self._voice_thread = None @@ -79,6 +80,9 @@ def __init__(self, bus=None): if not isdir(self._tts_audio_path): makedirs(self._tts_audio_path) + self._listening_sound = join(dirname(__file__), "res", + "start_listening.wav") + self.run() def run(self): @@ -96,25 +100,27 @@ def on_stt_audio(self, audio_bytes: bytes, context: dict): wav_file.writeframes(audio_bytes) self.send_audio(wav_path) + LOG.debug("Sent Audio to MQ") def on_hotword_audio(self, audio: bytes, context: dict): payload = context msg_type = "recognizer_loop:wakeword" - + play_wav(self._listening_sound) LOG.info(f"Emitting hotword event: {msg_type}") # emit ww event self.bus.emit(Message(msg_type, payload, context)) def handle_klat_response(self, message: Message): responses = message.data.get('responses') - for lang, data in responses: + for lang, data in responses.items(): text = data.get('sentence') LOG.info(text) file_basename = f"{hash(text)}.wav" genders = data.get('genders', []) for gender in genders: - audio_data = data.get(gender) - audio_file = join(self._tts_audio_path, lang, gender, file_basename) + audio_data = data["audio"].get(gender) + audio_file = join(self._tts_audio_path, lang, gender, + file_basename) try: decode_base64_string_to_file(audio_data, audio_file) except FileExistsError: @@ -140,10 +146,3 @@ def shutdown(self): self._voice_loop.stop() self._voice_thread.join(30) NeonAIClient.shutdown(self) - - -if __name__ == "__main__": - stopping = Event() - client = NeonVoiceClient() - stopping.wait() -