Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix:add hotwords kwarg #154

Merged
merged 1 commit into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 21 additions & 13 deletions ovos_dinkum_listener/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
import json
import subprocess
import wave
from shutil import which
from enum import Enum
from hashlib import md5
from os.path import dirname
from pathlib import Path
from shutil import which
from tempfile import NamedTemporaryFile
from threading import Thread, RLock, Event
from typing import List, Tuple, Optional
from typing import List, Tuple, Optional, Union

import speech_recognition as sr
import time
Expand All @@ -31,17 +31,18 @@
from ovos_config.locations import get_xdg_data_save_path
from ovos_plugin_manager.microphone import OVOSMicrophoneFactory
from ovos_plugin_manager.stt import get_stt_lang_configs, get_stt_supported_langs, get_stt_module_configs
from ovos_plugin_manager.templates.stt import STT
from ovos_plugin_manager.templates.microphone import Microphone
from ovos_plugin_manager.templates.stt import STT, StreamingSTT
from ovos_plugin_manager.templates.vad import VADEngine
from ovos_plugin_manager.utils.tts_cache import hash_sentence
from ovos_plugin_manager.vad import OVOSVADFactory
from ovos_plugin_manager.vad import get_vad_configs
from ovos_plugin_manager.vad import OVOSVADFactory, get_vad_configs
from ovos_plugin_manager.wakewords import get_ww_lang_configs, get_ww_supported_langs, get_ww_module_configs
from ovos_utils.fakebus import FakeBus
from ovos_utils.log import LOG, log_deprecation
from ovos_utils.process_utils import ProcessStatus, StatusCallbackMap, ProcessState

from ovos_dinkum_listener._util import _TemplateFilenameFormatter
from ovos_dinkum_listener.plugins import load_stt_module, load_fallback_stt
from ovos_dinkum_listener.plugins import load_stt_module, load_fallback_stt, FakeStreamingSTT
from ovos_dinkum_listener.transformers import AudioTransformersService
from ovos_dinkum_listener.voice_loop import DinkumVoiceLoop, ListeningMode, ListeningState
from ovos_dinkum_listener.voice_loop.hotwords import HotwordContainer
Expand Down Expand Up @@ -152,11 +153,14 @@ class OVOSDinkumVoiceService(Thread):

def __init__(self, on_ready=on_ready, on_error=on_error,
on_stopping=on_stopping, on_alive=on_alive,
on_started=on_started, watchdog=lambda: None, mic=None,
bus=None, validate_source=True,
on_started=on_started, watchdog=lambda: None,
mic: Optional[Microphone] = None,
bus: Optional[Union[MessageBusClient, FakeBus]] = None,
validate_source: bool = True,
stt: Optional[STT] = None,
fallback_stt: Optional[STT] = None,
vad: Optional[VADEngine] = None,
hotwords: Optional[HotwordContainer] = None,
disable_fallback: bool = False,
*args, **kwargs):
"""
Expand Down Expand Up @@ -193,11 +197,14 @@ def __init__(self, on_ready=on_ready, on_error=on_error,

self.mic = mic or OVOSMicrophoneFactory.create(microphone_config)

self.hotwords = HotwordContainer(self.bus)
self.hotwords = hotwords or HotwordContainer(self.bus)
self.vad = vad or OVOSVADFactory.create()
if stt and not isinstance(stt, StreamingSTT):
stt = FakeStreamingSTT(stt)
self.stt = stt or load_stt_module()
self.disable_fallback = disable_fallback
self.disable_reload = stt is not None
self.disable_hotword_reload = hotwords is not None
if disable_fallback:
self.fallback_stt = None
else:
Expand Down Expand Up @@ -439,7 +446,8 @@ def _shutdown(self):
if hasattr(self.fallback_stt, "shutdown"):
self.fallback_stt.shutdown()

self.hotwords.shutdown()
if not self.disable_hotword_reload:
self.hotwords.shutdown()

if hasattr(self.vad, "stop"):
self.vad.stop()
Expand Down Expand Up @@ -724,14 +732,14 @@ def _save_stt(self, audio_bytes, stt_meta, save_path=None):
@formatter.register('md5')
def transcription_md5():
# Build a hash of the transcription

try:
# transcriptions should be : List[Tuple[str, int]]
text = stt_meta.get('transcriptions')[0][0]
except IndexError:
# handles legacy API
return stt_meta.get('transcription') or 'null'

JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
return hash_sentence(text)

filename = formatter.format(utterance_filename)
Expand Down Expand Up @@ -1129,7 +1137,7 @@ def reload_configuration(self):
LOG.debug(f"new={self.fallback_stt.__class__}: "
f"{self.fallback_stt.config}")

if new_hash['hotwords'] != self._applied_config_hash['hotwords']:
if not self.disable_hotword_reload and new_hash['hotwords'] != self._applied_config_hash['hotwords']:
LOG.info(f"Reloading Hotwords")
LOG.debug(f"old={self.hotwords.applied_hotwords_config}")
self._reload_event.clear()
Expand Down
8 changes: 7 additions & 1 deletion ovos_dinkum_listener/voice_loop/hotwords.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,26 @@ class HotwordContainer:
_loaded = Event()

def __init__(self, bus=FakeBus(), expected_duration=3, sample_rate=16000,
sample_width=2):
sample_width=2, reload_allowed=True, autoload=False):
self.bus = bus
self.reload_allowed = reload_allowed
self.state = HotwordState.HOTWORD
# used for old style non-streaming wakeword (deprecated)
self.audio_buffer = CyclicAudioBuffer(expected_duration,
sample_rate=sample_rate,
sample_width=sample_width)
self.reload_on_failure = False
self.applied_hotwords_config = None
if autoload:
self.load_hotword_engines()

def load_hotword_engines(self):
"""
Load hotword objects from configuration
"""
if not self.reload_allowed and self._loaded.is_set():
LOG.debug("Hotwords already loaded! skipping reload")
return
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
self._loaded.clear()
LOG.info("creating hotword engines")
config_core = Configuration()
Expand Down
4 changes: 3 additions & 1 deletion ovos_dinkum_listener/voice_loop/voice_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,9 @@ def run(self):
chunk = self.mic.read_chunk()
if not self._is_running: # handle shutdown in middle of read_chunk
break
assert chunk is not None, "No audio from microphone"
if chunk is None:
#LOG.warning("No audio from microphone")
continue
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved

if self.is_muted:
# Soft mute
Expand Down
Loading