ear.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. # -*- coding: utf-8 -*-
  2. from __future__ import division
  3. from .__load__ import *
  4. from .snowboy import snowboydecoder
  5. # 耳朵,聆听者
  6. class Ear(object):
  7. def init(self, robot):
  8. # vecan机器人
  9. self.robot = robot
  10. # 勿扰模式控制 勿扰模式关闭
  11. self.bother = False
  12. # snowboy detector
  13. self.detector = None
  14. # 中断控制
  15. self.interrupted = False
  16. return self
  17. # 语音唤醒模式
  18. def wait(self):
  19. self.robot.logger.info(self.log('唤醒模式:喊我名字叫醒我吧,我听着呢'))
  20. if self.detector is not None:
  21. self.detector.terminate()
  22. self.getConfig()
  23. self.detector = snowboydecoder.HotwordDetector(self.config['models'], sensitivity=self.config['sensitivity'], outname=Demeter.config['vecan']['outname'], temp=Demeter.config['vecan']['temp'],robot=self.robot)
  24. # main loop
  25. #try:
  26. self.detector.start(detected_callback=self.config['callbacks'],
  27. audio_recorder_callback=self.recorderCallback,
  28. interrupt_check=self.interruptCallback,
  29. silent_count_threshold=int(self.config['silent_threshold']),
  30. recording_timeout=int(self.config['recording_timeout']) * 4,
  31. sleep_time=0.03)
  32. self.detector.terminate()
  33. #except Exception as e:
  34. #self.robot.logger.critical(self.log('离线唤醒机制初始化失败:{}'.format(e)))
  35. # listen
  36. def listen(self, silent=False):
  37. self.robot.logger.info(self.log('聆听模式:和我直接对话吧'))
  38. try:
  39. if not silent:
  40. time.sleep(1)
  41. self.robot.mouth.speek(self.robot.data + 'beep_hi.wav')
  42. listener = snowboydecoder.ActiveListener([self.robot.data + self.config['hotword']], outname=Demeter.config['vecan']['outname'], temp=Demeter.config['vecan']['temp'])
  43. voice = listener.listen(
  44. silent_count_threshold=int(self.config['silent_threshold']),
  45. recording_timeout=int(self.config['recording_timeout']) * 4
  46. )
  47. if not silent:
  48. self.robot.mouth.speek(self.robot.data + 'beep_lo.wav')
  49. if voice:
  50. query = self.robot.tool['asr'].asr(voice)
  51. File.remove(voice)
  52. return query
  53. except Exception as e:
  54. Demeter.logger.error(e)
  55. return ''
  56. # snowboy配置,后续改成从数据库读取
  57. def getConfig(self):
  58. self.config = Demeter.config['snowboy']
  59. if self.config['hotword_switch'] == True:
  60. self.config['models'] = [
  61. self.robot.data + self.config['hotword'],
  62. self.robot.data + self.config['on_hotword'],
  63. self.robot.data + self.config['off_hotword']
  64. ]
  65. self.config['callbacks'] = [
  66. self.detectedCallback,
  67. self.onHotwordCallback,
  68. self.offHotwordCallback
  69. ]
  70. else:
  71. self.config['models'] = self.robot.data + self.config['hotword']
  72. self.config['callbacks'] = self.detectedCallback
  73. # close
  74. def close(self):
  75. self.interrupted = True
  76. # callback
  77. def detectedCallback(self):
  78. if not self.isProperTime():
  79. self.robot.logger.warning(self.log('勿扰模式开启中'))
  80. return
  81. if self.robot.isRecording:
  82. self.robot.logger.warning(self.log('正在录音中,跳过'))
  83. return
  84. self.robot.mouth.speek(self.robot.data + 'beep_hi.wav')
  85. self.robot.logger.info(self.log('开始录音'))
  86. self.robot.stop()
  87. self.robot.isRecording = True
  88. def recorderCallback(self, fp, callback=None):
  89. self.robot.mouth.speek(self.robot.data + 'beep_lo.wav')
  90. self.robot.logger.info(self.log('结束录音'))
  91. self.robot.isRecording = False
  92. if self.robot.profiling:
  93. self.robot.logger.info(self.log('性能调试已打开'))
  94. pr = cProfile.Profile()
  95. pr.enable()
  96. self.recorder(fp, callback)
  97. pr.disable()
  98. s = io.StringIO()
  99. sortby = 'cumulative'
  100. ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
  101. ps.print_stats()
  102. print(s.getvalue())
  103. else:
  104. self.recorder(fp, callback)
  105. def recorder(self, fp, callback=None, onSay=None):
  106. try:
  107. self.robot.stop()
  108. query = self.robot.tool['asr'].asr(fp)
  109. File.remove(fp)
  110. self.robot.brain.think(query, callback, onSay)
  111. except Exception as e:
  112. self.robot.logger.critical(self.log(e))
  113. clean()
  114. def onHotwordCallback(self):
  115. if self.config['hotword_switch'] == True:
  116. self.bother = True
  117. self.robot.mouth.speek(self.robot.data + 'off.wav')
  118. self.robot.logger.info(self.log('勿扰模式打开'))
  119. def offHotwordCallback(self):
  120. if self.config['hotword_switch'] == True:
  121. self.bother = False
  122. self.robot.mouth.speek(self.robot.data + 'on.wav')
  123. self.robot.logger.info(self.log('勿扰模式关闭'))
  124. def interruptCallback(self):
  125. return self.interrupted
  126. def isProperTime(self):
  127. if self.bother == True:
  128. return False
  129. if 'bother_enable' not in self.config:
  130. return True
  131. if self.config['bother_enable'] == False:
  132. return True
  133. if 'bother_since' not in self.config or 'bother_till' not in self.config:
  134. return True
  135. since = int(self.config['bother_since'])
  136. till = int(self.config['bother_till'])
  137. current = time.localtime(time.time()).tm_hour
  138. if till > since:
  139. return current not in range(since, till)
  140. else:
  141. return not (current in range(since, 25) or
  142. current in range(-1, till))
  143. def log(self, text):
  144. return 'Ear:' + text