tencent.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. # -*- coding: utf-8 -*-
  2. from __future__ import division
  3. from ..__load__ import *
  4. 'Tencent ASR && TTS API'
  5. __author__ = 'Charles Li, Joseph Pan'
  6. import time
  7. import uuid
  8. import json
  9. import random
  10. import requests
  11. import hmac
  12. import base64
  13. import urllib
  14. from hashlib import sha1
  15. class Tencent(object):
  16. __slots__ = 'SECRET_ID', 'SECRET_KEY', 'SourceType', 'URL', 'VoiceFormat', 'PrimaryLanguage', 'Text', 'VoiceType', 'Region'
  17. def init(self, SECRET_ID, SECRET_KEY):
  18. self.SECRET_KEY, self.SECRET_ID = SECRET_KEY, SECRET_ID
  19. return self
  20. @property
  21. def secret_id(self):
  22. return self.SECRET_ID
  23. @secret_id.setter
  24. def secret_id(self, SECRET_ID):
  25. if not isinstance(SECRET_ID, str):
  26. raise ValueError('SecretId must be a string!')
  27. if len(SECRET_ID)==0:
  28. raise ValueError('SecretId can not be empty!')
  29. self.SECRET_ID = SECRET_ID
  30. @property
  31. def secret_key(self):
  32. return self.SECRET_KEY
  33. @secret_key.setter
  34. def secret_key(self, SECRET_KEY):
  35. if not isinstance(SECRET_KEY, str):
  36. raise ValueError('SecretKey must be a string!')
  37. if len(SECRET_KEY)==0:
  38. raise ValueError('SecretKey can not be empty!')
  39. self.SECRET_KEY = SECRET_KEY
  40. @property
  41. def source_type(self):
  42. return self.sourcetype
  43. @source_type.setter
  44. def source_type(self, SourceType):
  45. if not isinstance(SourceType, str):
  46. raise ValueError('SecretType must be an string!')
  47. if len(SourceType)==0:
  48. raise ValueError('SourceType can not be empty!')
  49. self.SourceType = SourceType
  50. @property
  51. def url(self):
  52. return self.URL
  53. @url.setter
  54. def url(self, URL):
  55. if not isinstance(URL, str):
  56. raise ValueError('url must be an string!')
  57. if len(URL)==0:
  58. raise ValueError('url can not be empty!')
  59. self.URL = URL
  60. @property
  61. def voiceformat(self):
  62. return self.VoiceFormat
  63. @voiceformat.setter
  64. def voiceformat(self, VoiceFormat):
  65. if not isinstance(VoiceFormat, str):
  66. raise ValueError('voiceformat must be an string!')
  67. if len(VoiceFormat)==0:
  68. raise ValueError('voiceformat can not be empty!')
  69. self.VoiceFormat = VoiceFormat
  70. @property
  71. def text(self):
  72. return self.Text
  73. @text.setter
  74. def text(self, Text):
  75. if not isinstance(Text, str):
  76. raise ValueError('text must be an string!')
  77. if len(Text)==0:
  78. raise ValueError('text can not be empty!')
  79. self.Text = Text
  80. @property
  81. def region(self):
  82. return self.Region
  83. @region.setter
  84. def region(self, Region):
  85. if not isinstance(Region, str):
  86. raise ValueError('region must be an string!')
  87. if len(Region)==0:
  88. raise ValueError('region can not be empty!')
  89. self.Region = Region
  90. @property
  91. def primarylanguage(self):
  92. return self.PrimaryLanguage
  93. @primarylanguage.setter
  94. def primarylanguage(self, PrimaryLanguage):
  95. self.PrimaryLanguage = PrimaryLanguage
  96. @property
  97. def voicetype(self):
  98. return self.VoiceType
  99. @voicetype.setter
  100. def voicetype(self, VoiceType):
  101. self.VoiceType = VoiceType
  102. def TTS(self, text, voicetype, primarylanguage, region):
  103. self.text, self.voicetype, self.primarylanguage, self.region = text, voicetype, primarylanguage, region
  104. return self.textToSpeech()
  105. def textToSpeech(self):
  106. #生成body
  107. def make_body(config_dict, sign_encode):
  108. ##注意URL编码的时候分str编码,整段编码会丢data
  109. body = ''
  110. for a, b in config_dict:
  111. body += self.quote(a) + '=' + self.quote(str(b)) + '&'
  112. return body + 'Signature=' + sign_encode
  113. HOST = 'aai.tencentcloudapi.com'
  114. config_dict= {
  115. 'Action' : 'TextToVoice',
  116. 'Version' : '2018-05-22',
  117. 'ProjectId' : 0,
  118. 'Region' : self.Region,
  119. 'VoiceType' : self.VoiceType,
  120. 'Timestamp' : int(time.time()),
  121. 'Nonce' : random.randint(100000, 200000),
  122. 'SecretId' : self.SECRET_ID,
  123. 'Text' : self.Text,
  124. 'PrimaryLanguage': self.PrimaryLanguage,
  125. 'ModelType' : 1,
  126. 'SessionId' : uuid.uuid1()
  127. }
  128. #按key排序
  129. config_dict = sorted(config_dict.items())
  130. signstr = self.formatSignString(config_dict)
  131. sign_encode = self.quote(self.encode_sign(signstr, self.SECRET_KEY))
  132. body = make_body(config_dict, sign_encode)
  133. #Get URL
  134. req_url = "https://aai."+self.region+".tencentcloudapi.com"
  135. header = {
  136. 'Host' : HOST,
  137. 'Content-Type' : 'application/x-www-form-urlencoded',
  138. 'Charset' : 'UTF-8'
  139. }
  140. request = requests.post(req_url, headers = header, data = body)
  141. #有些音频utf8解码失败,存在编码错误
  142. s = request.content.decode("utf8","ignore")
  143. return json.loads(s)
  144. def quote(self, str):
  145. if Demeter.checkPy3():
  146. return urllib.parse.quote(str)
  147. else:
  148. return urllib.quote(str)
  149. def ASR(self, URL, voiceformat, sourcetype, region):
  150. self.url, self.voiceformat, self.source_type, self.region = URL, voiceformat, sourcetype, region
  151. return self.oneSentenceRecognition()
  152. def oneSentenceRecognition(self):
  153. #生成body
  154. def make_body(config_dict, sign_encode):
  155. ##注意URL编码的时候分str编码,整段编码会丢data
  156. body = ''
  157. for a, b in config_dict:
  158. body += self.quote(a) + '=' + self.quote(str(b)) + '&'
  159. return body + 'Signature=' + sign_encode
  160. HOST = 'aai.tencentcloudapi.com'
  161. config_dict= {
  162. 'Action' : 'SentenceRecognition',
  163. 'Version' : '2018-05-22',
  164. 'Region' : self.Region,
  165. 'ProjectId' : 0,
  166. 'SubServiceType' : 2,
  167. 'EngSerViceType' : '16k',
  168. 'VoiceFormat' : self.VoiceFormat,
  169. 'UsrAudioKey' : random.randint(0, 20),
  170. 'Timestamp' : int(time.time()),
  171. 'Nonce' : random.randint(100000, 200000),
  172. 'SecretId' : self.SECRET_ID,
  173. 'SourceType' : self.SourceType
  174. }
  175. if self.SourceType == '0':
  176. config_dict['Url'] = self.quote(str(self.url))
  177. else:
  178. #不能大于1M
  179. file_path = self.URL
  180. file = open(file_path, 'rb')
  181. content = file.read()
  182. config_dict['DataLen'] = len(content)
  183. config_dict['Data'] = base64.b64encode(content).decode()
  184. #config_dict['Data'] = content
  185. file.close()
  186. #按key排序
  187. config_dict = sorted(config_dict.items())
  188. signstr = self.formatSignString(config_dict)
  189. sign_encode = self.quote(self.encode_sign(signstr, self.SECRET_KEY))
  190. body = make_body(config_dict, sign_encode)
  191. #Get URL
  192. req_url = "https://aai."+self.region+".tencentcloudapi.com"
  193. header = {
  194. 'Host' : HOST,
  195. 'Content-Type' : 'application/x-www-form-urlencoded',
  196. 'Charset' : 'UTF-8'
  197. }
  198. request = requests.post(req_url, headers = header, data = body)
  199. #有些音频utf8解码失败,存在编码错误
  200. s = request.content.decode("utf8","ignore")
  201. return s
  202. #拼接url和参数
  203. def formatSignString(self, config_dict):
  204. signstr="POSTaai.tencentcloudapi.com/?"
  205. argArr = []
  206. for a, b in config_dict:
  207. argArr.append(a + "=" + str(b))
  208. config_str = "&".join(argArr)
  209. return signstr + config_str
  210. #生成签名
  211. def encode_sign(self, signstr, SECRET_KEY):
  212. myhmac = hmac.new(SECRET_KEY.encode(), signstr.encode(), sha1)
  213. code = myhmac.digest()
  214. #hmac() 完一定要decode()和 python 2 hmac不一样
  215. signature = base64.b64encode(code).decode()
  216. return signature