snowboy.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. # -*- coding: utf-8 -*-
  2. from __future__ import division
  3. from .__load__ import *
  4. from snowboy import snowboydecoder
  5. class Snowboy(object):
  6. def init(self, robot):
  7. # 勿扰模式控制 勿扰模式关闭
  8. self.bother = False
  9. # snowboy detector
  10. self.detector = None
  11. # 中断控制
  12. self.interrupted = False
  13. # vecan机器人
  14. self.robot = robot
  15. self.hotword()
  16. # 启动hotword
  17. def hotword(self):
  18. if self.detector is not None:
  19. self.detector.terminate()
  20. self.getConfig()
  21. self.detector = snowboydecoder.HotwordDetector(self.config['models'], sensitivity=self.config['sensitivity'], outname=Demeter.config['vecan']['outname'], temp=Demeter.config['vecan']['temp'])
  22. # main loop
  23. try:
  24. self.detector.start(detected_callback=self.config['callbacks'],
  25. audio_recorder_callback=self.robot.talk,
  26. interrupt_check=self.interruptCallback,
  27. silent_count_threshold=int(self.config['silent_threshold']),
  28. recording_timeout=int(self.config['recording_timeout']) * 4,
  29. sleep_time=0.03)
  30. self.detector.terminate()
  31. except Exception as e:
  32. Demeter.logger.critical('离线唤醒机制初始化失败:{}'.format(e))
  33. # active
  34. def listen(self, silent=False):
  35. Demeter.logger.debug('activeListen')
  36. try:
  37. if not silent:
  38. time.sleep(1)
  39. self.robot.play(self.robot.data + 'beep_hi.wav')
  40. listener = snowboydecoder.ActiveListener([self.robot.data + self.config['hotword']], outname=Demeter.config['vecan']['outname'], temp=Demeter.config['vecan']['temp'])
  41. voice = listener.listen(
  42. silent_count_threshold=int(self.config['silent_threshold']),
  43. recording_timeout=int(self.config['recording_timeout']) * 4
  44. )
  45. if not silent:
  46. self.robot.play(self.robot.data + 'beep_lo.wav')
  47. if voice:
  48. query = self.robot.tool['asr'].asr(voice)
  49. Demeter.remove(voice)
  50. return query
  51. except Exception as e:
  52. Demeter.logger.error(e)
  53. return ''
  54. # snowboy配置,后续改成从数据库读取
  55. def getConfig(self):
  56. self.config = Demeter.config['snowboy']
  57. if self.config['hotword_switch'] == True:
  58. self.config['models'] = [
  59. self.robot.data + self.config['hotword'],
  60. self.robot.data + self.config['on_hotword'],
  61. self.robot.data + self.config['off_hotword']
  62. ]
  63. self.config['callbacks'] = [
  64. self.detectedCallback,
  65. self.onHotwordCallback,
  66. self.offHotwordCallback
  67. ]
  68. else:
  69. self.config['models'] = self.robot.data + self.config['hotword']
  70. self.config['callbacks'] = self.detectedCallback
  71. # stop
  72. def stop(self):
  73. self.interrupted = True
  74. clean()
  75. # callback
  76. def detectedCallback(self):
  77. if not self.isProperTime():
  78. Demeter.logger.warning('勿扰模式开启中')
  79. return
  80. if self.robot.isRecording:
  81. Demeter.logger.warning('正在录音中,跳过')
  82. return
  83. self.robot.player.play(self.robot.data + 'beep_hi.wav')
  84. Demeter.logger.info('开始录音')
  85. self.robot.interrupt()
  86. self.robot.isRecording = True;
  87. def onHotwordCallback(self):
  88. if self.config['hotword_switch'] == True:
  89. self.bother = True
  90. self.robot.player.play(self.robot.data + 'off.wav')
  91. Demeter.logger.info('勿扰模式打开')
  92. def offHotwordCallback(self):
  93. if self.config['hotword_switch'] == True:
  94. self.bother = False
  95. self.robot.player.play(self.robot.data + 'on.wav')
  96. Demeter.logger.info('勿扰模式关闭')
  97. def interruptCallback(self):
  98. return self.interrupted
  99. def isProperTime():
  100. if self.bother == True:
  101. return False
  102. if 'bother_enable' not in self.config:
  103. return True
  104. if self.config['bother_enable'] == False:
  105. return True
  106. if 'bother_since' not in self.config or 'bother_till' not in self.config:
  107. return True
  108. since = self.config['bother_since']
  109. till = self.config['bother_till']
  110. current = time.localtime(time.time()).tm_hour
  111. if till > since:
  112. return current not in range(since, till)
  113. else:
  114. return not (current in range(since, 25) or
  115. current in range(-1, till))