Rhino.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import argparse
  4. import struct
  5. import wave
  6. from threading import Thread
  7. import pvrhino
  8. from pvrecorder import PvRecorder
  9. import platform
  10. import configparser
  11. import os
  12. from VoicePlay import Voice
  13. class Rhino(Thread):
  14. instance = None
  15. @staticmethod
  16. def getInstance():
  17. if Rhino.instance==None:
  18. Rhino.instance = Rhino()
  19. return Rhino.instance
  20. def __init__(self):
  21. super(Rhino, self).__init__()
  22. print("Rhino.__init__")
  23. config = configparser.ConfigParser()
  24. config.read('config/pico.ini')
  25. self._lang = "de"
  26. if "lang" in config["global"]:
  27. self._lang = config["global"]["lang"]
  28. self._os = platform.system().lower()
  29. if "ApiKey" in config["PicoVoice"]:
  30. print(" - Api Key: " + config["PicoVoice"]["ApiKey"])
  31. self._access_key = config["PicoVoice"]["ApiKey"]
  32. print(" - Library: " + pvrhino.LIBRARY_PATH)
  33. self._library_path = pvrhino.LIBRARY_PATH
  34. #if "Model" in config["PicoVoice"]:
  35. # print(" - Model: " + config["PicoVoice"]["Model"])
  36. # self._model_path = config["PicoVoice"]["Model"]
  37. self._model_path = 'ressources/model/porcupine/' + config["Rhino"]["model"]
  38. #self._context_path = context_path
  39. self._require_endpoint = None
  40. if "InputDeviceIndex" in config["Hardware"]:
  41. print(" - Audio Device Index: " + config["Hardware"]["InputDeviceIndex"])
  42. self._audio_device_index = int(config["Hardware"]["InputDeviceIndex"])
  43. else:
  44. self._audio_device_index = None
  45. print(" - Output Path")
  46. self._output_path = None
  47. def run(self, contextFile, intentHandler, startListening = None, stopListening = None):
  48. """
  49. Creates an input audio stream, instantiates an instance of Rhino object, and infers the intent from spoken
  50. commands.
  51. """
  52. print("Rhino.run("+contextFile+", func)")
  53. rhino = None
  54. recorder = None
  55. wav_file = None
  56. # Find Context File
  57. bFoundContextFile = False
  58. for iMajor in range(4,0,-1):
  59. for iMinor in range(10,-1,-1):
  60. for iRev in range(10,-1,-1):
  61. cf = "ressources/models/context/" + contextFile + "_" + self._lang + "_" + self._os + "_v" + str(iMajor) + "_" + str(iMinor) + "_" + str(iRev) + ".rhn"
  62. print("Try: "+cf)
  63. if os.path.isfile(cf):
  64. print(" FOUND")
  65. bFoundContextFile = True
  66. break
  67. if bFoundContextFile == True:
  68. break
  69. if bFoundContextFile == True:
  70. break
  71. if bFoundContextFile == True:
  72. print(" - Context File Path: " + cf)
  73. else:
  74. print(" - Context File not found, use Version 2.0.0")
  75. cf = "ressources/models/context/" + contextFile + "_" + self._lang + "_" + self._os + "_v2_0_0.rhn"
  76. try:
  77. print(" - Create Rhino")
  78. rhino = pvrhino.create(
  79. access_key=self._access_key,
  80. library_path=self._library_path,
  81. model_path=self._model_path,
  82. context_path=cf,
  83. require_endpoint=self._require_endpoint
  84. )
  85. print(" - Create Recorder")
  86. recorder = PvRecorder(device_index=self._audio_device_index, frame_length=rhino.frame_length)
  87. print(" - Start Recorder")
  88. recorder.start()
  89. if self._output_path is not None:
  90. wav_file = wave.open(self._output_path, "w")
  91. wav_file.setparams((1, 2, 16000, 512, "NONE", "NONE"))
  92. print(rhino.context_info)
  93. print()
  94. print("Using device: '"+recorder.selected_device+"'")
  95. print("Listening...")
  96. print()
  97. bRunning = True
  98. while bRunning:
  99. if startListening is not None:
  100. startListeningResult = startListening({
  101. "library": self._library_path,
  102. "model_path": self._model_path,
  103. "context_path": self._context_path,
  104. "require_endpoint": self._require_endpoint,
  105. "rhino": rhino,
  106. "recorder": recorder,
  107. "wave_file":self._output_path
  108. })
  109. if startListeningResult is not None and startListeningResult == False:
  110. bRunning=False
  111. recorder.stop()
  112. break
  113. pcm = recorder.read()
  114. if wav_file is not None:
  115. wav_file.writeframes(struct.pack("h" * len(pcm), *pcm))
  116. is_finalized = rhino.process(pcm)
  117. if is_finalized:
  118. inference = rhino.get_inference()
  119. recorder.stop()
  120. if inference.is_understood:
  121. print('{')
  122. print(" intent : '"+inference.intent+"'")
  123. print(' slots : {')
  124. for slot, value in inference.slots.items():
  125. print(" "+slot+" : '"+value+"'")
  126. print(' }')
  127. print('}\n')
  128. if intentHandler is not None:
  129. res = intentHandler(inference)
  130. if res==False and res != None:
  131. bRunning = False
  132. else:
  133. recorder.start()
  134. else:
  135. print("Didn't understand the command.\n")
  136. bRunning = False
  137. print("Stop listening")
  138. if stopListening is not None:
  139. stopListening()
  140. except pvrhino.RhinoInvalidArgumentError as e:
  141. print("One or more arguments provided to Rhino is invalid: {\n" +
  142. "\t"+self._access_key+"\n" +
  143. "\t"+self._library_path+"\n" +
  144. "\t"+self._model_path+"\n" +
  145. "\t"+cf+"\n" +
  146. "\t"+str(self._require_endpoint)+"\n" +
  147. "}")
  148. print("If all other arguments seem valid, ensure that '"+self._access_key+"' is a valid AccessKey")
  149. Voice.getInstance().Say("Ausnahmefehler in Rhino Argument")
  150. raise e
  151. except pvrhino.RhinoActivationError as e:
  152. print("AccessKey activation error")
  153. raise e
  154. except pvrhino.RhinoActivationLimitError as e:
  155. print("AccessKey '"+self._access_key+"' has reached it's temporary device limit")
  156. Voice.getInstance().Say("Ausnahmefehler in Rhino - Begränzung erreicht")
  157. raise e
  158. except pvrhino.RhinoActivationRefusedError as e:
  159. print("AccessKey '"+self._access_key+"' refused")
  160. raise e
  161. except pvrhino.RhinoActivationThrottledError as e:
  162. print("AccessKey '"+self._access_key+"' has been throttled")
  163. Voice.getInstance().Say("Ausnahmefehler in Rhino - Anfragenbegränzung erreicht")
  164. raise e
  165. except pvrhino.RhinoError as e:
  166. print("Failed to initialize Rhino")
  167. Voice.getInstance().Say("Ausnahmefehler in Rhino - Initialisierung fehlgeschlagen")
  168. raise e
  169. except KeyboardInterrupt:
  170. print('Stopping ...')
  171. finally:
  172. if recorder is not None:
  173. recorder.delete()
  174. if rhino is not None:
  175. rhino.delete()
  176. if wav_file is not None:
  177. wav_file.close()
  178. @staticmethod
  179. def formatChar(c:str):
  180. if c=="Ah": return "a"
  181. elif c=="Be": return "b"
  182. elif c=="Zeh": return "c"
  183. elif c=="De": return "d"
  184. elif c=="E": return "e"
  185. elif c=="Ef": return "f"
  186. elif c=="Geh": return "g"
  187. elif c=="H": return "h"
  188. elif c=="Jott": return "j"
  189. elif c=="Ka": return "k"
  190. elif c=="El": return "l"
  191. elif c=="Em": return "m"
  192. elif c=="En": return "n"
  193. elif c=="O": return "o"
  194. elif c=="Pe": return "p"
  195. elif c=="Kuh": return "q"
  196. elif c=="Er": return "r"
  197. elif c=="Es": return "s"
  198. elif c=="Tee": return "t"
  199. elif c=="U": return "u"
  200. elif c=="Fau": return "v"
  201. elif c=="We": return "w"
  202. elif c=="Ix": return "x"
  203. elif c=="Yipsilon": return "y"
  204. elif c=="Zett": return "z"
  205. elif c=="Null": return "0"
  206. elif c=="eins": return "1"
  207. elif c=="zwei": return "2"
  208. elif c=="drei": return "3"
  209. elif c=="vier": return "4"
  210. elif c=="fünf": return "5"
  211. elif c=="sechs": return "6"
  212. elif c=="sieben": return "7"
  213. elif c=="acht": return "8"
  214. elif c=="neun": return "9"
  215. elif c=="komma": return ","
  216. elif c=="punkt": return "."
  217. elif c=="doppelpunkt": return ":"
  218. elif c=="Dollar": return "$"
  219. elif c=="Raute": return "#"
  220. elif c=="Äh": return "ä"
  221. elif c=="Ö": return "ö"
  222. elif c=="Ü": return "ü"
  223. elif c=="Ausrufezeichen": return "!"
  224. elif c=="Und": return "&"
  225. elif c=="Slash": return "/"
  226. elif c=="Backslash": return "\\"
  227. elif c=="Plus": return "+"
  228. elif c=="Minus": return "-"
  229. elif c=="Unterstrich": return "_"
  230. elif c=="Fu": return "Foo"
  231. else: return c.lower()