# -*- coding: utf-8 -*- from __future__ import division from .__load__ import * from .snowboy import snowboydecoder # 耳朵,聆听者 class Ear(object): def init(self, robot): # vecan机器人 self.robot = robot # 勿扰模式控制 勿扰模式关闭 self.bother = False # snowboy detector self.detector = None # 中断控制 self.interrupted = False return self # 语音唤醒模式 def wait(self): self.robot.logger.info(self.log('唤醒模式:喊我名字叫醒我吧,我听着呢')) if self.detector is not None: self.detector.terminate() self.getConfig() self.detector = snowboydecoder.HotwordDetector(self.config['models'], sensitivity=self.config['sensitivity'], outname=Demeter.config['vecan']['outname'], temp=Demeter.config['vecan']['temp'],robot=self.robot) # main loop #try: self.detector.start(detected_callback=self.config['callbacks'], audio_recorder_callback=self.recorderCallback, interrupt_check=self.interruptCallback, silent_count_threshold=int(self.config['silent_threshold']), recording_timeout=int(self.config['recording_timeout']) * 4, sleep_time=0.03) self.detector.terminate() #except Exception as e: #self.robot.logger.critical(self.log('离线唤醒机制初始化失败:{}'.format(e))) # listen def listen(self, silent=False): self.robot.logger.info(self.log('聆听模式:和我直接对话吧')) try: if not silent: time.sleep(1) self.robot.mouth.speek(self.robot.data + 'beep_hi.wav') listener = snowboydecoder.ActiveListener([self.robot.data + self.config['hotword']], outname=Demeter.config['vecan']['outname'], temp=Demeter.config['vecan']['temp']) voice = listener.listen( silent_count_threshold=int(self.config['silent_threshold']), recording_timeout=int(self.config['recording_timeout']) * 4 ) if not silent: self.robot.mouth.speek(self.robot.data + 'beep_lo.wav') if voice: query = self.robot.tool['asr'].asr(voice) File.remove(voice) return query except Exception as e: Demeter.logger.error(e) return '' # snowboy配置,后续改成从数据库读取 def getConfig(self): self.config = Demeter.config['snowboy'] if self.config['hotword_switch'] == True: self.config['models'] = [ self.robot.data + self.config['hotword'], self.robot.data + self.config['on_hotword'], self.robot.data + self.config['off_hotword'] ] self.config['callbacks'] = [ self.detectedCallback, self.onHotwordCallback, self.offHotwordCallback ] else: self.config['models'] = self.robot.data + self.config['hotword'] self.config['callbacks'] = self.detectedCallback # close def close(self): self.interrupted = True # callback def detectedCallback(self): if not self.isProperTime(): self.robot.logger.warning(self.log('勿扰模式开启中')) return if self.robot.isRecording: self.robot.logger.warning(self.log('正在录音中,跳过')) return self.robot.mouth.speek(self.robot.data + 'beep_hi.wav') self.robot.logger.info(self.log('开始录音')) self.robot.stop() self.robot.isRecording = True def recorderCallback(self, fp, callback=None): self.robot.mouth.speek(self.robot.data + 'beep_lo.wav') self.robot.logger.info(self.log('结束录音')) self.robot.isRecording = False if self.robot.profiling: self.robot.logger.info(self.log('性能调试已打开')) pr = cProfile.Profile() pr.enable() self.recorder(fp, callback) pr.disable() s = io.StringIO() sortby = 'cumulative' ps = pstats.Stats(pr, stream=s).sort_stats(sortby) ps.print_stats() print(s.getvalue()) else: self.recorder(fp, callback) def recorder(self, fp, callback=None, onSay=None): try: self.robot.stop() query = self.robot.tool['asr'].asr(fp) File.remove(fp) self.robot.brain.think(query, callback, onSay) except Exception as e: self.robot.logger.critical(self.log(e)) clean() def onHotwordCallback(self): if self.config['hotword_switch'] == True: self.bother = True self.robot.mouth.speek(self.robot.data + 'off.wav') self.robot.logger.info(self.log('勿扰模式打开')) def offHotwordCallback(self): if self.config['hotword_switch'] == True: self.bother = False self.robot.mouth.speek(self.robot.data + 'on.wav') self.robot.logger.info(self.log('勿扰模式关闭')) def interruptCallback(self): return self.interrupted def isProperTime(self): if self.bother == True: return False if 'bother_enable' not in self.config: return True if self.config['bother_enable'] == False: return True if 'bother_since' not in self.config or 'bother_till' not in self.config: return True since = int(self.config['bother_since']) till = int(self.config['bother_till']) current = time.localtime(time.time()).tm_hour if till > since: return current not in range(since, till) else: return not (current in range(since, 25) or current in range(-1, till)) def log(self, text): return 'Ear:' + text