From 01ac5aa11b07b418b60caa1443e4b87a006d71fd Mon Sep 17 00:00:00 2001 From: schneefux Date: Fri, 2 Jan 2015 10:58:39 +0100 Subject: Added witai-stt-engine to client.stt module This was asked for in a comment at PR #118 --- client/stt.py | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/client/stt.py b/client/stt.py index 86cc83b..9277cb6 100644 --- a/client/stt.py +++ b/client/stt.py @@ -413,6 +413,84 @@ class AttSTT(AbstractSTTEngine): return diagnose.check_network_connection() +class WitAiSTT(AbstractSTTEngine): + """ + Speech-To-Text implementation which relies on the Wit.ai Speech API. + + This implementation requires an Wit.ai Access Token to be present in + profile.yml. Please sign up at https://wit.ai and copy your instance + token, which can be found under Settings in the Wit console to your + profile.yml: + ... + stt_engine: witai + witai-stt: + access_token: ERJKGE86SOMERANDOMTOKEN23471AB + """ + + SLUG = "witai" + + def __init__(self, access_token): + self._logger = logging.getLogger(__name__) + self._token = access_token + + @classmethod + def get_config(cls): + # FIXME: Replace this as soon as we have a config module + config = {} + # Try to get wit.ai Auth token from config + profile_path = jasperpath.config('profile.yml') + if os.path.exists(profile_path): + with open(profile_path, 'r') as f: + profile = yaml.safe_load(f) + if 'witai-stt' in profile: + if 'access_token' in profile['witai-stt']: + config['access_token'] = \ + profile['witai-stt']['access_token'] + return config + + @property + def token(self): + return self._token + + def transcribe(self, fp): + data = fp.read() + headers = {'Authorization': 'Bearer %s' % self.token, + 'accept': 'application/json', + 'Content-Type': 'audio/wav'} + r = requests.post('https://api.wit.ai/speech?v=20140916', + data=data, + headers=headers) + try: + r.raise_for_status() + except requests.exceptions.HTTPError: + self._logger.critical('Request failed with response: %r', + r.text, + exc_info=True) + return [] + except requests.exceptions.RequestException: + self._logger.critical('Request failed.', exc_info=True) + return [] + else: + try: + text = r.json()['_text'] + except ValueError as e: + self._logger.debug('Recognition failed with status: %s', + e.args[0]) + return [] + except KeyError: + self._logger.critical('Cannot parse response.', + exc_info=True) + return [] + else: + transcribed = [text.upper()] + self._logger.info('Transcribed: %r', transcribed) + return transcribed + + @classmethod + def is_available(cls): + return diagnose.check_network_connection() + + def get_engine_by_slug(slug=None): """ Returns: -- cgit v1.3.1 From 3974aea5320d4c11fbb9214bba9e1b26bbdec3d0 Mon Sep 17 00:00:00 2001 From: schneefux Date: Fri, 2 Jan 2015 13:34:25 +0100 Subject: Use latest wit.ai API version in STT engine --- client/stt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/stt.py b/client/stt.py index 9277cb6..5c2faeb 100644 --- a/client/stt.py +++ b/client/stt.py @@ -457,7 +457,7 @@ class WitAiSTT(AbstractSTTEngine): headers = {'Authorization': 'Bearer %s' % self.token, 'accept': 'application/json', 'Content-Type': 'audio/wav'} - r = requests.post('https://api.wit.ai/speech?v=20140916', + r = requests.post('https://api.wit.ai/speech?v=20150101', data=data, headers=headers) try: -- cgit v1.3.1 From 04a7d4c6d0c4aef37c95efa63d10d393b0a4e3b5 Mon Sep 17 00:00:00 2001 From: schneefux Date: Fri, 2 Jan 2015 13:39:45 +0100 Subject: Wit.ai STT code further improved --- client/stt.py | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/client/stt.py b/client/stt.py index 5c2faeb..4298cd2 100644 --- a/client/stt.py +++ b/client/stt.py @@ -431,7 +431,7 @@ class WitAiSTT(AbstractSTTEngine): def __init__(self, access_token): self._logger = logging.getLogger(__name__) - self._token = access_token + self.token = access_token @classmethod def get_config(cls): @@ -452,16 +452,25 @@ class WitAiSTT(AbstractSTTEngine): def token(self): return self._token + @token.setter + def token(self, value): + self._token = value + self._headers = {'Authorization': 'Bearer %s' % self.token, + 'accept': 'application/json', + 'Content-Type': 'audio/wav'} + + @property + def headers(self): + return self._headers + def transcribe(self, fp): data = fp.read() - headers = {'Authorization': 'Bearer %s' % self.token, - 'accept': 'application/json', - 'Content-Type': 'audio/wav'} r = requests.post('https://api.wit.ai/speech?v=20150101', data=data, - headers=headers) + headers=self.headers) try: r.raise_for_status() + text = r.json()['_text'] except requests.exceptions.HTTPError: self._logger.critical('Request failed with response: %r', r.text, @@ -470,21 +479,18 @@ class WitAiSTT(AbstractSTTEngine): except requests.exceptions.RequestException: self._logger.critical('Request failed.', exc_info=True) return [] + except ValueError as e: + self._logger.critical('Cannot parse response: %s', + e.args[0]) + return [] + except KeyError: + self._logger.critical('Cannot parse response.', + exc_info=True) + return [] else: - try: - text = r.json()['_text'] - except ValueError as e: - self._logger.debug('Recognition failed with status: %s', - e.args[0]) - return [] - except KeyError: - self._logger.critical('Cannot parse response.', - exc_info=True) - return [] - else: - transcribed = [text.upper()] - self._logger.info('Transcribed: %r', transcribed) - return transcribed + transcribed = [text.upper()] + self._logger.info('Transcribed: %r', transcribed) + return transcribed @classmethod def is_available(cls): -- cgit v1.3.1