Эх сурвалжийг харах

allow STT mother class to read an audo file if provided by the child STT engine class

nico 8 жил өмнө
parent
commit
359d5efa6c

+ 6 - 5
Docs/contributing/contribute_stt.md

@@ -37,14 +37,15 @@ The constructor has a __**kwargs argument__ which is corresponding to the Dict o
 1. Attach the incoming callback to the self.main_controller_callback attribute. This callback come from the main controller and will receive the text at the end of the process
 1. Obtain audio from the microphone in the constructor. (Note : we mostly use the [speech_recognition library](https://pypi.python.org/pypi/SpeechRecognition/))
 1. Set your callback method into the mother class with `self.set_callback(self.google_callback)`. This callback is the one which will process the audio into a text.
-1. Use self.start_listening() from the mother class to get an audio. Once caught, the mother class will give the audio stream to the callback you've set before.
-1. The callback method must implement two arguments: recognizer and audio. The audio argument contains the stream caught by the microphone
+1. Use self.start_processing() from the mother class to get an audio from the microphone or read the audio file path if provided. The mother class will give the audio stream to the callback you've set before.
+1. The callback method must implement two arguments: recognizer and audio. The audio argument contains the stream caught by the microphone or read from an audio file path
 1. Do magic stuff with the audio in order to get a string that contains the translated text
 1. Once you get the text, let give it to the main_controller_callback method received in the constructor by calling it with the text string as argument `self.main_controller_callback(audio_to_text)`
 
     ```python
     def __init__(self, callback=None, **kwargs):
-        OrderListener.__init__(self)
+        # give the audio file path to process directly to the mother class if exist
+        SpeechRecognition.__init__(self, kwargs.get('audio_file_path', None))
         # here is the main controller callback. We will return the text at the end of the process
         self.main_controller_callback = callback
         
@@ -52,8 +53,8 @@ The constructor has a __**kwargs argument__ which is corresponding to the Dict o
         
         #  give our callback   
         self.set_callback(self.my_callback)
-        # start the microphone to capture an audio
-        self.start_listening()
+        # start processing, record a sample from the microphone if no audio file path provided, else read the file
+        self.start_processing()
         
         def my_callback((self, recognizer, audio):
             # ---------------------------------------------

+ 22 - 11
kalliope/stt/Utils.py

@@ -12,7 +12,7 @@ logger = logging.getLogger("kalliope")
 
 class SpeechRecognition(Thread):
 
-    def __init__(self):
+    def __init__(self, audio_file=None):
         """
         Thread used to caught n audio from the microphone and pass it to a callback method
         """
@@ -22,22 +22,33 @@ class SpeechRecognition(Thread):
         self.callback = None
         self.stop_thread = None
         self.kill_yourself = False
-        with self.microphone as source:
-            # we only need to calibrate once, before we start listening
-            self.recognizer.adjust_for_ambient_noise(source)
+        self.audio_stream = None
+
+        if audio_file is None:
+            # audio file not set, we need to capture a sample from the microphone
+            with self.microphone as source:
+                # we only need to calibrate once, before we start listening
+                self.recognizer.adjust_for_ambient_noise(source)
+        else:
+            # audio file provided
+            with sr.AudioFile(audio_file) as source:
+                self.audio_stream = self.recognizer.record(source)  # read the entire audio file
 
     def run(self):
         """
         Start the thread that listen the microphone and then give the audio to the callback method
         """
-        Utils.print_info("Say something!")
-        self.stop_thread = self.recognizer.listen_in_background(self.microphone, self.callback)
-        while not self.kill_yourself:
-            sleep(0.1)
-        logger.debug("kill the speech recognition process")
-        self.stop_thread()
+        if self.audio_stream is None:
+            Utils.print_info("Say something!")
+            self.stop_thread = self.recognizer.listen_in_background(self.microphone, self.callback)
+            while not self.kill_yourself:
+                sleep(0.1)
+            logger.debug("kill the speech recognition process")
+            self.stop_thread()
+        else:
+            self.callback(self.recognizer, self.audio_stream)
 
-    def start_listening(self):
+    def start_processing(self):
         """
         A method to start the thread
         """

+ 4 - 2
kalliope/stt/apiai/apiai.py

@@ -12,7 +12,8 @@ class Apiai(SpeechRecognition):
         :param callback: The callback function to call to send the text
         :param kwargs:
         """
-        SpeechRecognition.__init__(self)
+        # give the audio file path to process directly to the mother class if exist
+        SpeechRecognition.__init__(self, kwargs.get('audio_file_path', None))
 
         # callback function to call after the translation speech/tex
         self.main_controller_callback = callback
@@ -23,7 +24,8 @@ class Apiai(SpeechRecognition):
 
         # start listening in the background
         self.set_callback(self.apiai_callback)
-        self.start_listening()
+        # start processing, record a sample from the microphone if no audio file path provided, else read the file
+        self.start_processing()
 
     def apiai_callback(self, recognizer, audio):
         """

+ 4 - 2
kalliope/stt/bing/bing.py

@@ -12,7 +12,8 @@ class Bing(SpeechRecognition):
         :param callback: The callback function to call to send the text
         :param kwargs:
         """
-        SpeechRecognition.__init__(self)
+        # give the audio file path to process directly to the mother class if exist
+        SpeechRecognition.__init__(self, kwargs.get('audio_file_path', None))
 
         # callback function to call after the translation speech/tex
         self.main_controller_callback = callback
@@ -22,7 +23,8 @@ class Bing(SpeechRecognition):
 
         # start listening in the background
         self.set_callback(self.bing_callback)
-        self.start_listening()
+        # start processing, record a sample from the microphone if no audio file path provided, else read the file
+        self.start_processing()
 
     def bing_callback(self, recognizer, audio):
         """

+ 4 - 2
kalliope/stt/cmusphinx/cmusphinx.py

@@ -12,14 +12,16 @@ class Cmusphinx(SpeechRecognition):
         :param callback: The callback function to call to send the text
         :param kwargs:
         """
-        SpeechRecognition.__init__(self)
+        # give the audio file path to process directly to the mother class if exist
+        SpeechRecognition.__init__(self, kwargs.get('audio_file_path', None))
 
         # callback function to call after the translation speech/tex
         self.main_controller_callback = callback
 
         # start listening in the background
         self.set_callback(self.sphinx_callback)
-        self.start_listening()
+        # start processing, record a sample from the microphone if no audio file path provided, else read the file
+        self.start_processing()
 
     def sphinx_callback(self, recognizer, audio):
         """

+ 5 - 3
kalliope/stt/google/google.py

@@ -14,7 +14,8 @@ class Google(SpeechRecognition):
         :param callback: The callback function to call to send the text
         :param kwargs:
         """
-        SpeechRecognition.__init__(self)
+        # give the audio file path to process directly to the mother class if exist
+        SpeechRecognition.__init__(self, kwargs.get('audio_file_path', None))
 
         # callback function to call after the translation speech/tex
         self.main_controller_callback = callback
@@ -22,9 +23,10 @@ class Google(SpeechRecognition):
         self.language = kwargs.get('language', "en-US")
         self.show_all = kwargs.get('show_all', False)
 
-        # start listening in the background
+        # set the callback that will process the audio stream
         self.set_callback(self.google_callback)
-        self.start_listening()
+        # start processing, record a sample from the microphone if no audio file path provided, else read the file
+        self.start_processing()
 
     def google_callback(self, recognizer, audio):
         """

+ 4 - 2
kalliope/stt/houndify/houndify.py

@@ -12,7 +12,8 @@ class Houndify(SpeechRecognition):
         :param callback: The callback function to call to send the text
         :param kwargs:
         """
-        SpeechRecognition.__init__(self)
+        # give the audio file path to process directly to the mother class if exist
+        SpeechRecognition.__init__(self, kwargs.get('audio_file_path', None))
 
         # callback function to call after the translation speech/tex
         self.main_controller_callback = callback
@@ -24,7 +25,8 @@ class Houndify(SpeechRecognition):
 
         # start listening in the background
         self.set_callback(self.houndify_callback)
-        self.start_listening()
+        # start processing, record a sample from the microphone if no audio file path provided, else read the file
+        self.start_processing()
 
     def houndify_callback(self, recognizer, audio):
         """

+ 4 - 2
kalliope/stt/wit/wit.py

@@ -12,7 +12,8 @@ class Wit(SpeechRecognition):
         :param callback: The callback function to call to send the text
         :param kwargs:
         """
-        SpeechRecognition.__init__(self)
+        # give the audio file path to process directly to the mother class if exist
+        SpeechRecognition.__init__(self, kwargs.get('audio_file_path', None))
 
         # callback function to call after the translation speech/tex
         self.main_controller_callback = callback
@@ -21,7 +22,8 @@ class Wit(SpeechRecognition):
 
         # start listening in the background
         self.set_callback(self.wit_callback)
-        self.start_listening()
+        # start processing, record a sample from the microphone if no audio file path provided, else read the file
+        self.start_processing()
 
     def wit_callback(self, recognizer, audio):
         try: