sync_client.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding: utf-8 -*-
00003 
00004 # import python libraries
00005 import urllib
00006 import urllib2
00007 import json
00008 import socket
00009 import traceback
00010 import ssl
00011 
00012 # import local libraries
00013 import rospeex_core.exceptions as ext
00014 from rospeex_core import logging_util
00015 from rospeex_core.validators import accepts, check_wave_data, check_language
00016 from rospeex_core.sr.base.client import IClient
00017 from rospeex_core.sr.nict import Client
00018 
00019 # create logger
00020 logger = logging_util.get_logger(__name__)
00021 
00022 
00023 class SyncClient(IClient):
00024     """ SpeechRecognitionClient_Google class """
00025     AUDIO_LENGTH = 16000
00026     FRAMERATE = 16000
00027     CHANNELS = 1
00028     SAMPWIDTH = 2
00029     LANGUAGES = ['ja', 'en']
00030     URL = 'https://www.google.com/speech-api/v2/recognize?'
00031 
00032     def __init__(self, google_api_key=None, *args, **kwargs):
00033         """ initialize function """
00034         self._api_key = google_api_key
00035 
00036     @accepts(data=str, languate=str, timeout=int)
00037     def request(
00038         self,
00039         data,
00040         language='ja',
00041         timeout=socket._GLOBAL_DEFAULT_TIMEOUT
00042     ):
00043         """ send speech recognition request to server
00044         @param data: speech binary data
00045         @type  data: str
00046         @param language: speech data language
00047         @type  language: str
00048         @param timeout: time out time[ms]
00049         @type  timeout: int
00050         """
00051         check_wave_data(
00052             data,
00053             self.FRAMERATE,
00054             self.CHANNELS,
00055             self.SAMPWIDTH,
00056             self.AUDIO_LENGTH
00057         )
00058         check_language(language, self.LANGUAGES)
00059         self._check_api_key()
00060 
00061         # speech recognition by nict engine
00062         nict_result = ''
00063         try:
00064             client = Client()
00065             nict_result = client.request(data, language, 10)
00066 
00067         except Exception:
00068             pass
00069 
00070         # speech recognition by google engine
00071         result_text = None
00072         try:
00073             result_text = self._request_google_server(
00074                 self._api_key,
00075                 language,
00076                 data,
00077                 timeout
00078             )
00079 
00080         except ext.InvalidResponseException:
00081             logger.info(
00082                 'google speech api connection failed. thus use nict api.'
00083             )
00084             result_text = nict_result
00085 
00086         return result_text
00087 
00088     def _check_api_key(self):
00089         """ check api key """
00090         if not self._api_key:
00091             msg = 'argment failed. if you want to use google engine,'\
00092                   'you MUST set api key for google speech api v2.'
00093             raise ext.ParameterException(msg)
00094 
00095     def _request_google_server(self, access_key, language, data, timeout):
00096         """ speech recognition request to google server (use speech api v2)
00097         @param access_key: google speech api key
00098         @type  access_key: str
00099         @param language: speech data language
00100         @type  language: str
00101         @param data: speech binary data
00102         @type  data: str
00103         @param timeout: timeout time [s]
00104         @type  timeout: int
00105         @raise SpeechRecognitionException:
00106         """
00107         try:
00108             # リクエストを作成し、googleにデータを送信する
00109             req = self._create_request(access_key, language, data)
00110             res = urllib2.urlopen(req, timeout=timeout)
00111             res_read = res.read()
00112             google_result_text = self._process_data(res_read)
00113 
00114         except urllib2.URLError as err:
00115             if isinstance(err.reason, socket.timeout):
00116                 raise ext.RequestTimeoutException(
00117                     'request time out. Exception: %s',
00118                     str(err)
00119                 )
00120             raise ext.InvalidRequestException(
00121                 'request url error. Exception:%s',
00122                 str(err)
00123             )
00124 
00125         except urllib2.HTTPError as err:
00126             raise ext.InvalidResponseException(
00127                 'http error. %s Exception:%s',
00128                 err.code,
00129                 err.msg
00130             )
00131 
00132         except (ssl.SSLError, socket.timeout) as err:
00133             raise ext.RequestTimeoutException(str(err))
00134 
00135         except Exception as err:
00136             msg = 'unknown exception. Traceback: {}'.format(
00137                 traceback.format_exc()
00138             )
00139             raise ext.SpeechRecognitionException(msg)
00140 
00141         return google_result_text
00142 
00143     def _create_request(self, access_key, language, data):
00144         """ create http request data for google speech api v2
00145         @param access_key: google speech api key
00146         @type  access_key: str
00147         @param language: speech data language
00148         @type  language: str
00149         @param data: speech binary data
00150         @type  data: str
00151         """
00152         header = {'Content-Type': 'audio/l16; rate=16000;'}
00153         values = {
00154             'output': 'json',
00155             'lang': language,
00156             'key': access_key
00157         }
00158         url_req = self.URL + urllib.urlencode(values)
00159         request = urllib2.Request(url_req, data, header)
00160         return request
00161 
00162     def _process_data(self, input_str):
00163         result_list = input_str.split('\n')
00164         json_result_list = []
00165         for result in result_list:
00166             try:
00167                 json_result_list.append(json.loads(result))
00168             except:
00169                 pass
00170 
00171         # データの抽出
00172         result_data = self._extract_result_key_data(json_result_list)
00173         if result_data != '':
00174             result_data = self._extract_alternative_final_key_data(result_data)
00175             result_data = self._extract_final_data(result_data)
00176             result_data = self._extract_transcript_data(result_data)
00177 
00178         # get data
00179         result_text = result_data[0] if len(result_data) else ''
00180         return result_text
00181 
00182     @classmethod
00183     def _extract_result_key_data(cls, input_data):
00184         """ extract result data from server response
00185         @param input_data:
00186         @type  input_data: dict()
00187         """
00188         # 必要なデータを取り出す
00189         result_data = [
00190             result['result'] for result in input_data if 'result' in result
00191         ]
00192         if len(result_data) is 0:
00193             raise ext.InvalidResponseException(
00194                 'result key is not found. Input: %s',
00195                 input_data
00196             )
00197 
00198         result_data = filter(lambda x: len(x), result_data)
00199         if len(result_data) is 0:
00200             return ''
00201 
00202         result_data = reduce(lambda a, b: a+b, result_data)
00203         return result_data
00204 
00205     @classmethod
00206     def _extract_alternative_final_key_data(cls, input_data):
00207         """ extract alternative key data
00208         @param input_data:
00209         @type  input_data: dict()
00210         """
00211         # key=>alternative と key=>final を持つ結果を取得する
00212         result_data = filter(
00213             lambda x: 'alternative' in x and 'final' in x, input_data
00214         )
00215         if len(result_data) is 0:
00216             raise ext.InvalidResponseException(
00217                 'alternative key is not found. Input: %s',
00218                 input_data
00219             )
00220         return result_data
00221 
00222     @classmethod
00223     def _extract_final_data(cls, intput_data):
00224         """ extract final data from server response
00225         @param input_data:
00226         @type  input_data: dict()
00227         """
00228         # result['final'] is True のデータを取得する
00229         result_data = [
00230             result['alternative'] for result in intput_data
00231             if len(result['alternative']) > 0 and result['final'] is True
00232         ]
00233         if len(result_data) is 0:
00234             raise ext.InvalidResponseException(
00235                 'final key is not found. Input: %s',
00236                 intput_data
00237             )
00238         return result_data
00239 
00240     @classmethod
00241     def _extract_transcript_data(cls, input_data):
00242         """ extract transcript data from server response
00243         @param input_data:
00244         @type  input_data: dict()
00245         """
00246         # result['transcript'] を持つデータを取得する
00247         result_data = reduce(lambda a, b: a+b, input_data)
00248         result_data = [
00249             result['transcript'] for result in result_data
00250             if 'transcript' in result
00251         ]
00252         if len(result_data) is 0:
00253             raise ext.InvalidResponseException(
00254                 'transcript key is not found. Input: %s',
00255                 input_data
00256             )
00257         return result_data
00258 
00259     def support_streaming(self):
00260         """
00261         check support streaming
00262         @returns: True for support streaming / False for NOT support streaming
00263         """
00264         return False
00265 
00266     def add_streaming_packet(self, packet_type, packet_data):
00267         """
00268         add streaming packet
00269         @param packet_type:
00270         @type  packet_type: int
00271         @param packet_data:
00272         @param packet_data: str
00273         """
00274         pass
00275 
00276     def register_streaming_cb(self, cb):
00277         """
00278         register streaming result callback
00279         @param cb:
00280         @type cb:
00281         """
00282         pass
00283 
00284     def unregister_streaming_cb(self, cb):
00285         """
00286         unregister streaming result callback
00287         @param cb:
00288         @type cb:
00289         """
00290         pass
00291 
00292     def set_streaming_config(self, language):
00293         """ set streaming config
00294         @param language:
00295         """
00296         pass
00297 
00298     def join(self, timeout=None):
00299         """
00300         join streaming client
00301         @param timeout:
00302         @type timeout:
00303         """
00304         pass


rospeex_core
Author(s): Komei Sugiura
autogenerated on Thu Apr 20 2017 03:08:53