예제 #1
0
def aksk_connect(ak, sk, url, params, http_method, config=None):
    """
        根据url,返回json
    :param ak:  ak
    :param sk:  sk
    :param url: 完整请求url
    :param params:  请求参数, dict
    :param http_method: 请求方法,'POST' or 'GET', 其他会报错
    :param config: SisConfig(), 配置超时和代理
    :return: http返回结果转化为json
    """
    sis_config = config
    if sis_config is None:
        sis_config = SisConfig()
    if not isinstance(sis_config, SisConfig):
        error_msg = 'the param \'config\' in aksk_connect must be SisConfig class'
        logger.error(error_msg)
        raise ClientException(error_msg)
    signed_headers = _get_signed_headers(ak, sk, url, params, http_method)
    time_out = (sis_config.get_connect_timeout(),
                sis_config.get_read_timeout())
    resp = http_utils.http_connect(url, signed_headers, params, http_method,
                                   time_out, sis_config.get_proxy())
    json_result = http_utils.parse_resp(resp)
    if resp is not None:
        resp.close()
    return json_result
예제 #2
0
 def _on_message(ws, message):
     result = json.loads(message)
     _check_result(result)
     result_type = result['resp_type']
     trace_id = result['trace_id']
     if result_type == 'START':
         self._callback.on_start(trace_id)
     elif result_type == 'EVENT':
         event = result['event']
         if event == 'EXCEEDED_AUDIO':
             logger.warn(
                 'the duration of the audio is too long, the rest won\'t be recognized'
             )
             self._status = 'end'
         elif event == 'EXCEEDED_SILENCE':
             logger.error(
                 'silent time is too long, the audio won\'t be recognized'
             )
             self._callback.on_error(
                 'silent time is too long, the audio won\'t be recognized'
             )
             self._status = 'error'
         elif event == 'VOICE_END':
             logger.warn(
                 'detect voice end, the rest won\'t be recognized')
             self._status = 'end'
     elif result_type == 'RESULT':
         self._callback.on_response(result)
     elif result_type == 'END':
         self._status = 'end'
         self._callback.on_end(trace_id)
     else:
         logger.error('%s don\'t belong to any type' % result_type)
예제 #3
0
def _generate_request_proxy(proxy):
    if proxy is None:
        return proxy
    if not isinstance(proxy, list) or (not len(proxy) == 2
                                       and not len(proxy) == 4):
        logger.error(
            'Proxy must be list, the format is [host, port] or [host, port, username, password]'
        )
        raise ClientException(
            'Proxy must be list, the format is [host, port] or [host, port, username, password]'
        )
    proxy_str = str(proxy[0]) + ':' + str(proxy[1])
    if len(proxy) == 2:
        proxy = {
            'http': 'http://' + proxy_str,
            'https': 'https://' + proxy_str
        }
    else:
        proxy = {
            'http':
            'http://' + str(proxy[2]) + ':' + str(proxy[3]) + '@' + proxy_str,
            'https':
            'https://' + str(proxy[2]) + ':' + str(proxy[3]) + '@' + proxy_str
        }
    return proxy
예제 #4
0
def encode_file(file_path):
    if not os.path.exists(file_path):
        logger.error('The Path %s doesn\'t exist' % file_path)
        raise ClientException('The Path %s doesn\'t exist' % file_path)
    with open(file_path, 'rb') as f:
        data = f.read()
        base64_data = str(base64.b64encode(data), 'utf-8')
        return base64_data
예제 #5
0
def get_token(user_name,
              password,
              domain_name,
              region,
              url=None,
              config=SisConfig()):
    """
        获取token
    :param user_name:   用户名
    :param password:    密码
    :param domain_name: 账户名,一般等同用户名
    :param region:      区域,如cn-north-4
    :param url:         请求token的url,可使用默认值
    :param config       配置信息
    :return:            请求的token
    """
    if url is None:
        url = 'https://iam.' + region + '.myhuaweicloud.com/v3/auth/tokens'
    if not isinstance(config, SisConfig):
        error_msg = 'the param \'config\' in token_service must be SisConfig class'
        logger.error(error_msg)
        raise ClientException(error_msg)
    time_out = (config.get_connect_timeout(), config.get_read_timeout())
    proxy = config.get_proxy()
    auth_data = {
        "auth": {
            "identity": {
                "password": {
                    "user": {
                        "name": user_name,
                        "password": password,
                        "domain": {
                            "name": domain_name
                        }
                    }
                },
                "methods": ["password"]
            },
            "scope": {
                "project": {
                    "name": region
                }
            }
        }
    }

    headers = {'Content-Type': 'application/json'}
    req = http_utils.http_connect(url, headers, auth_data, 'POST', time_out,
                                  proxy)
    if 'X-Subject-Token' not in req.headers:
        logger.error('Error occurs in getting token, %s' % req.text)
        raise ClientException('Error occurs in getting token, %s' % req.text)
    token = req.headers['X-Subject-Token']
    return token
예제 #6
0
def generate_scheme_host_uri(url):
    if url.find('//') == -1 or url.find('com') == -1:
        error_msg = '%s is invalid' % url
        logger.error(error_msg)
        raise ClientException(error_msg)
    split1s = url.split('//')
    split2s = split1s[1].split('com')
    scheme = split1s[0] + '//'
    host = split2s[0] + 'com'
    uri = split2s[1]
    return scheme, host, uri
예제 #7
0
 def create(self, request):
     """
         创建热词表
     :param request: 热词表请求
     :return: 热词表id
     """
     if not isinstance(request, HotWordRequest):
         logger.error('the parameter in \'create_hot_word(request)\' should be HotWordRequest class')
         raise ClientException('the parameter in \'create_hot_word(request)\' should be HotWordRequest class')
     url = self._service_endpoint + '/v1/' + self._project_id + '/asr/vocabularies'
     params = request.construct_params()
     result = aksk_service.aksk_connect(self._ak, self._sk, url, params, 'POST', self._sis_config)
     return result
예제 #8
0
 def construct_params(self):
     paras = dict()
     paras['encode_type'] = self._encode_type
     paras['sample_rate'] = self._sample_rate
     if self._data is None and self._url is None:
         logger.error('data and url can\'n be both None')
         raise ClientException('data and url can\'n be both None, you can choose set one parameter')
     if self._data is not None and self._url is not None:
         logger.warn('when data and url are not both None, only data can take effect.')
     if self._data is not None:
         paras['data'] = self._data
     else:
         paras['url'] = self._url
     return paras
예제 #9
0
 def assessment_video(self, request):
     """
         多模态评测接口
     :param request: 多模态评测请求
     :return: 响应结果,返回为json格式
     """
     if not isinstance(request, PaVideoRequest):
         error_msg = 'the parameter in \'assessment_video(request)\' should be PaVideoRequest class'
         logger.error(error_msg)
         raise ClientException(error_msg)
     url = self._service_endpoint + '/v1/' + self._project_id + '/assessment/video'
     params = request.construct_parameter()
     result = aksk_service.aksk_connect(self._ak, self._sk, url, params, 'POST', self._sis_config)
     return result
예제 #10
0
 def get_short_response(self, request):
     """
         一句话识别接口
     :param request: 一句话识别请求AsrCustomShortRequest
     :return: 一句话识别响应结果,返回为json格式
     """
     if not isinstance(request, AsrCustomShortRequest):
         error_msg = 'the parameter in \'get_short_response(request)\' should be AsrCustomShortRequest class'
         logger.error(error_msg)
         raise ClientException(error_msg)
     url = self._service_endpoint + '/v1/' + self._project_id + '/asr/short-audio'
     params = request.construct_params()
     result = aksk_service.aksk_connect(self._ak, self._sk, url, params,
                                        'POST', self._sis_config)
     return result
예제 #11
0
 def _check_result(result):
     result_str = json.dumps(result)
     if 'error_code' in result and 'error_msg' in result:
         logger.error(result_str)
         # 睡眠2s保证关闭前,发送端有充足时间收到关闭请求。
         self._status = 'close'
         self._callback.on_error(result_str)
         time.sleep(2)
         self._ws.close()
         raise ClientException(result_str)
     if 'resp_type' not in result:
         self._status == 'error'
         error_msg = 'result doesn\'t contain key resp, result is %s' % result_str
         logger.error(error_msg)
         self._callback.on_error(error_msg)
         raise ClientException(error_msg)
예제 #12
0
 def get_asr_response(self, request):
     """
         短语音识别接口
     :param request: 短语音识别请求 AsrRequest
     :return: 短语音识别响应,json格式
     """
     if not isinstance(request, AsrRequest):
         logger.error(
             'the parameter in \'get_asr_response(request)\' should be AsrRequest class'
         )
         raise ClientException(
             'the parameter in \'get_asr_response(request)\' should be AsrRequest class'
         )
     url = self._service_endpoint + '/v1.0/voice/asr/sentence'
     params = request.construct_params()
     result = aksk_service.aksk_connect(self._ak, self._sk, url, params,
                                        'POST', self._sis_config)
     return result
예제 #13
0
 def submit_job(self, request):
     """
         录音文件识别,提交任务接口
     :param request: 录音文件识别请求
     :return: job_id
     """
     if not isinstance(request, AsrCustomLongRequest):
         error_msg = 'the parameter in \'submit_job(request)\' should be AsrCustomLongRequest class'
         logger.error(error_msg)
         raise ClientException(error_msg)
     url = self._service_endpoint + '/v1/' + self._project_id + '/asr/transcriber/jobs'
     params = request.construct_parameter()
     result = aksk_service.aksk_connect(self._ak, self._sk, url, params,
                                        'POST', self._sis_config)
     if 'job_id' not in result:
         error_msg = 'The result of long audio transcription doesn\'t contain key job_id, result is ' % result
         logger.error(error_msg)
         raise ClientException(error_msg)
     return result['job_id']
예제 #14
0
def parse_resp(resp):
    """
        requests响应转化为json格式
    :param resp: requests请求返回的响应
    :return: json
    """
    if resp is None or resp.text is None or resp.text == '':
        return None
    text = resp.text
    try:
        result = json.loads(text)
    except Exception as e:
        error_msg = 'Parsing json failed, the text is %s' % text
        logger.error(error_msg)
        raise ClientException(error_msg)
    if 'error_code' in result and 'error_msg' in result:
        error_msg = json.dumps(result)
        logger.error(error_msg)
        raise ServerException(result['error_code'], result['error_msg'])
    return result
예제 #15
0
 def get_ttsc_response(self, request):
     """
         定制语音合成接口
     :param request: 定制语音合成请求,TtsCustomRequest
     :return: 请求结果,json格式
     """
     if not isinstance(request, TtsCustomRequest):
         logger.error('the parameter in \'get_ttsc_response(request)\' should be TtsCustomRequest class')
         raise ClientException('the parameter in \'get_ttsc_response(request)\' should be TtsCustomRequest class')
     url = self._service_endpoint + '/v1/' + self._project_id + '/tts'
     params = request.construct_params()
     result = aksk_service.aksk_connect(self._ak, self._sk, url, params, 'POST', self._sis_config)
     if 'result' not in result:
         error_msg = 'The result of tts customization is invalid. Result is %s ' % json.dumps(result)
         logger.error(error_msg)
         raise ClientException(error_msg)
     if request.get_saved():
         base_str = result['result']['data']
         io_utils.save_audio_from_base64str(base_str, request.get_saved_path())
         result['is_saved'] = True
         result['saved_path'] = request.get_saved_path()
     return result
예제 #16
0
 def _on_error(ws, error):
     logger.error(error)
     self._status = 'error'
     self._callback.on_error(error)
예제 #17
0
def http_connect(url,
                 header,
                 data,
                 http_method='POST',
                 time_out=5,
                 proxy=None):
    """
        post请求,带有header信息(用于认证)
    :param url: -
    :param header: 头部
    :param data: post数据
    :param time_out: 超时
    :param proxy: 代理
    :param http_method: http方法,目前支持put、delete、post、get
    :return: http请求的response
    """
    if isinstance(data, dict):
        data = json.dumps(data)
    if proxy is not None:
        proxy = _generate_request_proxy(proxy)
    else:
        proxy = {'http': None, 'https': None}
    # 加入重试机制
    count = 0
    resp = None
    while count < NUM_MAX_RETRY:
        try:
            if http_method == 'POST':
                resp = requests.post(url,
                                     headers=header,
                                     data=data,
                                     timeout=time_out,
                                     verify=False,
                                     proxies=proxy)
            elif http_method == 'GET':
                resp = requests.get(url,
                                    headers=header,
                                    params=data,
                                    timeout=time_out,
                                    verify=False,
                                    proxies=proxy)
            elif http_method == 'PUT':
                resp = requests.put(url,
                                    headers=header,
                                    data=data,
                                    timeout=time_out,
                                    verify=False,
                                    proxies=proxy)
            elif http_method == 'DELETE':
                resp = requests.delete(url,
                                       headers=header,
                                       params=data,
                                       timeout=time_out,
                                       verify=False,
                                       proxies=proxy)
            else:
                logger.error('%s is invalid' % http_method)
                raise ClientException('%s is invalid' % http_method)
            break
        except requests.exceptions.RequestException as e:
            logger.error(
                'Error occurs in %s, the client will retry 5 times. Error message is %s'
                % (http_method, e))
            count += 1
    if resp is None:
        logger.error('%s Response is empety, url is %s' % (http_method, url))
        raise ClientException('%s Response is empety, url is %s' %
                              (http_method, url))
    return resp
예제 #18
0
 def _check_request(request):
     if not isinstance(request, RasrRequest):
         error_msg = 'The parameter of request in RasrClient should be RasrRequest class'
         logger.error(error_msg)
         raise ClientException(error_msg)
예제 #19
0
    def __init__(self,
                 user_name,
                 password,
                 domain_name,
                 region,
                 project_id,
                 callback,
                 config=SisConfig(),
                 service_endpoint=None,
                 token_url=None,
                 retry_sleep_time=1):
        """
            实时语音转写client初始化
        :param user_name:           用户名
        :param password:            密码
        :param domain_name:         账户名,一般等同用户名
        :param region:              区域,如cn-north-4
        :param project_id:          项目ID,可参考https://support.huaweicloud.com/api-sis/sis_03_0008.html
        :param callback:            回调类RasrCallBack,用于监听websocket连接、响应、断开、错误等
        :param service_endpoint:    终端节点,一般使用默认即可
        :param token_url:           请求token的url,一般使用默认即可
        :param retry_sleep_time:          当websocket连接失败重试的间隔时间,默认为5s
        """
        if service_endpoint is None:
            self._service_endpoint = 'wss://sis-ext.' + region + '.myhuaweicloud.com'
        else:
            self._service_endpoint = service_endpoint
        if token_url is None:
            self._token_url = 'https://iam.' + region + '.myhuaweicloud.com/v3/auth/tokens'
        else:
            self._token_url = token_url
        if not isinstance(callback, RasrCallBack):
            logger.error('The parameter callback must be RasrCallBack class')
            raise ClientException(
                'The parameter callback must be RasrCallBack class')
        if not isinstance(config, SisConfig):
            logger.error('The parameter config must by SisConfig class')
            raise ClientException(
                'The parameter config must by SisConfig class')
        self._project_id = project_id
        self._config = config

        # token 缓存必须在client进行,才可以在多线程中生效。
        now_time = time.time()
        self._token = None
        if user_name in user_dict and user_name in time_dict:
            token = user_dict[user_name]
            save_time = time_dict[user_name]
            if now_time - save_time < 5 * 3600:
                logger.info('use token cache')
                self._token = token
        if self._token is None:
            self._token = token_service.get_token(user_name,
                                                  password,
                                                  domain_name,
                                                  region,
                                                  url=self._token_url,
                                                  config=self._config)
            user_dict[user_name] = self._token
            time_dict[user_name] = now_time

        self._callback = callback
        self._status = 'pre_start'
        self._request = None
        self._retry_sleep_time = retry_sleep_time
예제 #20
0
 def on_error(self, error):
     logger.error(error)
예제 #21
0
    def _connect(self, url):
        def _check_result(result):
            result_str = json.dumps(result)
            if 'error_code' in result and 'error_msg' in result:
                logger.error(result_str)
                # 睡眠2s保证关闭前,发送端有充足时间收到关闭请求。
                self._status = 'close'
                self._callback.on_error(result_str)
                time.sleep(2)
                self._ws.close()
                raise ClientException(result_str)
            if 'resp_type' not in result:
                self._status == 'error'
                error_msg = 'result doesn\'t contain key resp, result is %s' % result_str
                logger.error(error_msg)
                self._callback.on_error(error_msg)
                raise ClientException(error_msg)

        def _on_open(ws):
            logger.info('websocket open')
            self._status = 'start'
            self._callback.on_open()

        def _on_message(ws, message):
            result = json.loads(message)
            _check_result(result)
            result_type = result['resp_type']
            trace_id = result['trace_id']
            if result_type == 'START':
                self._callback.on_start(trace_id)
            elif result_type == 'EVENT':
                event = result['event']
                if event == 'EXCEEDED_AUDIO':
                    logger.warn(
                        'the duration of the audio is too long, the rest won\'t be recognized'
                    )
                    self._status = 'end'
                elif event == 'EXCEEDED_SILENCE':
                    logger.error(
                        'silent time is too long, the audio won\'t be recognized'
                    )
                    self._callback.on_error(
                        'silent time is too long, the audio won\'t be recognized'
                    )
                    self._status = 'error'
                elif event == 'VOICE_END':
                    logger.warn(
                        'detect voice end, the rest won\'t be recognized')
                    self._status = 'end'
            elif result_type == 'RESULT':
                self._callback.on_response(result)
            elif result_type == 'END':
                self._status = 'end'
                self._callback.on_end(trace_id)
            else:
                logger.error('%s don\'t belong to any type' % result_type)

        def _on_close(ws):
            logger.info('websocket close')
            self._status = 'close'
            self._callback.on_close()

        def _on_error(ws, error):
            logger.error(error)
            self._status = 'error'
            self._callback.on_error(error)

        # 重试机制
        headers = {'X-Auth-Token': self._token}
        sslopt = {"cert_reqs": ssl.CERT_NONE}
        retry_count = 5
        for i in range(retry_count):
            self._status = 'pre_start'
            self._ws = websocket.WebSocketApp(url,
                                              headers,
                                              on_open=_on_open,
                                              on_close=_on_close,
                                              on_message=_on_message,
                                              on_error=_on_error)
            self._thread = threading.Thread(
                target=self._ws.run_forever,
                args=(None, sslopt,
                      self._config.get_connect_lost_timeout() + 1,
                      self._config.get_connect_lost_timeout()))
            self._thread.daemon = True
            self._thread.start()
            connect_count = int(self._config.get_connect_timeout() /
                                connect_sleep_time)
            for j in range(connect_count):
                if self._status != 'pre_start':
                    break
                else:
                    time.sleep(connect_sleep_time)
            if self._status == 'start':
                break
            else:
                logger.error(
                    'connect meets error, it will retry %d times, now it is %d'
                    % (retry_count, i + 1))
            time.sleep(self._retry_sleep_time)
        if self._status == 'pre_start' or self._status == 'close' or self._status == 'error' or self._status == 'end':
            logger.error('websocket connect failed, url is %s' % url)
            raise ClientException('websocket connect failed, url is %s' % url)