From 6316eed92c5db198bc12c4270d3caa2afb7e4928 Mon Sep 17 00:00:00 2001 From: schneefux Date: Fri, 28 Nov 2014 14:38:41 +0100 Subject: Improve Google STT engine. --- client/stt.py | 54 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'client/stt.py') diff --git a/client/stt.py b/client/stt.py index bdf9d4e..d732d32 100644 --- a/client/stt.py +++ b/client/stt.py @@ -189,6 +189,7 @@ class GoogleSTT(AbstractSTTEngine): if not api_key: raise ValueError("No Google API Key given") self.api_key = api_key + self._logger = logging.getLogger(__name__) self.http = requests.Session() @classmethod @@ -217,33 +218,42 @@ class GoogleSTT(AbstractSTTEngine): wav = wave.open(fp, 'rb') frame_rate = wav.getframerate() wav.close() + data = fp.read() url = (("https://www.google.com/speech-api/v2/recognize?output=json" + "&client=chromium&key=%s&lang=%s&maxresults=6&pfilter=2") % (self.api_key, "en-us")) - - data = fp.read() - + headers = {'content-type': 'audio/l16; rate=%s' % frame_rate} + r = self.http.post(url, data=data, headers=headers) + try: + r.raise_for_status() + except requests.exceptions.HTTPError: + self._logger.critical('Request failed with http status %d', + r.status_code) + if r.status_code == requests.codes['forbidden']: + self._logger.warning('Status 403 is probably caused by an ' + + 'invalid Google API key.') + return [] + r.encoding = 'utf-8' try: - headers = {'Content-type': 'audio/l16; rate=%s' % frame_rate} - response = self.http.post(url, data=data, headers=headers) - response.encoding = 'utf-8' - response_read = response.text - - response_parts = response_read.strip().split("\n") - decoded = json.loads(response_parts[-1]) - if decoded['result']: - texts = [alt['transcript'] for alt in - decoded['result'][0]['alternative']] - if texts: - print "===================" - print "JASPER: " + ', '.join(texts) - print "===================" - return texts - else: - return [] - except Exception: - traceback.print_exc() + # We cannot simply use r.json() because Google sends invalid json + # (i.e. multiple json objects, seperated by newlines. We only want + # the last one). + response = json.loads(list(r.text.strip().split('\n'))[-1]) + if len(response['result']) == 0: + # Response result is empty + raise ValueError('Nothing has been transcribed.') + results = [alt['transcript'] for alt + in response['result'][0]['alternative']] + except ValueError as e: + self._logger.warning('Empty response: %s', e.args[0]) + results = [] + except (KeyError, IndexError): + self._logger.warning('Cannot parse response.', exc_info=True) + results = [] + else: + self._logger.info('Transcribed: %r', results) + return results @classmethod def is_available(cls): -- cgit v1.3.1 From efa98a7154468962bdf82bcf4e54a7002f8c86ac Mon Sep 17 00:00:00 2001 From: schneefux Date: Fri, 28 Nov 2014 15:02:05 +0100 Subject: Remove unused import from client/stt.py --- client/stt.py | 1 - 1 file changed, 1 deletion(-) (limited to 'client/stt.py') diff --git a/client/stt.py b/client/stt.py index d732d32..7626a5d 100644 --- a/client/stt.py +++ b/client/stt.py @@ -1,7 +1,6 @@ #!/usr/bin/env python2 # -*- coding: utf-8-*- import os -import traceback import wave import json import tempfile -- cgit v1.3.1 From 71c4822dabb385b3648226094d9f36cc25fc8859 Mon Sep 17 00:00:00 2001 From: schneefux Date: Sat, 29 Nov 2014 15:53:51 +0100 Subject: Generate google-stt request_url only on api_key/language change and convert results to uppercase --- client/stt.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 10 deletions(-) (limited to 'client/stt.py') diff --git a/client/stt.py b/client/stt.py index 7626a5d..aeaae0b 100644 --- a/client/stt.py +++ b/client/stt.py @@ -5,6 +5,8 @@ import wave import json import tempfile import logging +import urllib +import urlparse from abc import ABCMeta, abstractmethod import requests import yaml @@ -179,17 +181,55 @@ class GoogleSTT(AbstractSTTEngine): SLUG = 'google' - def __init__(self, api_key=None): + def __init__(self, api_key=None, language='en-us'): # FIXME: get init args from config """ Arguments: api_key - the public api key which allows access to Google APIs """ - if not api_key: - raise ValueError("No Google API Key given") - self.api_key = api_key self._logger = logging.getLogger(__name__) - self.http = requests.Session() + self._request_url = None + self._language = None + self._api_key = None + self._http = requests.Session() + self.language = language + self.api_key = api_key + + @property + def request_url(self): + return self._request_url + + @property + def language(self): + return self._language + + @language.setter + def language(self, value): + self._language = value + self._regenerate_request_url() + + @property + def api_key(self): + return self._api_key + + @api_key.setter + def api_key(self, value): + self._api_key = value + self._regenerate_request_url() + + def _regenerate_request_url(self): + if self.api_key and self.language: + query = urllib.urlencode({'output': 'json', + 'client': 'chromium', + 'key': self.api_key, + 'lang': self.language, + 'maxresults': 6, + 'pfilter': 2}) + self._request_url = urlparse.urlunparse( + ('https', 'www.google.com', '/speech-api/v2/recognize', '', + query, '')) + else: + self._request_url = None @classmethod def get_config(cls): @@ -214,16 +254,22 @@ class GoogleSTT(AbstractSTTEngine): audio_file_path -- the path to the .wav file to be transcribed """ + if not self.api_key: + self._logger.critical('API key missing, transcription request ' + + 'aborted.') + return [] + elif not self.language: + self._logger.critical('Language info missing, transcription ' + + 'request aborted.') + return [] + wav = wave.open(fp, 'rb') frame_rate = wav.getframerate() wav.close() data = fp.read() - url = (("https://www.google.com/speech-api/v2/recognize?output=json" + - "&client=chromium&key=%s&lang=%s&maxresults=6&pfilter=2") % - (self.api_key, "en-us")) headers = {'content-type': 'audio/l16; rate=%s' % frame_rate} - r = self.http.post(url, data=data, headers=headers) + r = self._http.post(self.request_url, data=data, headers=headers) try: r.raise_for_status() except requests.exceptions.HTTPError: @@ -238,7 +284,7 @@ class GoogleSTT(AbstractSTTEngine): # We cannot simply use r.json() because Google sends invalid json # (i.e. multiple json objects, seperated by newlines. We only want # the last one). - response = json.loads(list(r.text.strip().split('\n'))[-1]) + response = json.loads(list(r.text.strip().split('\n', 1))[-1]) if len(response['result']) == 0: # Response result is empty raise ValueError('Nothing has been transcribed.') @@ -251,6 +297,8 @@ class GoogleSTT(AbstractSTTEngine): self._logger.warning('Cannot parse response.', exc_info=True) results = [] else: + # Convert all results to uppercase + results = tuple(result.upper() for result in results) self._logger.info('Transcribed: %r', results) return results -- cgit v1.3.1