def recognition_callback(self, words, rule, words_are_dictation_mask): try: # Prepare the words and rule names for the element parsers rule_names = (rule.name,) + (('dgndictation',) if any(words_are_dictation_mask) else ()) words_rules = tuple((word, 0 if not is_dictation else 1) for (word, is_dictation) in zip(words, words_are_dictation_mask)) # Attempt to parse the recognition func = getattr(self.grammar, "process_recognition", None) if func: if not func(words): return state = State(words_rules, rule_names, self.engine) state.initialize_decoding() for result in rule.decode(state): if state.finished(): root = state.build_parse_tree() self.engine._recognition_observer_manager.notify_recognition(words, rule, root) with debug_timer(self.engine._log.debug, "rule execution time"): rule.process_recognition(root) self.engine._recognition_observer_manager.notify_post_recognition(words, rule, root) return except Exception as e: self.engine._log.error("Grammar %s: exception: %s" % (self.grammar._name, e), exc_info=True) # If this point is reached, then the recognition was not processed successfully self.engine._log.error("Grammar %s: failed to decode rule %s recognition %r." % (self.grammar._name, rule.name, words))
def recognition_callback(self, recognition): words = recognition.words rule = recognition.kaldi_rule.parent_rule words_are_dictation_mask = recognition.words_are_dictation_mask try: assert (rule.active and rule.exported ), "Kaldi engine should only ever return the correct rule" # Prepare the words and rule names for the element parsers rule_names = (rule.name, ) + ( ('dgndictation', ) if any(words_are_dictation_mask) else ()) words_rules = tuple( (word, 0 if not is_dictation else 1) for (word, is_dictation) in zip(words, words_are_dictation_mask)) # Attempt to parse the recognition func = getattr(self.grammar, "process_recognition", None) if func: if not self._process_grammar_callback( func, words=words, results=recognition): # Return early if the method didn't return True or equiv. return state = State(words_rules, rule_names, self.engine) state.initialize_decoding() for result in rule.decode(state): if state.finished(): root = state.build_parse_tree() notify_args = (words, rule, root, recognition) self.recobs_manager.notify_recognition(*notify_args) with debug_timer(self.engine._log.debug, "rule execution time"): rule.process_recognition(root) self.recobs_manager.notify_post_recognition(*notify_args) return except Exception as e: self.engine._log.error("Grammar %s: exception: %s" % (self.grammar._name, e), exc_info=True) # If this point is reached, then the recognition was not processed successfully self.engine._log.error( "Grammar %s: failed to decode rule %s recognition %r." % (self.grammar._name, rule.name, words))
def recognition_callback(self, StreamNumber, StreamPosition, RecognitionType, Result): try: newResult = Dispatch(Result) phrase_info = newResult.PhraseInfo rule_name = phrase_info.Rule.Name #--------------------------------------------------------------- # Build a list of rule names for each element. # First populate it with the top level rule name. element = phrase_info.Rule name = element.Name start = element.FirstElement count = element.NumberOfElements rule_names = [name] * count # Walk the tree of child rules and put their names in the list. stack = [collection_iter(phrase_info.Rule.Children)] while stack: try: element = next(stack[-1]) except StopIteration: stack.pop() continue name = element.Name start = element.FirstElement count = element.NumberOfElements rule_names[start:start + count] = [name] * count if element.Children: stack.append(collection_iter(element.Children)) #--------------------------------------------------------------- # Prepare the words and rule names for the element parsers. replacements = [False] * len(rule_names) if phrase_info.Replacements: for replacement in collection_iter(phrase_info.Replacements): begin = replacement.FirstElement end = begin + replacement.NumberOfElements replacements[begin] = replacement.Text for index in range(begin + 1, end): replacements[index] = True results = [] rule_set = list(set(rule_names)) elements = phrase_info.Elements for index in range(len(rule_names)): element = elements.Item(index) rule_id = rule_set.index(rule_names[index]) # Map dictation rule IDs to 1M so that dragonfly recognizes # the words as dictation. if rule_names[index] == "dgndictation": rule_id = 1000000 replacement = replacements[index] info = [ element.LexicalForm, rule_id, element.DisplayText, element.DisplayAttributes, replacement ] results.append(info) #--------------------------------------------------------------- # Retain audio # Only write audio data and metadata if the directory exists. retain_dir = self.engine._retain_dir if retain_dir and not os.path.isdir(retain_dir): self.engine._log.warning( "Audio was not retained because '%s' was not a " "directory" % retain_dir) elif retain_dir: try: file_stream = Dispatch("SAPI.SpFileStream") # Note: application can also retrieve smaller portions # of the audio stream by specifying a starting phrase # element and phrase element length. audio_stream = newResult.Audio() # Make sure we have audio data, which we wouldn't from a # mimic or if the retain flag wasn't set above. if audio_stream: # Write audio data. file_stream.Format = audio_stream.Format now = datetime.now() filename = ("retain_%s.wav" % now.strftime("%Y-%m-%d_%H-%M-%S_%f")) wav_path = os.path.join(retain_dir, filename) flags = constants.SSFMCreateForWrite file_stream.Open(wav_path, flags) try: file_stream.Write(audio_stream.GetData()) finally: file_stream.Close() # Write metadata words = ' '.join([r[2] for r in results]) audio_length = int(newResult.Times.Length) / 1e7 tsv_path = os.path.join(retain_dir, "retain.tsv") with open(tsv_path, "a") as tsv_file: tsv_file.write('\t'.join([ filename, str(audio_length), self.grammar.name, rule_name, words ]) + '\n') except: self.engine._log.exception("Exception retaining audio") #--------------------------------------------------------------- # Attempt to parse the recognition. func = getattr(self.grammar, "process_recognition", None) words = tuple([r[0] for r in results]) if func: if not self._process_grammar_callback( func, words=words, results=newResult): return s = State(results, rule_set, self.engine) for r in self.grammar.rules: if not (r.active and r.exported): continue s.initialize_decoding() for result in r.decode(s): if s.finished(): # Notify recognition observers, then process the # rule. root = s.build_parse_tree() notify_args = (words, r, root, newResult) self.recobs_manager.notify_recognition(*notify_args) r.process_recognition(root) self.recobs_manager.notify_post_recognition( *notify_args) return except Exception as e: Sapi5Engine._log.error("Grammar %s: exception: %s" % (self.grammar._name, e), exc_info=True) #------------------------------------------------------------------- # If this point is reached, then the recognition was not # processed successfully.. self.engine._log.error("Grammar %s: failed to decode" " recognition %r." % (self.grammar._name, [r[0] for r in results]))