# robot.sdk.TencentSpeech 源代码

    # coding: utf-8
    #!/usr/bin/env python3

    'Tencent ASR && TTS API'
    __author__ = 'Charles Li, Joseph Pan'

    import time
    import uuid
    import json
    import random
    import requests
    import hmac
    import base64
    import urllib
    #腾讯web API一句话识别请求
    class tencentSpeech(object):
        __slots__ = 'SECRET_ID', 'SECRET_KEY', 'SourceType', 'URL', 'VoiceFormat', 'PrimaryLanguage', 'Text', 'VoiceType', 'Region'

        def __init__(self, SECRET_KEY, SECRET_ID):
            self.SECRET_KEY, self.SECRET_ID = SECRET_KEY, SECRET_ID
        @property
        def secret_id(self):
            return self.SECRET_ID
        @secret_id.setter
        def secret_id(self, SECRET_ID):
            if not isinstance(SECRET_ID, str):
                raise ValueError('SecretId must be a string!')
            if len(SECRET_ID)==0:
                raise ValueError('SecretId can not be empty!')
            self.SECRET_ID = SECRET_ID
        @property
        def secret_key(self):
            return self.SECRET_KEY
        @secret_key.setter
        def secret_key(self, SECRET_KEY):
            if not isinstance(SECRET_KEY, str):
                raise ValueError('SecretKey must be a string!')
            if len(SECRET_KEY)==0:
                raise ValueError('SecretKey can not be empty!')
            self.SECRET_KEY = SECRET_KEY
        @property
        def source_type(self):
            return self.sourcetype
        @source_type.setter
        def source_type(self, SourceType):
            if not isinstance(SourceType, str):
                raise ValueError('SecretType must be an string!')
            if len(SourceType)==0:
                raise ValueError('SourceType can not be empty!')
            self.SourceType = SourceType
        @property
        def url(self):
            return self.URL
        @url.setter
        def url(self, URL):
            if not isinstance(URL, str):
                raise ValueError('url must be an string!')
            if len(URL)==0:
                raise ValueError('url can not be empty!')
            self.URL = URL
        @property
        def voiceformat(self):
            return self.VoiceFormat
        @voiceformat.setter
        def voiceformat(self, VoiceFormat):
            if not isinstance(VoiceFormat, str):
                raise ValueError('voiceformat must be an string!')
            if len(VoiceFormat)==0:
                raise ValueError('voiceformat can not be empty!')
            self.VoiceFormat = VoiceFormat
        @property
        def text(self):
            return self.Text
        @text.setter
        def text(self, Text):
            if not isinstance(Text, str):
                raise ValueError('text must be an string!')
            if len(Text)==0:
                raise ValueError('text can not be empty!')
            self.Text = Text
        @property
        def region(self):
            return self.Region
        @region.setter
        def region(self, Region):
            if not isinstance(Region, str):
                raise ValueError('region must be an string!')
            if len(Region)==0:
                raise ValueError('region can not be empty!')
            self.Region = Region
        @property
        def primarylanguage(self):
            return self.PrimaryLanguage
        @primarylanguage.setter
        def primarylanguage(self, PrimaryLanguage):
            self.PrimaryLanguage = PrimaryLanguage
        @property
        def voicetype(self):
            return self.VoiceType
        @voicetype.setter
        def voicetype(self, VoiceType):
            self.VoiceType = VoiceType
        def TTS(self, text, voicetype, primarylanguage, region):
            self.text, self.voicetype, self.primarylanguage, self.region = text, voicetype, primarylanguage, region
            return self.textToSpeech()
        def textToSpeech(self):
            #生成body
            def make_body(config_dict, sign_encode):
                ##注意URL编码的时候分str编码，整段编码会丢data
                body = ''
                for a, b in config_dict:
                    body += urllib.parse.quote(a) + '=' + urllib.parse.quote(str(b)) + '&'
                return body + 'Signature=' + sign_encode
            HOST = 'aai.tencentcloudapi.com'
            config_dict= {
                            'Action'         : 'TextToVoice',
                            'Version'        : '2018-05-22',
                            'ProjectId'      : 0,
                            'Region'         : self.Region,
                            'VoiceType'      : self.VoiceType,
                            'Timestamp'      : int(time.time()),
                            'Nonce'          : random.randint(100000, 200000),
                            'SecretId'       : self.SECRET_ID,
                            'Text'           : self.Text,
                            'PrimaryLanguage': self.PrimaryLanguage,
                            'ModelType'      : 1,
                            'SessionId'      : uuid.uuid1()
            }
            #按key排序
            config_dict = sorted(config_dict.items())
            signstr = self.formatSignString(config_dict)
            sign_encode = urllib.parse.quote(self.encode_sign(signstr, self.SECRET_KEY))
            body = make_body(config_dict, sign_encode)
            #Get URL
            req_url = "https://aai.tencentcloudapi.com"
            header = {
                'Host' : HOST,
                'Content-Type' : 'application/x-www-form-urlencoded',
                'Charset' : 'UTF-8'
            }
            request = requests.post(req_url, headers = header, data = body)
            #有些音频utf8解码失败，存在编码错误
            s = request.content.decode("utf8","ignore")
            return json.loads(s)
        def ASR(self, URL, voiceformat, sourcetype, region):
            self.url, self.voiceformat, self.source_type, self.region = URL, voiceformat, sourcetype, region
            return self.oneSentenceRecognition()
        def oneSentenceRecognition(self):
            #生成body
            def make_body(config_dict, sign_encode):
                ##注意URL编码的时候分str编码，整段编码会丢data
                body = ''
                for a, b in config_dict:
                    body += urllib.parse.quote(a) + '=' + urllib.parse.quote(str(b)) + '&'
                return body + 'Signature=' + sign_encode
            HOST = 'aai.tencentcloudapi.com'
            config_dict= {
                            'Action'         : 'SentenceRecognition',
                            'Version'        : '2018-05-22',
                            'Region'         : self.Region,
                            'ProjectId'      : 0,
                            'SubServiceType' : 2,
                            'EngSerViceType' : '16k',
                            'VoiceFormat'    : self.VoiceFormat,
                            'UsrAudioKey'    : random.randint(0, 20),
                            'Timestamp'      : int(time.time()),
                            'Nonce'          : random.randint(100000, 200000),
                            'SecretId'       : self.SECRET_ID,
                            'SourceType'     : self.SourceType
            }
            if self.SourceType == '0':
                config_dict['Url'] = urllib.parse.quote(str(self.url))
            else:
                #不能大于1M
                file_path = self.URL
                file = open(file_path, 'rb')
                content = file.read()
                config_dict['DataLen'] = len(content)
                config_dict['Data'] = base64.b64encode(content).decode()
                #config_dict['Data'] = content
                file.close()
            #按key排序
            config_dict = sorted(config_dict.items())
            signstr = self.formatSignString(config_dict)
            sign_encode = urllib.parse.quote(self.encode_sign(signstr, self.SECRET_KEY))
            body = make_body(config_dict, sign_encode)
            #Get URL
            req_url = "https://aai.tencentcloudapi.com"
            header = {
                'Host' : HOST,
                'Content-Type' : 'application/x-www-form-urlencoded',
                'Charset' : 'UTF-8'
            }
            request = requests.post(req_url, headers = header, data = body)
            #有些音频utf8解码失败，存在编码错误
            s = request.content.decode("utf8","ignore")
            return s
        #拼接url和参数
        def formatSignString(self, config_dict):
            signstr="POSTaai.tencentcloudapi.com/?"
            argArr = []
            for a, b in config_dict:
                argArr.append(a + "=" + str(b))
            config_str = "&".join(argArr)
            return signstr + config_str
        #生成签名
        def encode_sign(self, signstr, SECRET_KEY):
            myhmac = hmac.new(SECRET_KEY.encode(), signstr.encode(), digestmod = 'sha1')
            code = myhmac.digest()
            #hmac() 完一定要decode()和 python 2 hmac不一样
            signature = base64.b64encode(code).decode()
            return signature