generalRequest.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. import base64
  2. import hashlib
  3. import hmac
  4. import json
  5. from datetime import datetime
  6. from http import HTTPMethod
  7. from time import mktime
  8. from urllib.parse import urlencode
  9. from wsgiref.handlers import format_date_time
  10. import requests
  11. # 填写在开放平台申请的APPID、APIKey、APISecret
  12. # 相应编码音频base64编码后数据(不超过4M) 说话人辨认(Speaker Identification)和说话人确认(Speaker Verification)
  13. class Gen_req_url(object):
  14. """生成请求的url"""
  15. def sha256base64(self, data):
  16. sha256 = hashlib.sha256()
  17. sha256.update(data)
  18. digest = base64.b64encode(sha256.digest()).decode(encoding='utf-8')
  19. return digest
  20. def parse_url(self, requset_url):
  21. stidx = requset_url.index("://")
  22. host = requset_url[stidx + 3:]
  23. # self.schema = requset_url[:stidx + 3]
  24. edidx = host.index("/")
  25. if edidx <= 0:
  26. raise Exception("invalid request url:" + requset_url)
  27. self.path = host[edidx:]
  28. self.host = host[:edidx]
  29. # build websocket auth request url
  30. def assemble_ws_auth_url(self, requset_url, api_key, api_secret, method="GET"):
  31. self.parse_url(requset_url)
  32. now = datetime.now()
  33. date = format_date_time(mktime(now.timetuple()))
  34. # date = "Thu, 12 Dec 2019 01:57:27 GMT"
  35. signature_origin = "host: {}\ndate: {}\n{} {} HTTP/1.1".format(self.host, date, method, self.path)
  36. signature_sha = hmac.new(api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
  37. digestmod=hashlib.sha256).digest()
  38. signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')
  39. authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (
  40. api_key, "hmac-sha256", "host date request-line", signature_sha)
  41. authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
  42. values = {
  43. "host": self.host,
  44. "date": date,
  45. "authorization": authorization
  46. }
  47. return requset_url + "?" + urlencode(values)
  48. def gen_req_body(apiname, APPId,groupId,featureId,file_path):
  49. """
  50. 生成请求的body
  51. :param apiname
  52. :param APPId: Appid
  53. :param file_name: 文件路径
  54. :return:
  55. """
  56. if apiname == 'createFeature':
  57. with open(file_path, "rb") as f:
  58. audioBytes = f.read()
  59. body = {
  60. "header": {
  61. "app_id": APPId,
  62. "status": 3
  63. },
  64. # 定义参数,解密返回值后比对一致
  65. "parameter": {
  66. "s782b4996": {
  67. "func": "createFeature",
  68. "groupId": groupId,
  69. "featureId": featureId,
  70. "featureInfo": "aiDog_featureInfo_"+str(featureId),
  71. "createFeatureRes": {
  72. "encoding": "utf8",
  73. "compress": "raw",
  74. "format": "json"
  75. }
  76. }
  77. },
  78. "payload": {
  79. "resource": {
  80. "encoding": "lame",
  81. "sample_rate": 16000,
  82. "channels": 1,
  83. "bit_depth": 16,
  84. "status": 3,
  85. "audio": str(base64.b64encode(audioBytes), 'UTF-8')
  86. }
  87. }
  88. }
  89. elif apiname == 'createGroup':
  90. body = {
  91. "header": {
  92. "app_id": APPId,
  93. "status": 3
  94. },
  95. "parameter": {
  96. "s782b4996": {
  97. "func": "createGroup",
  98. "groupId": groupId,
  99. "groupName": "aiDog_groupName_"+str(groupId),
  100. "groupInfo": "aiDog_groupInfo_"+str(groupId),
  101. "createGroupRes": {
  102. "encoding": "utf8",
  103. "compress": "raw",
  104. "format": "json"
  105. }
  106. }
  107. }
  108. }
  109. elif apiname == 'deleteFeature':
  110. body = {
  111. "header": {
  112. "app_id": APPId,
  113. "status": 3
  114. },
  115. "parameter": {
  116. "s782b4996": {
  117. "func": "deleteFeature",
  118. "groupId": groupId,
  119. "featureId": featureId,
  120. "deleteFeatureRes": {
  121. "encoding": "utf8",
  122. "compress": "raw",
  123. "format": "json"
  124. }
  125. }
  126. }
  127. }
  128. elif apiname == 'queryFeatureList':
  129. body = {
  130. "header": {
  131. "app_id": APPId,
  132. "status": 3
  133. },
  134. "parameter": {
  135. "s782b4996": {
  136. "func": "queryFeatureList",
  137. "groupId": groupId,
  138. "queryFeatureListRes": {
  139. "encoding": "utf8",
  140. "compress": "raw",
  141. "format": "json"
  142. }
  143. }
  144. }
  145. }
  146. elif apiname == 'searchFea':
  147. with open(file_path, "rb") as f:
  148. audioBytes = f.read()
  149. body = {
  150. "header": {
  151. "app_id": APPId,
  152. "status": 3
  153. },
  154. "parameter": {
  155. "s782b4996": {
  156. "func": "searchFea",
  157. "groupId": groupId,
  158. "topK": 1,
  159. "searchFeaRes": {
  160. "encoding": "utf8",
  161. "compress": "raw",
  162. "format": "json"
  163. }
  164. }
  165. },
  166. "payload": {
  167. "resource": {
  168. "encoding": "lame",
  169. "sample_rate": 16000,
  170. "channels": 1,
  171. "bit_depth": 16,
  172. "status": 3,
  173. "audio": str(base64.b64encode(audioBytes), 'UTF-8')
  174. }
  175. }
  176. }
  177. elif apiname == 'searchScoreFea':
  178. with open(file_path, "rb") as f:
  179. audioBytes = f.read()
  180. body = {
  181. "header": {
  182. "app_id": APPId,
  183. "status": 3
  184. },
  185. "parameter": {
  186. "s782b4996": {
  187. "func": "searchScoreFea",
  188. "groupId": groupId,
  189. "dstFeatureId": featureId,
  190. "searchScoreFeaRes": {
  191. "encoding": "utf8",
  192. "compress": "raw",
  193. "format": "json"
  194. }
  195. }
  196. },
  197. "payload": {
  198. "resource": {
  199. "encoding": "lame",
  200. "sample_rate": 16000,
  201. "channels": 1,
  202. "bit_depth": 16,
  203. "status": 3,
  204. "audio": str(base64.b64encode(audioBytes), 'UTF-8')
  205. }
  206. }
  207. }
  208. elif apiname == 'updateFeature':
  209. with open(file_path, "rb") as f:
  210. audioBytes = f.read()
  211. body = {
  212. "header": {
  213. "app_id": APPId,
  214. "status": 3
  215. },
  216. "parameter": {
  217. "s782b4996": {
  218. "func": "updateFeature",
  219. "groupId": groupId,
  220. "featureId": featureId,
  221. "featureInfo": "aiDog_featureInfo_"+str(featureId),
  222. "updateFeatureRes": {
  223. "encoding": "utf8",
  224. "compress": "raw",
  225. "format": "json"
  226. }
  227. }
  228. },
  229. "payload": {
  230. "resource": {
  231. "encoding": "lame",
  232. "sample_rate": 16000,
  233. "channels": 1,
  234. "bit_depth": 16,
  235. "status": 3,
  236. "audio": str(base64.b64encode(audioBytes), 'UTF-8')
  237. }
  238. }
  239. }
  240. elif apiname == 'deleteGroup':
  241. body = {
  242. "header": {
  243. "app_id": APPId,
  244. "status": 3
  245. },
  246. "parameter": {
  247. "s782b4996": {
  248. "func": "deleteGroup",
  249. "groupId": groupId,
  250. "deleteGroupRes": {
  251. "encoding": "utf8",
  252. "compress": "raw",
  253. "format": "json"
  254. }
  255. }
  256. }
  257. }
  258. else:
  259. raise Exception(
  260. "输入的apiname不在[createFeature, createGroup, deleteFeature, queryFeatureList, searchFea, searchScoreFea,updateFeature]内,请检查")
  261. return body
  262. def req_url(api_name, APPId, APIKey, APISecret,featureId,groupId,file_path):
  263. """
  264. 开始请求
  265. :param APPId: APPID
  266. :param APIKey: APIKEY
  267. :param APISecret: APISecret
  268. :param file_path: body里的文件路径
  269. :return:
  270. """
  271. res = {
  272. "code":"",
  273. "status": "",
  274. "msg": "",
  275. "response_time": ""
  276. }
  277. time_start = datetime.now()
  278. gen_req_url = Gen_req_url()
  279. body = gen_req_body(apiname=api_name, APPId=APPId, file_path=file_path,featureId=featureId,groupId=groupId)
  280. request_url = gen_req_url.assemble_ws_auth_url(requset_url='https://api.xf-yun.com/v1/private/s782b4996', method="POST", api_key=APIKey, api_secret=APISecret)
  281. headers = {'content-type': "application/json", 'host': 'api.xf-yun.com', 'appid': '$APPID'}
  282. response = requests.post(request_url, data=json.dumps(body), headers=headers)
  283. tempResult = json.loads(response.content.decode('utf-8'))
  284. # print(tempResult)
  285. time_end = datetime.now()
  286. time_diff = (time_end - time_start).total_seconds()
  287. res['code'] = tempResult.get('header').get('code')
  288. if res['code'] ==0:
  289. fb = tempResult.get('payload').get(api_name + 'Res').get('text')
  290. res['status'] = tempResult.get('header').get('message')
  291. res["msg"] = str(base64.b64decode(fb), 'UTF-8')
  292. res["time_diff"]=time_diff
  293. res['response_time'] =datetime.strftime(datetime.today(), '%Y-%m-%d %H:%M:%S')
  294. print(tempResult)
  295. print(str(base64.b64decode(fb),'UTF-8'))
  296. print(res)
  297. return res
  298. else:
  299. res['status'] = tempResult.get('header').get('message')
  300. res["time_diff"] = time_diff
  301. res["msg"] = 'you wrong!'
  302. res['response_time'] = datetime.strftime(datetime.today(), '%Y-%m-%d %H:%M:%S')
  303. return res
  304. """
  305. * 1.声纹识别接口,请填写在讯飞开放平台-控制台-对应能力页面获取的APPID、APIKey、APISecret
  306. * 2.groupId要先创建,然后再在createFeature里使用,不然会报错23005,修改时需要注意保持统一
  307. * 3.音频base64编码后数据(不超过4M),音频格式需要16K、16BIT的MP3音频。
  308. * 4.主函数只提供调用示例,其他参数请到对应类去更改,以适应实际的应用场景。
  309. """
  310. if __name__ == '__main__':
  311. # APPId = "4522d502"
  312. # APISecret = "Zjc5MjJhMzBmMDYxNTg4MTNlMTg1MmQw"
  313. # APIKey = "f7a9f0ceae3ff7ebfc0c89efeb18810d"
  314. APPId = "527f831f"
  315. APISecret = "YWE5MjI0MzA4NmM3MTNmNTNiMWJkYzE4"
  316. APIKey = "be5c37f3db1569737934240a0e3ad02d"
  317. # file_path = '示例音频/讯飞开放平台.mp3'#读取数据库路径下音源
  318. file_path='audio_cache/voice_JTYNZP9O_1726111463.mp3'
  319. # 执行逻辑
  320. # 先从客户端获取音频,使用音频文件格式转换工具ffmpeg
  321. # 并根据uid生成音频特征(一个名字对应一个特征),提交后创建特征库并添加特征id,(每个用户的8个声音指令=8个特征id,所有数据都在特征列表中)
  322. # 同时该音频存储到数据库对应uid下,下次提交音频的时候,根据用户id查询存储在数据库的音纹,
  323. # 提交数据库的音纹给检索出特征列表判断是否有数据,如有,则判断新音纹执行特征比对方法,返回结果中,取出text解密出得分0.0~1.0,给到前端做逻辑判断执行
  324. # 用户移除,则删掉对应音纹
  325. # apiname取值:
  326. # 1.创建声纹特征库 createGroup
  327. # req_url(api_name='createGroup', APPId=APPId,
  328. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  329. # 2.添加音频特征 createFeature
  330. # req_url(api_name='createFeature', APPId=APPId,
  331. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  332. # 3.查询特征列表 queryFeatureList
  333. # req_url(api_name='queryFeatureList', APPId=APPId,
  334. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  335. # 4.特征比对1:1 searchScoreFea
  336. req_url(api_name='searchScoreFea', APPId=APPId,
  337. APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  338. # 5.特征比对1:N searchFea
  339. # req_url(api_name='searchFea', APPId=APPId,
  340. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  341. # 6.更新音频特征 updateFeature
  342. # req_url(api_name='updateFeature', APPId=APPId,
  343. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  344. # 7.删除指定特征 deleteFeature
  345. # req_url(api_name='deleteFeature', APPId=APPId,
  346. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  347. # 8.删除声纹特征库 deleteGroup
  348. # req_url(api_name='deleteGroup', APPId=APPId,
  349. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)