Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
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)
Пример #4
0
    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))
Пример #5
0
    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
Пример #6
0
 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)
Пример #7
0
    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
Пример #8
0
    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()
Пример #11
0
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)
Пример #12
0
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
Пример #13
0
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