def __init__(self, decoder_model, resource=RESOURCE_FILE, sensitivity=[], audio_gain=1, apply_frontend=False): tm = type(decoder_model) ts = type(sensitivity) if tm is not list: decoder_model = [decoder_model] if ts is not list: sensitivity = [sensitivity] model_str = ",".join(decoder_model) self.detector = snowboydetect.SnowboyDetect( resource_filename=resource.encode(), model_str=model_str.encode()) self.detector.SetAudioGain(audio_gain) self.detector.ApplyFrontend(apply_frontend) self.num_hotwords = self.detector.NumHotwords() if len(decoder_model) > 1 and len(sensitivity) == 1: sensitivity = sensitivity * self.num_hotwords if len(sensitivity) != 0: assert self.num_hotwords == len(sensitivity), \ "number of hotwords in decoder_model (%d) and sensitivity " \ "(%d) does not match" % (self.num_hotwords, len(sensitivity)) sensitivity_str = ",".join([str(t) for t in sensitivity]) if len(sensitivity) != 0: self.detector.SetSensitivity(sensitivity_str.encode()) self.ring_buffer = RingBuffer( self.detector.NumChannels() * self.detector.SampleRate() * 5)
def load_detectors(self) -> None: """Load snowboy detector.""" if not self.detectors: from snowboy import snowboydetect, snowboydecoder # Load model names and settings self.models = self._parse_models() self.model_names = sorted(list(self.models.keys())) # Create snowboy detectors for model_name in self.model_names: model_settings = self.models[model_name] model_path = Path(self.profile.read_path(model_name)) assert model_path.is_file(), f"Missing {model_path}" self._logger.debug("Loading snowboy model from %s", model_path) detector = snowboydetect.SnowboyDetect( snowboydecoder.RESOURCE_FILE.encode(), str(model_path).encode()) detector.SetSensitivity( str(model_settings["sensitivity"]).encode()) detector.SetAudioGain(float(model_settings["audio_gain"])) detector.ApplyFrontend(bool(model_settings["apply_frontend"])) self.detectors.append(detector) self._logger.debug("Loaded snowboy model %s (%s)", model_name, model_settings)
class SnowboySTT(AbstractSTTEngine): """ Snowboy STT 离线识别引擎(只适用于离线唤醒) ... snowboy: model: '/home/pi/.dingdang/snowboy/dingdangdingdang.pmdl' # 唤醒词模型 sensitivity: "0.5" # 敏感度 ... """ SLUG = "snowboy-stt" def __init__(self, sensitivity, model, hotword): self._logger = logging.getLogger(__name__) self.sensitivity = sensitivity self.hotword = hotword self.model = model self.resource_file = os.path.join(dingdangpath.LIB_PATH, 'snowboy/common.res') try: from snowboy import snowboydetect except Exception, e: self._logger.critical(e) if 'libf77blas.so' in e.message: self._logger.critical("您可能需要安装一个so包加载库:" + "sudo apt-get install libatlas-base-dev") return self.detector = snowboydetect.SnowboyDetect( resource_filename=self.resource_file, model_str=self.model) self.detector.SetAudioGain(1) self.detector.SetSensitivity(self.sensitivity)
def load_detector(self) -> None: if self.detector is None: from snowboy import snowboydetect, snowboydecoder self.model_name = self.profile.get("wake.snowboy.model", "snowboy.umdl") model_path = os.path.realpath( self.profile.read_path(self.model_name)) assert os.path.exists( model_path ), f"Can't find snowboy model file (expected at {model_path})" sensitivity = float( self.profile.get("wake.snowboy.sensitivity", 0.5)) audio_gain = float(self.profile.get("wake.snowboy.audio_gain", 1.0)) self._logger.debug(f"Loading snowboy model from {model_path}") self.detector = snowboydetect.SnowboyDetect( snowboydecoder.RESOURCE_FILE.encode(), model_path.encode()) assert self.detector is not None sensitivity_str = str(sensitivity).encode() self.detector.SetSensitivity(sensitivity_str) self.detector.SetAudioGain(audio_gain) self.detector.ApplyFrontend(self.apply_frontend) self._logger.debug( "Loaded snowboy (model=%s, sensitivity=%s, audio_gain=%s)" % (model_path, sensitivity, audio_gain))
def __init__(self, model='snowboy', sensitivity=0.5): super(KWS, self).__init__() resource_path = os.path.join(os.path.dirname(snowboydetect.__file__), 'resources') common_resource = os.path.join(resource_path, 'common.res') for model_path in [ resource_path, os.path.join(resource_path, 'models') ]: builtin_model = os.path.join(model_path, '{}.umdl'.format(model)) if os.path.isfile(builtin_model): model = builtin_model break self.detector = snowboydetect.SnowboyDetect(common_resource.encode(), model.encode()) # self.detector.SetAudioGain(1) # self.detector.ApplyFrontend(True) self.detector.SetSensitivity(str(sensitivity).encode()) self.queue = queue.Queue() self.done = False self.thread = None self.on_detected = None
def setup(self): model_str = ",".join([w.model for w in self._hotwords]) sensitivity_str = ",".join( [str(w.sensitivity) for w in self._hotwords]) self._detector = snowboydetect.SnowboyDetect( resource_filename=self._resource.encode(), model_str=model_str.encode()) self._detector.SetSensitivity(sensitivity_str.encode()) self._detector.SetAudioGain(self._gain)
def __init__(self, hotword, decoder_model, resource=os.path.join(const.resources_path, "common.res"), sensitivity=[], audio_gain=1): self.logger = logging.getLogger("snowboy") def audio_callback(in_data, frame_count, time_info, status): self.ring_buffer.extend(in_data) play_data = chr(0) * len(in_data) return play_data, pyaudio.paContinue tm = type(decoder_model) ts = type(sensitivity) if tm is not list: decoder_model = [decoder_model] if ts is not list: sensitivity = [sensitivity] model_str = ",".join(decoder_model) self.detector = snowboydetect.SnowboyDetect( resource_filename=resource.encode(), model_str=model_str.encode()) self.detector.SetAudioGain(audio_gain) self.num_hotwords = self.detector.NumHotwords() if len(decoder_model) > 1 and len(sensitivity) == 1: sensitivity = sensitivity * self.num_hotwords if len(sensitivity) != 0: assert self.num_hotwords == len(sensitivity), \ "number of hotwords in decoder_model (%d) and sensitivity " \ "(%d) does not match" % (self.num_hotwords, len(sensitivity)) sensitivity_str = ",".join([str(t) for t in sensitivity]) if len(sensitivity) != 0: self.detector.SetSensitivity(sensitivity_str.encode()) size = self.detector.NumChannels() * self.detector.SampleRate() * 5 self.ring_buffer = collections.deque(maxlen=size) self.audio = pyaudio.PyAudio() self.stream_in = self.audio.open( input=True, output=False, format=self.audio.get_format_from_width( self.detector.BitsPerSample() / 8), channels=self.detector.NumChannels(), rate=self.detector.SampleRate(), frames_per_buffer=2048, stream_callback=audio_callback) self.hotword = hotword
def __init__(self, model='snowboy', sensitivity=0.5): super(KWS, self).__init__() resource_path = os.path.join(os.path.dirname(snowboydetect.__file__), 'resources') common_resource = os.path.join(resource_path, 'common.res') if model in ['alexa', 'snowboy']: model = os.path.join(resource_path, '{}.umdl'.format(model)) self.detector = snowboydetect.SnowboyDetect(common_resource, model) # self.detector.SetAudioGain(1) # self.detector.ApplyFrontend(True) self.detector.SetSensitivity(str(sensitivity).encode()) self.queue = queue.Queue() self.done = False self.on_detected = None
def load_detectors(self, site_info: SiteInfo): """Load snowboy detectors from models""" site_info.model_ids = [] site_info.detectors = [] for model in self.models: assert model.model_path.is_file(), f"Missing {model.model_path}" _LOGGER.debug("Loading snowboy model: %s", model) detector = snowboydetect.SnowboyDetect( snowboydecoder.RESOURCE_FILE.encode(), str(model.model_path).encode()) detector.SetSensitivity(model.sensitivity.encode()) detector.SetAudioGain(model.audio_gain) detector.ApplyFrontend(model.apply_frontend) site_info.detectors.append(detector) site_info.model_ids.append(model.model_path.stem)
def setup(self): # """ # :param decoder_model: decoder model file path, a string or a list of strings # :param resource: resource file path. # :param sensitivity: decoder sensitivity, a float of a list of floats. # The bigger the value, the more senstive the # decoder. If an empty list is provided, then the # default sensitivity in the model will be used. # :param audio_gain: multiply input volume by this factor. # """ audio_gain = 1 tm = type(self._model) ts = type(self._sensitivity) if tm is not list: self._model = [self._model] if ts is not list: self._sensitivity = [self._sensitivity] model_str = ",".join(self._model) resource_filename = os.path.join(SNOWBOY_FOLDER, "resources/common.res") self._detector = snowboydetect.SnowboyDetect(resource_filename.encode(), model_str.encode()) self._detector.SetAudioGain(audio_gain) num_hotwords = self._detector.NumHotwords() if len(self._model) > 1 and len(self._sensitivity) == 1: self._sensitivity = self._sensitivity * num_hotwords if self._sensitivity: assert num_hotwords == len(self._sensitivity), \ "number of hotwords in self._model (%d) and sensitivity " \ "(%d) does not match" % (num_hotwords, len(self._sensitivity)) sensitivity_str = ",".join([str(t) for t in self._sensitivity]) self._detector.SetSensitivity(sensitivity_str.encode()) self._ring_buffer = RingBuffer(self._detector.NumChannels() * self._detector.SampleRate() * 5) self._pa = pyaudio.PyAudio()
class SnowboySTT(AbstractSTTEngine): SLUG = "snowboy-stt" def __init__(self, sensitivity, model, hotword): self._logger = logging.getLogger(__name__) self.sensitivity = sensitivity self.hotword = hotword self.model = model self.resource_file = os.path.join(jasperpath.LIB_PATH, 'snowboy/common.res') try: from snowboy import snowboydetect except Exception, e: self._logger.critical(e) if 'libf77blas.so' in e.message: self._logger.critical("您可能需要安装一个so包加载库:" + "sudo apt-get install libatlas-base-dev") return self.detector = snowboydetect.SnowboyDetect( resource_filename=self.resource_file, model_str=self.model) self.detector.SetAudioGain(1) self.detector.SetSensitivity(self.sensitivity)
def main(): # Find available universal models (.umdl) resource_dir = os.path.dirname(snowboydecoder.RESOURCE_FILE) umdl_dir = os.path.join(resource_dir, 'models') umdl_models = { os.path.splitext(name)[0]: os.path.join(umdl_dir, name) for name in os.listdir(umdl_dir) } # Parse arguments parser = argparse.ArgumentParser(description='snowboy') parser.add_argument('--host', help='MQTT host (default=localhost)', type=str, default='localhost') parser.add_argument('--port', help='MQTT port (default=1883)', type=int, default=1883) parser.add_argument('--username', help='MQTT username (default=)', type=str, default='') parser.add_argument('--password', help='MQTT password (default=)', type=str, default='') parser.add_argument('--reconnect', help='Seconds before MQTT reconnect (default=5, disabled=0)', type=float, default=5) parser.add_argument('--site-id', help='Hermes siteId (default=default)', type=str, default='default') parser.add_argument('--wakeword-id', help='Hermes wakewordId (default=default)', type=str, default='default') parser.add_argument('--model', action='append', type=str, help='Path to snowboy model file or one of %s (default=snowboy)' % list(umdl_models.keys()), default=[]) parser.add_argument('--sensitivity', action='append', help='Model sensitivity (default=0.5)', type=float, default=[]) parser.add_argument('--gain', help='Audio gain (default=1.0)', type=float, default=1.0) parser.add_argument('--feedback', help='Show printed feedback', action='store_true') args = parser.parse_args() if len(args.model) == 0: args.model = ['snowboy'] if len(args.sensitivity) == 0: args.sensitivity = [0.5] logging.debug(args) # Create detector(s) detectors = [] for i, model in enumerate(args.model): model_path = umdl_models.get(model, model) detector = snowboydetect.SnowboyDetect( snowboydecoder.RESOURCE_FILE.encode(), model_path.encode()) if len(args.sensitivity) > i: sensitivity_str = str(args.sensitivity[i]).encode() detector.SetSensitivity(sensitivity_str) detector.SetAudioGain(args.gain) detectors.append(detector) # Set up MQTT topic_audio_frame = 'hermes/audioServer/%s/audioFrame' % args.site_id topic_hotword_detected = 'hermes/hotword/%s/detected' % args.wakeword_id client = mqtt.Client() # Login if len(args.username) > 0: logging.debug('Logging in as %s' % args.username) client.username_pw_set(args.username, args.password) # Set up MQTT def on_connect(client, userdata, flags, rc): client.subscribe(topic_audio_frame) client.subscribe('hermes/hotword/toggleOn') client.subscribe('hermes/hotword/toggleOff') logging.debug('Connected to %s:%s' % (args.host, args.port)) first_frame = True listening = True def on_message(client, userdata, message): nonlocal first_frame, listening try: if message.topic == topic_audio_frame: if not listening: return if first_frame: logging.debug('Receiving audio data') first_frame = False if args.feedback: print('.', end='', flush=True) # Extract audio data with io.BytesIO(message.payload) as wav_buffer: with wave.open(wav_buffer, mode='rb') as wav_file: audio_data = wav_file.readframes(wav_file.getnframes()) for detector in detectors: index = detector.RunDetection(audio_data) # Return is: # -2 silence # -1 error # 0 voice # n index n-1 if index > 0: # Hotword detected if args.feedback: print('!', end='', flush=True) logging.debug('Hotword detected!') payload = json.dumps({ 'siteId': args.site_id, 'modelId': args.model, 'modelVersion': '', 'modelType': 'personal', 'currentSensitivity': args.sensitivity }).encode() client.publish(topic_hotword_detected, payload) first_frame = True elif message.topic == 'hermes/hotword/toggleOn': listening = True logging.debug('On') elif message.topic == 'hermes/hotword/toggleOff': listening = False logging.debug('Off') except Exception as e: logging.exception('on_message') client.on_connect = on_connect client.on_message = on_message def on_disconnect(client, userdata, rc): logging.warn('Disconnected') if args.reconnect > 0: time.sleep(args.reconnect) logging.debug('Reconnecting') client.connect(args.host, args.port) client.on_disconnect = on_disconnect connected = False while not connected: try: client.connect(args.host, args.port) connected = True except Exception as e: logging.exception('connect') if args.reconnect > 0: time.sleep(args.reconnect) logging.debug('Reconnecting') else: return try: logging.info('Listening') client.loop_forever() except KeyboardInterrupt: pass
def main(): # Find available universal models (.umdl) resource_dir = os.path.dirname(snowboydecoder.RESOURCE_FILE) umdl_dir = os.path.join(resource_dir, "models") umdl_models = { os.path.splitext(name)[0]: os.path.join(umdl_dir, name) for name in os.listdir(umdl_dir) } # Parse arguments parser = argparse.ArgumentParser(description="snowboy") parser.add_argument("--host", help="MQTT host (default=localhost)", type=str, default="localhost") parser.add_argument("--port", help="MQTT port (default=1883)", type=int, default=1883) parser.add_argument("--username", help="MQTT username (default=)", type=str, default="") parser.add_argument("--password", help="MQTT password (default=)", type=str, default="") parser.add_argument( "--reconnect", help="Seconds before MQTT reconnect (default=5, disabled=0)", type=float, default=5, ) parser.add_argument("--site-id", help="Hermes siteId (default=default)", type=str, default="default") parser.add_argument( "--wakeword-id", help="Hermes wakewordId (default=default)", type=str, default="default", ) parser.add_argument( "--model", action="append", type=str, help="Path to snowboy model file or one of %s (default=snowboy)" % list(umdl_models.keys()), default=[], ) parser.add_argument( "--sensitivity", action="append", help="Model sensitivity (default=0.5)", type=float, default=[], ) parser.add_argument("--gain", help="Audio gain (default=1.0)", type=float, default=1.0) parser.add_argument("--feedback", help="Show printed feedback", action="store_true") args = parser.parse_args() if len(args.model) == 0: args.model = ["snowboy"] if len(args.sensitivity) == 0: args.sensitivity = [0.5] logging.debug(args) # Create detector(s) detectors = [] for i, model in enumerate(args.model): model_path = umdl_models.get(model, model) detector = snowboydetect.SnowboyDetect( snowboydecoder.RESOURCE_FILE.encode(), model_path.encode()) if len(args.sensitivity) > i: sensitivity_str = str(args.sensitivity[i]).encode() detector.SetSensitivity(sensitivity_str) detector.SetAudioGain(args.gain) detectors.append(detector) # Set up MQTT topic_audio_frame = "hermes/audioServer/%s/audioFrame" % args.site_id topic_hotword_detected = "hermes/hotword/%s/detected" % args.wakeword_id client = mqtt.Client() # Login if len(args.username) > 0: logging.debug("Logging in as %s" % args.username) client.username_pw_set(args.username, args.password) # Set up MQTT def on_connect(client, userdata, flags, rc): client.subscribe(topic_audio_frame) client.subscribe("hermes/hotword/toggleOn") client.subscribe("hermes/hotword/toggleOff") logging.debug("Connected to %s:%s" % (args.host, args.port)) first_frame = True listening = True def on_message(client, userdata, message): nonlocal first_frame, listening try: if message.topic == topic_audio_frame: if not listening: return if first_frame: logging.debug("Receiving audio data") first_frame = False if args.feedback: print(".", end="", flush=True) # Extract audio data with io.BytesIO(message.payload) as wav_buffer: with wave.open(wav_buffer, mode="rb") as wav_file: audio_data = wav_file.readframes(wav_file.getnframes()) for detector in detectors: index = detector.RunDetection(audio_data) # Return is: # -2 silence # -1 error # 0 voice # n index n-1 if index > 0: # Hotword detected if args.feedback: print("!", end="", flush=True) logging.debug("Hotword detected!") payload = json.dumps({ "siteId": args.site_id, "modelId": args.model[0], "modelVersion": "", "modelType": "personal", "currentSensitivity": args.sensitivity[0], }).encode() client.publish(topic_hotword_detected, payload) first_frame = True elif message.topic == "hermes/hotword/toggleOn": listening = True logging.debug("On") elif message.topic == "hermes/hotword/toggleOff": listening = False logging.debug("Off") except Exception as e: logging.exception("on_message") client.on_connect = on_connect client.on_message = on_message def on_disconnect(client, userdata, rc): logging.warn("Disconnected") if args.reconnect > 0: time.sleep(args.reconnect) logging.debug("Reconnecting") client.connect(args.host, args.port) client.on_disconnect = on_disconnect connected = False while not connected: try: client.connect(args.host, args.port) connected = True except Exception as e: logging.exception("connect") if args.reconnect > 0: time.sleep(args.reconnect) logging.debug("Reconnecting") else: return try: logging.info("Listening") client.loop_forever() except KeyboardInterrupt: pass