diff --git a/neon_speech/__init__.py b/neon_speech/__init__.py index 718d1b0..4af0cae 100644 --- a/neon_speech/__init__.py +++ b/neon_speech/__init__.py @@ -25,3 +25,6 @@ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Import to ensure patched class is applied +from neon_speech.transformers import NeonAudioTransformerService diff --git a/neon_speech/service.py b/neon_speech/service.py index e6feb36..27ae9c2 100644 --- a/neon_speech/service.py +++ b/neon_speech/service.py @@ -112,6 +112,8 @@ def __init__(self, ready_hook=on_ready, error_hook=on_error, watchdog=watchdog) self.daemon = daemonic self.config.bus = self.bus + self._stt_stopwatch = Stopwatch("get_stt", allow_reporting=True, + bus=self.bus) from neon_utils.signal_utils import init_signal_handlers, \ init_signal_bus init_signal_bus(self.bus) @@ -133,6 +135,25 @@ def __init__(self, ready_hook=on_ready, error_hook=on_error, LOG.info("Skipping api_stt init") self.api_stt = None + def _record_begin(self): + self._stt_stopwatch.start() + OVOSDinkumVoiceService._record_begin(self) + + def _stt_text(self, text: str, stt_context: dict): + self._stt_stopwatch.stop() + stt_context.setdefault("timing", dict()) + stt_context["timing"]["get_stt"] = self._stt_stopwatch.time + + # This is where the first Message of the interaction is created + OVOSDinkumVoiceService._stt_text(self, text, stt_context) + self._stt_stopwatch.report() + + def _save_stt(self, audio_bytes, stt_meta, save_path=None): + with Stopwatch("save_audio", True, self.bus): + path = OVOSDinkumVoiceService._save_stt(self, audio_bytes, stt_meta, + save_path) + return path + def _validate_message_context(self, message: Message, native_sources=None): if message.context.get('destination') and \ "audio" not in message.context['destination']: diff --git a/neon_speech/transformers.py b/neon_speech/transformers.py new file mode 100644 index 0000000..dde3179 --- /dev/null +++ b/neon_speech/transformers.py @@ -0,0 +1,47 @@ +# NEON AI (TM) SOFTWARE, Software Development Kit & Application Framework +# All trademark and other rights reserved by their respective owners +# Copyright 2008-2022 Neongecko.com Inc. +# Contributors: Daniel McKnight, Guy Daniels, Elon Gasper, Richard Leeds, +# Regina Bloomstine, Casimiro Ferreira, Andrii Pernatii, Kirill Hrymailo +# BSD-3 License +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import ovos_dinkum_listener.transformers +from neon_utils.metrics_utils import Stopwatch +from ovos_dinkum_listener.transformers import AudioTransformersService + + +class NeonAudioTransformerService(AudioTransformersService): + """ + Overrides the default AudioTransformersService to add timing metrics + """ + + def transform(self, chunk: bytes) -> (bytes, dict): + stopwatch = Stopwatch("transform_audio", True, self.bus) + with stopwatch: + chunk, context = AudioTransformersService.transform(self, chunk) + context.setdefault("timing", dict()) + context['timing']['transform_audio'] = stopwatch.time + return chunk, context + + +ovos_dinkum_listener.transformers.AudioTransformersService = NeonAudioTransformerService