From 1fba09303d3adceac01623623f2fe91ed5e8c9f9 Mon Sep 17 00:00:00 2001 From: Daniel McKnight <34697904+NeonDaniel@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:09:16 -0700 Subject: [PATCH] Fix ovos-audio compat. (#177) # Description Update to address breaking changes in most recent alpha and stable ovos-audio versions # Issues # Other Notes --------- Co-authored-by: Daniel McKnight --- neon_audio/__main__.py | 14 ++++++++++---- neon_audio/service.py | 22 ++++++++++------------ neon_audio/tts/__init__.py | 4 ++-- neon_audio/tts/neon.py | 15 +++++++++++++-- neon_audio/utils.py | 2 ++ requirements/requirements.txt | 8 ++++---- 6 files changed, 41 insertions(+), 24 deletions(-) diff --git a/neon_audio/__main__.py b/neon_audio/__main__.py index 69ceb7e..f9e67f5 100644 --- a/neon_audio/__main__.py +++ b/neon_audio/__main__.py @@ -58,15 +58,21 @@ def main(*args, **kwargs): check_for_signal("isSpeaking") Lock("audio") setup_locale() - service = NeonPlaybackService(*args, **kwargs) - service.start() - wait_for_exit_signal() + try: + service = NeonPlaybackService(*args, **kwargs) + LOG.info("Service init completed") + service.start() + wait_for_exit_signal() + except Exception as e: + LOG.exception(e) + service = None if malloc_running: try: print_malloc(snapshot_malloc()) except Exception as e: LOG.error(e) - service.shutdown() + if service: + service.shutdown() def deprecated_entrypoint(): diff --git a/neon_audio/service.py b/neon_audio/service.py index 833937e..4458dbe 100644 --- a/neon_audio/service.py +++ b/neon_audio/service.py @@ -31,6 +31,7 @@ import ovos_plugin_manager.templates.tts from threading import Event + from ovos_utils.log import LOG, log_deprecation from neon_audio.tts import TTSFactory from neon_utils.messagebus_utils import get_messagebus @@ -84,21 +85,15 @@ def __init__(self, ready_hook=on_ready, error_hook=on_error, from neon_audio.utils import patch_config patch_config(audio_config) bus = bus or get_messagebus() - # Override all the previously loaded signal methods - from neon_utils.signal_utils import init_signal_handlers, \ - init_signal_bus - init_signal_bus(bus) - init_signal_handlers() - from neon_utils.signal_utils import create_signal, check_for_signal - ovos_audio.service.check_for_signal = check_for_signal - ovos_plugin_manager.templates.tts.check_for_signal = check_for_signal - ovos_plugin_manager.templates.tts.create_signal = create_signal + from neon_utils.signal_utils import create_signal - from neon_audio.tts.neon import NeonPlaybackThread - ovos_audio.service.PlaybackThread = NeonPlaybackThread PlaybackService.__init__(self, ready_hook, error_hook, stopping_hook, alive_hook, started_hook, watchdog, bus, - disable_ocp) + disable_ocp, validate_source=False) + del self.playback_thread + from neon_audio.tts.neon import NeonPlaybackThread + from ovos_plugin_manager.tts import TTS + self.playback_thread = NeonPlaybackThread(TTS.queue, self.bus) LOG.debug(f'Initialized tts={self._tts_hash} | ' f'fallback={self._fallback_tts_hash}') create_signal("neon_speak_api") # Create signal so skills use API @@ -186,3 +181,6 @@ def handle_get_tts(self, message): def init_messagebus(self): self.bus.on('neon.get_tts', self.handle_get_tts) PlaybackService.init_messagebus(self) + self.bus.remove("speak", PlaybackService.handle_speak) + self.bus.on("speak", self.handle_speak) + LOG.info("Initialized messagebus") diff --git a/neon_audio/tts/__init__.py b/neon_audio/tts/__init__.py index b09f020..3ae24f0 100644 --- a/neon_audio/tts/__init__.py +++ b/neon_audio/tts/__init__.py @@ -53,11 +53,11 @@ def create(config=None): "en-us") tts_config = get_tts_config(config) - tts_lang = tts_config["lang"] clazz = OVOSTTSFactory.get_class(tts_config) if not clazz: LOG.error(f"Could not find plugin: {tts_config.get('module')}") return - tts = WrappedTTS(clazz, tts_lang, tts_config) + tts = WrappedTTS(clazz, config=tts_config) tts.validator.validate() + LOG.info(f"Initialized tts: {tts.tts_name}") return tts diff --git a/neon_audio/tts/neon.py b/neon_audio/tts/neon.py index 97951da..f51cb32 100644 --- a/neon_audio/tts/neon.py +++ b/neon_audio/tts/neon.py @@ -172,6 +172,7 @@ def end_audio(self, listen, message=None): check_for_signal("isSpeaking") def _play(self): + LOG.debug(f"Start playing {self._now_playing}") # wav_file, vis, listen, ident, message ident = self._now_playing[3] message = self._now_playing[4] @@ -180,7 +181,7 @@ def _play(self): ident = message.context.get('ident') or \ message.context.get('session', {}).get('session_id') - super()._play() + PlaybackThread._play(self) # Notify playback is finished LOG.info(f"Played {ident}") self.bus.emit(message.forward(ident)) @@ -192,9 +193,18 @@ def _play(self): **_sort_timing_metrics( message.context['timing'])})) + def pause(self): + LOG.debug(f"Playback thread paused") + PlaybackThread.pause(self) + + def resume(self): + LOG.debug(f"Playback thread resumed") + PlaybackThread.resume(self) + class WrappedTTS(TTS): def __new__(cls, base_engine, *args, **kwargs): + LOG.info(f"Creating wrapped TTS object for {base_engine}") base_engine.execute = cls.execute base_engine.get_multiple_tts = cls.get_multiple_tts # TODO: Below method is only to bridge compatibility @@ -306,7 +316,6 @@ def get_multiple_tts(self, message, **kwargs) -> dict: for request in tts_requested: tts_lang = kwargs["lang"] = request["language"] # Check if requested tts lang matches internal (text) lang - # TODO: `self.lang` should come from the incoming message if tts_lang.split("-")[0] != skill_lang.split("-")[0]: self.cached_translations.setdefault(tts_lang, {}) @@ -359,6 +368,7 @@ def execute(self, sentence: str, ident: str = None, listen: bool = False, kwargs: (dict) optional keyword arguments to be passed to TTS engine get_tts method """ + LOG.debug(f"execute: {sentence}") stopwatch = Stopwatch("get_tts", True, self.bus) if message: # Make sure to set the speaking signal now @@ -400,6 +410,7 @@ def execute(self, sentence: str, ident: str = None, listen: bool = False, vis = self.viseme(r["phonemes"]) if r["phonemes"] \ else None # queue for playback + LOG.debug(f"Queue playback of: {wav_file}") self.queue.put((wav_file, vis, listen, ident, message)) self.handle_metric({"metric_type": "tts.queued"}) else: diff --git a/neon_audio/utils.py b/neon_audio/utils.py index 24227f6..c864432 100644 --- a/neon_audio/utils.py +++ b/neon_audio/utils.py @@ -74,6 +74,7 @@ def build_extra_dependency_list(config: Union[dict, Configuration], additional: return dependencies + @deprecated("Replaced by `neon_utils.packaging_utils.install_packages_from_pip`", "2.0.0") def install_tts_plugin(plugin: str) -> bool: """ @@ -85,6 +86,7 @@ def install_tts_plugin(plugin: str) -> bool: _, tmp_file = mkstemp() with open(tmp_file, 'w') as f: constraints = '\n'.join(get_package_dependencies("neon-audio")) + constraints += '\n' + '\n'.join(get_package_dependencies("ovos-audio")) f.write(constraints) LOG.info(f"Constraints={constraints}") LOG.info(f"Requested installation of plugin: {plugin}") diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 24cd5a3..413b0ae 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,15 +1,15 @@ -ovos-audio~=0.2 +ovos-audio~=0.0,>=0.0.2 ovos-utils~=0.0,>=0.0.35 ovos-config~=0.0,>=0.0.10 phoneme-guesser~=0.1 -ovos-plugin-manager~=0.0,>=0.0.26 +ovos-plugin-manager~=0.0,>=0.0.26a16 neon-utils[network]~=1.9 click~=8.0 click-default-group~=1.2 -ovos-bus-client~=0.0.3 +ovos-bus-client~=0.0,>=0.0.3 # Default OCP backend + plugins -ovos-plugin-common-play~=0.1 +ovos-plugin-common-play~=0.0,>=0.0.6 ovos-ocp-m3u-plugin~=0.0.1 ovos-ocp-rss-plugin~=0.0.2 ovos-ocp-files-plugin~=0.13