Somewhat fancy voice command recognition software
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Blather.py 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #!/usr/bin/env python2
  2. # -- this code is licensed GPLv3
  3. # Copyright 2013 Jezra
  4. import sys
  5. import signal
  6. import gobject
  7. import os.path
  8. import subprocess
  9. from optparse import OptionParser
  10. try:
  11. import yaml
  12. except:
  13. print "YAML is not supported. ~/.config/blather/options.yaml will not function"
  14. #where are the files?
  15. conf_dir = os.path.expanduser("~/.config/blather")
  16. lang_dir = os.path.join(conf_dir, "language")
  17. command_file = os.path.join(conf_dir, "commands.conf")
  18. strings_file = os.path.join(conf_dir, "sentences.corpus")
  19. history_file = os.path.join(conf_dir, "blather.history")
  20. opt_file = os.path.join(conf_dir, "options.yaml")
  21. lang_file = os.path.join(lang_dir,'lm')
  22. dic_file = os.path.join(lang_dir,'dic')
  23. #make the lang_dir if it doesn't exist
  24. if not os.path.exists(lang_dir):
  25. os.makedirs(lang_dir)
  26. class Blather:
  27. def __init__(self, opts):
  28. #import the recognizer so Gst doesn't clobber our -h
  29. from Recognizer import Recognizer
  30. self.ui = None
  31. self.options = {}
  32. ui_continuous_listen = False
  33. self.continuous_listen = False
  34. self.commands = {}
  35. #read the commands
  36. self.read_commands()
  37. #load the options file
  38. self.load_options()
  39. #merge the opts
  40. for k,v in opts.__dict__.items():
  41. if (not k in self.options) or opts.override:
  42. self.options[k] = v
  43. print "Using Options: ", self.options
  44. if self.options['interface'] != None:
  45. if self.options['interface'] == "q":
  46. from QtUI import UI
  47. elif self.options['interface'] == "g":
  48. from GtkUI import UI
  49. elif self.options['interface'] == "gt":
  50. from GtkTrayUI import UI
  51. else:
  52. print "no GUI defined"
  53. sys.exit()
  54. self.ui = UI(args, self.options['continuous'])
  55. self.ui.connect("command", self.process_command)
  56. #can we load the icon resource?
  57. icon = self.load_resource("icon.png")
  58. if icon:
  59. self.ui.set_icon_active_asset(icon)
  60. #can we load the icon_inactive resource?
  61. icon_inactive = self.load_resource("icon_inactive.png")
  62. if icon_inactive:
  63. self.ui.set_icon_inactive_asset(icon_inactive)
  64. if self.options['history']:
  65. self.history = []
  66. #create the recognizer
  67. self.recognizer = Recognizer(lang_file, dic_file, self.options['microphone'] )
  68. self.recognizer.connect('finished',self.recognizer_finished)
  69. def read_commands(self):
  70. #read the.commands file
  71. file_lines = open(command_file)
  72. strings = open(strings_file, "w")
  73. for line in file_lines:
  74. print line
  75. #trim the white spaces
  76. line = line.strip()
  77. #if the line has length and the first char isn't a hash
  78. if len(line) and line[0]!="#":
  79. #this is a parsible line
  80. (key,value) = line.split(":",1)
  81. print key, value
  82. self.commands[key.strip().lower()] = value.strip()
  83. strings.write( key.strip()+"\n")
  84. #close the strings file
  85. strings.close()
  86. def load_options(self):
  87. #is there an opt file?
  88. try:
  89. opt_fh = open(opt_file)
  90. text = opt_fh.read()
  91. self.options = yaml.load(text)
  92. except:
  93. pass
  94. def log_history(self,text):
  95. if self.options['history']:
  96. self.history.append(text)
  97. if len(self.history) > self.options['history']:
  98. #pop off the first item
  99. self.history.pop(0)
  100. #open and truncate the blather history file
  101. hfile = open(history_file, "w")
  102. for line in self.history:
  103. hfile.write( line+"\n")
  104. #close the file
  105. hfile.close()
  106. def recognizer_finished(self, recognizer, text):
  107. t = text.lower()
  108. #is there a matching command?
  109. if self.commands.has_key( t ):
  110. #run the valid_sentence_command if there is a valid sentence command
  111. if self.options['valid_sentence_command']:
  112. subprocess.call(self.options['valid_sentence_command'], shell=True)
  113. cmd = self.commands[t]
  114. print cmd
  115. subprocess.call(cmd, shell=True)
  116. self.log_history(text)
  117. else:
  118. #run the invalid_sentence_command if there is a valid sentence command
  119. if self.options['invalid_sentence_command']:
  120. subprocess.call(self.options['invalid_sentence_command'], shell=True)
  121. print "no matching command %s" %(t)
  122. #if there is a UI and we are not continuous listen
  123. if self.ui:
  124. if not self.continuous_listen:
  125. #stop listening
  126. self.recognizer.pause()
  127. #let the UI know that there is a finish
  128. self.ui.finished(t)
  129. def run(self):
  130. if self.ui:
  131. self.ui.run()
  132. else:
  133. blather.recognizer.listen()
  134. def quit(self):
  135. sys.exit()
  136. def process_command(self, UI, command):
  137. print command
  138. if command == "listen":
  139. self.recognizer.listen()
  140. elif command == "stop":
  141. self.recognizer.pause()
  142. elif command == "continuous_listen":
  143. self.continuous_listen = True
  144. self.recognizer.listen()
  145. elif command == "continuous_stop":
  146. self.continuous_listen = False
  147. self.recognizer.pause()
  148. elif command == "quit":
  149. self.quit()
  150. def load_resource(self,string):
  151. local_data = os.path.join(os.path.dirname(__file__), 'data')
  152. paths = ["/usr/share/blather/","/usr/local/share/blather", local_data]
  153. for path in paths:
  154. resource = os.path.join(path, string)
  155. if os.path.exists( resource ):
  156. return resource
  157. #if we get this far, no resource was found
  158. return False
  159. if __name__ == "__main__":
  160. parser = OptionParser()
  161. parser.add_option("-i", "--interface", type="string", dest="interface",
  162. action='store',
  163. help="Interface to use (if any). 'q' for Qt, 'g' for GTK, 'gt' for GTK system tray icon")
  164. parser.add_option("-c", "--continuous",
  165. action="store_true", dest="continuous", default=False,
  166. help="starts interface with 'continuous' listen enabled")
  167. parser.add_option("-o", "--override",
  168. action="store_true", dest="override", default=False,
  169. help="override config file with command line options")
  170. parser.add_option("-H", "--history", type="int",
  171. action="store", dest="history",
  172. help="number of commands to store in history file")
  173. parser.add_option("-m", "--microphone", type="int",
  174. action="store", dest="microphone", default=None,
  175. help="Audio input card to use (if other than system default)")
  176. parser.add_option("--valid-sentence-command", type="string", dest="valid_sentence_command",
  177. action='store',
  178. help="command to run when a valid sentence is detected")
  179. parser.add_option( "--invalid-sentence-command", type="string", dest="invalid_sentence_command",
  180. action='store',
  181. help="command to run when an invalid sentence is detected")
  182. (options, args) = parser.parse_args()
  183. #make our blather object
  184. blather = Blather(options)
  185. #init gobject threads
  186. gobject.threads_init()
  187. #we want a main loop
  188. main_loop = gobject.MainLoop()
  189. #handle sigint
  190. signal.signal(signal.SIGINT, signal.SIG_DFL)
  191. #run the blather
  192. blather.run()
  193. #start the main loop
  194. try:
  195. main_loop.run()
  196. except:
  197. print "time to quit"
  198. main_loop.quit()
  199. sys.exit()