예제 #1
0
    def __init__(self, lisa_client, botname):
        # Init thread class
        threading.Thread.__init__(self)
        self._stopevent = threading.Event()

        configuration = ConfigManagerSingleton.get().getConfiguration()
        self.botname = lisa_client.botname.lower()
        self.scores = []
        self.record_time_start = 0
        self.record_time_end = 0
        self.wit_thread = None
        self.loop = None
        if configuration.has_key("keyword_score"):
            self.keyword_score = configuration['keyword_score']
        else:
            self.keyword_score = -10000

        # Build Gstreamer pipeline : mic->Pulse->tee|->queue->audioConvert->audioResample->vader->pocketsphinx->fakesink
        #                                           |->queue->audioConvert->audioResample->lamemp3enc->appsink
        # fakesink : async=false is mandatory for parallelism
        self.pipeline = gst.parse_launch('pulsesrc '
                                        #+ '! ladspa-gate Threshold=-30.0 Decay=2.0 Hold=2.0 Attack=0.1 '
                                        + '! tee name=audio_tee '
                                        + ' audio_tee. ! queue '
                                        + '            ! audioconvert ! audioresample '
                                        + '            ! audio/x-raw-int, format=(string)S16_LE, channels=1, rate=16000 '
                                        + '            ! lamemp3enc bitrate=64 mono=true '
                                        + '            ! appsink name=rec_sink emit-signals=true '
                                        + ' audio_tee. ! queue '
                                        + '            ! audioconvert ! audioresample '
                                        + '            ! vader name=vad_asr auto-threshold=true'
                                        + '            ! tee name=asr_tee '
                                        + '             asr_tee. ! fakesink async=false name=asr_sink'
                                        + '             asr_tee. ! pocketsphinx name=asr '
                                        + '                      ! fakesink async=false'
                                         )

        # Create recorder
        self.recorder = Recorder(lisa_client = lisa_client, listener = self)

        # Find client path
        if os.path.isdir('/var/lib/lisa/client/pocketsphinx'):
            client_path = '/var/lib/lisa/client/pocketsphinx'
        else:
            client_path = "%s/pocketsphinx" % PWD

        # PocketSphinx configuration
        asr = self.pipeline.get_by_name('asr')
        asr.set_property("dict", "%s/%s.dic" % (client_path, self.botname))
        asr.set_property("lm", "%s/%s.lm" % (client_path, self.botname))
        if configuration.has_key("hmm"):
            hmm_path = "%s/%s" % (client_path, configuration["hmm"])
            if os.path.isdir(hmm_path):
                asr.set_property("hmm", hmm_path)
        asr.connect('result', self._asr_result)
        asr.set_property('configured', True)
        self.ps = pocketsphinx.Decoder(boxed=asr.get_property('decoder'))

        # Start thread
        self.start()
예제 #2
0
    def __init__(self, factory):
        # Init thread class
        threading.Thread.__init__(self)
        self._stopevent = threading.Event()

        self.configuration = ConfigManager.getConfiguration()
        self._ = self.configuration['trans']
        self.factory = factory
        self.botname = ""
        self.scores = []
        self.recorder = Recorder(factory = factory)
        self.running_state = False

        # Find client path
        if os.path.isdir('/var/lib/lisa/client/pocketsphinx'):
            self.client_path = '/var/lib/lisa/client/pocketsphinx'
        else:
            self.client_path = "{0}/lib/pocketsphinx".format(self.configuration['path'])

        # Initialize with a default bot name
        self.setBotName("neo")

        # Start thread
        threading.Thread.start(self)
예제 #3
0
class Listener(threading.Thread):
    """
    The goal is to listen for a keyword, then it starts a voice recording
    """

    #-----------------------------------------------------------------------------
    def __init__(self, factory):
        # Init thread class
        threading.Thread.__init__(self)
        self._stopevent = threading.Event()

        self.configuration = ConfigManager.getConfiguration()
        self._ = self.configuration['trans']
        self.factory = factory
        self.botname = ""
        self.scores = []
        self.recorder = Recorder(factory = factory)
        self.running_state = False

        # Find client path
        if os.path.isdir('/var/lib/lisa/client/pocketsphinx'):
            self.client_path = '/var/lib/lisa/client/pocketsphinx'
        else:
            self.client_path = "{0}/lib/pocketsphinx".format(self.configuration['path'])

        # Initialize with a default bot name
        self.setBotName("neo")

        # Start thread
        threading.Thread.start(self)

    #-----------------------------------------------------------------------------
    def setBotName(self, botname):
        # If nothing to do
        if botname == self.botname:
            return
        self.botname = botname

        # Pause thread
        self.setRunningState(state = False)

        # Init pipes
        self.pipes = []
        for i in range(NUM_PIPES):
            self.pipes.append({'vad' : None, 'ps' : None, 'timeout' : 0})

        # Build Gstreamer pipeline
        if self.configuration['asr'] == "ispeech":
            enc_str = 'speexenc mode=2'
        elif self.configuration['asr'] == "google":
            enc_str = 'flacenc'
        # Default Wit
        else:
            enc_str = 'lamemp3enc bitrate=16 mono=true'
        pipeline = 'pulsesrc' \
                    + ' ! tee name=audio_tee' \
                    + ' audio_tee.' \
                    + ' ! queue ! audiodynamic characteristics=soft-knee mode=compressor threshold=0.5 ratio=0.5 ! audioconvert ! audioresample' \
                    + ' ! audio/x-raw-int, format=(string)S16_LE, channels=1, rate=16000' \
                    + ' ! ' + enc_str \
                    + ' ! appsink name=rec_sink emit-signals=true async=false' \
                    + ' audio_tee.' \
                    + ' ! queue ! audiocheblimit mode=1 cutoff=150' \
                    + ' ! audiodynamic ! audioconvert ! audioresample' \
                    + ' ! tee name=asr_tee'

        # Add pocketsphinx
        for i in range(NUM_PIPES):
            pipeline = pipeline \
                    + ' asr_tee.' \
                    + ' ! vader name=vad_{0} auto-threshold=true'.format(i) \
                    + ' ! pocketsphinx name=asr_{0}'.format(i) \
                    + ' ! fakesink async=false'

        # Create pipeline
        self.pipeline = gst.parse_launch(pipeline)

        # Configure pipes
        for i in range(NUM_PIPES):
            # Initialize vader
            vader = self.pipeline.get_by_name('vad_{0}'.format(i))
            vader.connect('vader-start', self._vaderStart, i)
            vader.connect('vader-stop', self._vaderStop, i)
            self.pipes[i]['vad'] = vader

            # Initialize pocketsphinx
            asr = self.pipeline.get_by_name('asr_{0}'.format(i))
            asr.set_property("dict", "{path}/{bot}.dic".format(path = self.client_path, bot = self.botname))
            asr.set_property("lm", "{path}/{bot}.lm".format(path = self.client_path, bot = self.botname))
            if self.configuration.has_key("hmm"):
                if os.path.isdir(self.configuration["hmm"]):
                    asr.set_property("hmm", self.configuration["hmm"])
                else:
                    hmm_path = "{path}/{hmm}".format(path = self.client_path, hmm = self.configuration["hmm"])
                    if os.path.isdir(hmm_path):
                        asr.set_property("hmm", hmm_path)
            asr.connect('result', self._asrResult, i)
            asr.set_property('configured', 1)
            self.pipes[i]['ps'] = pocketsphinx.Decoder(boxed = asr.get_property('decoder'))

        # Start pipeline
        self.pipeline.set_state(gst.STATE_PLAYING)

        # Restart
        self.setRunningState(state = True)

    #-----------------------------------------------------------------------------
    def setRunningState(self, state):
        if state == True:
            # Restart
            self.running_state = True
            self.recorder.setRunningState(state = True, rec_sink = self.pipeline.get_by_name('rec_sink'))
        else:
            # Pause thread
            self.running_state = False
            self.recorder.setRunningState(state = False)

    #-----------------------------------------------------------------------------
    def setContinuousMode(self, enabled, wit_context = None):
        # Change continuous mode in recorder
        self.recorder.setContinuousMode(enabled = enabled, wit_context = wit_context)

    #-----------------------------------------------------------------------------
    def run(self):
        """
        Listener main loop
        """
        # Thread loop
        while not self._stopevent.isSet():
            if self.running_state == True:
                for p in self.pipes:
                    if p['timeout'] > 0 and time() >= p['timeout']:
                        # Force silent to cut current utterance
                        p['vad'].set_property('silent', True)
                        p['vad'].set_property('silent', False)

                        # Manual start (vader_start may be not called after the forced silence)
                        p['timeout'] += VADER_MAX_LENGTH
                        self.recorder.vaderStart()
            sleep(.1)

        # Stop pipeline
        self.pipeline.set_state(gst.STATE_NULL)
        self.pipeline = None

    #-----------------------------------------------------------------------------
    def stop(self):
        """
        Stop listener.
        """
        # Stop everything
        self.recorder.stop()
        self._stopevent.set()

    #-----------------------------------------------------------------------------
    def _vaderStart(self, ob, message, pipe_id):
        """
        Vader start detection
        """
        # Vader start
        if self.pipes[pipe_id]['timeout'] == 0:
            self.pipes[pipe_id]['timeout'] = time() + VADER_MAX_LENGTH * (1 + pipe_id / 2.0)
        self.recorder.vaderStart()

    #-----------------------------------------------------------------------------
    def _vaderStop(self, ob, message, pipe_id):
        """
        Vader stop detection
        """
        # Vader stop
        self.pipes[pipe_id]['timeout'] = 0
        self.recorder.vaderStop()

    #-----------------------------------------------------------------------------
    def _asrResult(self, asr, text, uttid, pipe_id):
        """
        Result from pocketsphinx : checking keyword recognition
        """
        # When not running
        if self.running_state == False:
            return

        # Get score from decoder
        dec_text, dec_uttid, dec_score = self.pipes[pipe_id]['ps'].get_hyp()

        # Detection must have a minimal score to be valid
        if dec_score != 0 and dec_score < self.configuration['keyword_score']:
            log.msg("I recognized the {word} keyword but I think it's a false positive according the {score} score".format(word = self.botname, score = dec_score))
            return

        # Activate recorder
        self.recorder.activate()

        # Logs
        self.scores.append(dec_score)
        log.msg("======================")
        log.msg("{word} keyword detected".format(word = self.botname))
        log.msg("score: {score} (min {min}, moy {moy}, max {max})".format(score = dec_score, min = min(self.scores), moy = sum(self.scores) / len(self.scores), max = max(self.scores)))
예제 #4
0
class Listener(threading.Thread):
    """
    The goal is to listen for a keyword, then it starts a voice recording
    """

    def __init__(self, lisa_client, botname):
        # Init thread class
        threading.Thread.__init__(self)
        self._stopevent = threading.Event()

        configuration = ConfigManagerSingleton.get().getConfiguration()
        self.botname = lisa_client.botname.lower()
        self.scores = []
        self.record_time_start = 0
        self.record_time_end = 0
        self.wit_thread = None
        self.loop = None
        if configuration.has_key("keyword_score"):
            self.keyword_score = configuration['keyword_score']
        else:
            self.keyword_score = -10000

        # Build Gstreamer pipeline : mic->Pulse->tee|->queue->audioConvert->audioResample->vader->pocketsphinx->fakesink
        #                                           |->queue->audioConvert->audioResample->lamemp3enc->appsink
        # fakesink : async=false is mandatory for parallelism
        self.pipeline = gst.parse_launch('pulsesrc '
                                        #+ '! ladspa-gate Threshold=-30.0 Decay=2.0 Hold=2.0 Attack=0.1 '
                                        + '! tee name=audio_tee '
                                        + ' audio_tee. ! queue '
                                        + '            ! audioconvert ! audioresample '
                                        + '            ! audio/x-raw-int, format=(string)S16_LE, channels=1, rate=16000 '
                                        + '            ! lamemp3enc bitrate=64 mono=true '
                                        + '            ! appsink name=rec_sink emit-signals=true '
                                        + ' audio_tee. ! queue '
                                        + '            ! audioconvert ! audioresample '
                                        + '            ! vader name=vad_asr auto-threshold=true'
                                        + '            ! tee name=asr_tee '
                                        + '             asr_tee. ! fakesink async=false name=asr_sink'
                                        + '             asr_tee. ! pocketsphinx name=asr '
                                        + '                      ! fakesink async=false'
                                         )

        # Create recorder
        self.recorder = Recorder(lisa_client = lisa_client, listener = self)

        # Find client path
        if os.path.isdir('/var/lib/lisa/client/pocketsphinx'):
            client_path = '/var/lib/lisa/client/pocketsphinx'
        else:
            client_path = "%s/pocketsphinx" % PWD

        # PocketSphinx configuration
        asr = self.pipeline.get_by_name('asr')
        asr.set_property("dict", "%s/%s.dic" % (client_path, self.botname))
        asr.set_property("lm", "%s/%s.lm" % (client_path, self.botname))
        if configuration.has_key("hmm"):
            hmm_path = "%s/%s" % (client_path, configuration["hmm"])
            if os.path.isdir(hmm_path):
                asr.set_property("hmm", hmm_path)
        asr.connect('result', self._asr_result)
        asr.set_property('configured', True)
        self.ps = pocketsphinx.Decoder(boxed=asr.get_property('decoder'))

        # Start thread
        self.start()

    def run(self):
        """
        Listener main loop
        """
        Speaker.speak("ready")
        self.pipeline.set_state(gst.STATE_PLAYING)

        # Thread loop
        self.loop = gobject.MainLoop()
        self.loop.run()

    def stop(self):
        """
        Stop listener.
        """
        Speaker.speak('lost_server')

        # Stop everything
        self.pipeline.set_state(gst.STATE_NULL)
        self.recorder.stop()
        if self.loop is not None:
            self.loop.quit()

    def _asr_result(self, asr, text, uttid):
        """
        Result from pocketsphinx : checking keyword recognition
        """
        # Check keyword detection
        if text.lower() == self.botname and self.recorder.get_running_state() == False:
            # Get scrore from decoder
            dec_text, dec_uttid, dec_score = self.ps.get_hyp()

            # Detection must have a minimal score to be valid
            if dec_score < self.keyword_score:
                log.msg("I recognized the %s keyword but I think it's a false positive according the %s score" % (self.botname, dec_score))
                return

            # Logs
            self.scores.append(dec_score)
            log.msg("======================")
            log.msg("%s keyword detected" % self.botname)
            log.msg("score: {} (min {}, moy {}, max {})".format(dec_score, min(self.scores), sum(self.scores) / len(self.scores), max(self.scores)))

            # Start voice recording
            Speaker.speak('yes')

            # Start recorder
            self.recorder.set_running_state(True)

    def get_pipeline(self):
        """
        Return Gstreamer pipeline
        """
        return self.pipeline