Go to the documentation of this file.00001
00002
00003 import urllib2
00004 import json
00005 import base64
00006 import socket
00007 import traceback
00008 import logging
00009
00010
00011
00012 from rospeex_core.validators import accepts
00013 from rospeex_core.validators import check_language
00014 from rospeex_core import exceptions as ext
00015 from rospeex_core.ss.base import IClient
00016
00017
00018 logger = logging.getLogger(__name__)
00019
00020
00021 class Client(IClient):
00022 """ SpeechSynthesisCient_NICT class """
00023 URL = 'http://rospeex.nict.go.jp/nauth_json/jsServices/VoiceTraSS'
00024 FORMAT = 'x-wav'
00025 LANGUAGES = ['ja', 'en', 'zh', 'ko']
00026 VOICEFONT_DICT = {
00027 'ja': ['F128', 'F117', '*'],
00028 'en': ['EF007', '*'],
00029 'zh': ['CJF101', '*'],
00030 'ko': ['KF001', '*']
00031 }
00032
00033 def __init__(self):
00034 """ initialize function """
00035 pass
00036
00037 @accepts(message=basestring, language=str, voice_font=str, timeout=int)
00038 def request(
00039 self,
00040 message,
00041 language='ja',
00042 voice_font='*',
00043 timeout=socket._GLOBAL_DEFAULT_TIMEOUT
00044 ):
00045 """
00046 Send speech synthesis request to server,
00047 and get speech synthesis result.
00048 @param message: message
00049 @type message: str
00050 @param language: speech synthesis language
00051 @type language: str
00052 @param voice_font: taraget voice font
00053 @type voice_font: str
00054 @param timeout: request timeout time (second)
00055 @type timeout: float
00056 @return: voice data (wav format binary)
00057 @rtype: str
00058 @raise InvalidResponseException:
00059 @raise InvalidRequestException: send invalid request.
00060 @raise InvalidResponseException: server error.
00061 @raise RequestTimeoutException: timeout error.
00062 """
00063 check_language(language, self.LANGUAGES)
00064 self._check_voice_font(voice_font, language)
00065
00066
00067 decorded_data = self._request_tts(
00068 message,
00069 language,
00070 voice_font,
00071 timeout
00072 )
00073
00074
00075 ret_code = self._check_decorded_data(decorded_data)
00076
00077
00078 voice = None
00079 if not ret_code:
00080 if decorded_data['error']['faultCode'] == 'Server.userException':
00081 msg = 'the format is not supported.'
00082 raise ext.InvalidResponseException(msg)
00083 msg = 'server response error. msg:%s' % decorded_data['error']
00084 raise ext.InvalidResponseException(msg)
00085 else:
00086 voice = base64.b64decode(decorded_data['result']['audio'])
00087 return voice
00088
00089 def _check_voice_font(self, voice_font, language):
00090 """ check voice font
00091 @param voice_font:
00092 @type voice_font:
00093 @param language:
00094 @type language:
00095 @raise ParameterException
00096 """
00097 if voice_font not in self.VOICEFONT_DICT[language]:
00098 msg = 'invalid voice font [{voice_font}].'\
00099 ' Expect: {voice_font_list}'.format(
00100 voice_font=voice_font,
00101 voice_font_list=str(self.VOICEFONT_DICT[language])
00102 )
00103 raise ext.ParameterException(msg)
00104
00105 def _check_decorded_data(self, decorded_data):
00106 """
00107 @param decorded_data:
00108 @type decorded_data:
00109 @return: True to success / False to failture
00110 @rtype: bool
00111 @raise InvalidResponseException:
00112 """
00113
00114 if not decorded_data:
00115 msg = 'invalid server response. response has no data.'
00116 raise ext.InvalidResponseException(msg)
00117
00118 ret_code = False
00119 if 'result' in decorded_data:
00120 if decorded_data['result'] is not None:
00121 if 'audio' in decorded_data['result']:
00122 ret_code = True
00123 else:
00124 msg = 'invalid server response.'\
00125 ' response has no audio data.'
00126 raise ext.InvalidResponseException(msg)
00127
00128
00129 if 'error' in decorded_data:
00130 if decorded_data['error'] is not None:
00131 if 'faultCode' in decorded_data['error']:
00132 ret_code = False
00133 else:
00134 msg = 'invalid server response. response has no faultcode.'
00135 raise ext.InvalidResponseException(msg)
00136
00137 return ret_code
00138
00139 def _request_tts(self, message, language, voice_font, timeout):
00140 """
00141 request tts to NICT server
00142 @param message: message
00143 @type message: str
00144 @param language: speech synthesis language
00145 @type language: str
00146 @param voice_font: taraget voice font
00147 @type voice_font: str
00148 @param timeout: request timeout time (second)
00149 @type timeout: float
00150 @return: voice data (wav format binary)
00151 @rtype: str
00152 @raise InvalidRequestException: send invalid request.
00153 @raise InvalidResponseException: server error.
00154 @raise RequestTimeoutException: timeout error.
00155 """
00156
00157 data = {
00158 'method': 'speak',
00159 'params': [
00160 '1.1',
00161 {
00162 'language': language,
00163 'text': message,
00164 'voiceType': voice_font,
00165 'audioType': 'audio/%s' % self.FORMAT,
00166 'applicationType': 'rospeex'
00167 }
00168 ]
00169 }
00170
00171
00172 decorded_data = None
00173 request = urllib2.Request(self.URL)
00174 request.add_header('Content-Type', 'application/json')
00175
00176
00177 try:
00178 response = urllib2.urlopen(
00179 request,
00180 json.dumps(data),
00181 timeout=timeout
00182 )
00183 decorded_data = json.loads(response.read())
00184
00185 except urllib2.URLError as err:
00186 if isinstance(err.reason, socket.timeout):
00187 msg = 'request time out. Exception: %s' % str(err)
00188 raise ext.RequestTimeoutException(msg)
00189
00190 msg = 'request url error. Exception: %s' % str(err)
00191 raise ext.InvalidRequestException(msg)
00192
00193 except urllib2.HTTPError as err:
00194 msg = 'http error. %s Exception:%s' % (err.code, err.msg)
00195 raise ext.InvalidResponseException(msg)
00196
00197 except socket.timeout as err:
00198 msg = 'request time out. Exception: %s' % str(err)
00199 raise ext.RequestTimeoutException(msg)
00200
00201 except:
00202 msg = 'unknown exception. Traceback: %s' % traceback.format_exc()
00203 raise ext.SpeechSynthesisException(msg)
00204
00205 return decorded_data