generalRequest.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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=None):
  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_".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_".groupId,
  100. "groupInfo": "aiDog_groupInfo_".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_".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=None):
  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. gen_req_url = Gen_req_url()
  278. body = gen_req_body(apiname=api_name, APPId=APPId, file_path=file_path,featureId=featureId,groupId=groupId)
  279. 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)
  280. headers = {'content-type': "application/json", 'host': 'api.xf-yun.com', 'appid': '$APPID'}
  281. response = requests.post(request_url, data=json.dumps(body), headers=headers)
  282. tempResult = json.loads(response.content.decode('utf-8'))
  283. # print(tempResult)
  284. res['code'] = tempResult.get('header').get('code')
  285. if res['code'] ==0:
  286. fb = tempResult.get('payload').get(api_name + 'Res').get('text')
  287. res['status'] = tempResult.get('header').get('message')
  288. res["msg"] = str(base64.b64decode(fb), 'UTF-8')
  289. res['response_time'] =datetime.strftime(datetime.today(), '%Y-%m-%d %H:%M:%S')
  290. print(tempResult)
  291. print(str(base64.b64decode(fb),'UTF-8'))
  292. print(res)
  293. return res
  294. else:
  295. res['status'] = tempResult.get('header').get('message')
  296. res["msg"] = 'you wrong!'
  297. res['response_time'] = datetime.strftime(datetime.today(), '%Y-%m-%d %H:%M:%S')
  298. return res
  299. """
  300. * 1.声纹识别接口,请填写在讯飞开放平台-控制台-对应能力页面获取的APPID、APIKey、APISecret
  301. * 2.groupId要先创建,然后再在createFeature里使用,不然会报错23005,修改时需要注意保持统一
  302. * 3.音频base64编码后数据(不超过4M),音频格式需要16K、16BIT的MP3音频。
  303. * 4.主函数只提供调用示例,其他参数请到对应类去更改,以适应实际的应用场景。
  304. """
  305. if __name__ == '__main__':
  306. APPId = "4522d502"
  307. APISecret = "Zjc5MjJhMzBmMDYxNTg4MTNlMTg1MmQw"
  308. APIKey = "f7a9f0ceae3ff7ebfc0c89efeb18810d"
  309. # file_path = '示例音频/讯飞开放平台.mp3'#读取数据库路径下音源
  310. file_path='audio_cache/voice_JTYNZP9O_1726111463.mp3'
  311. # 执行逻辑
  312. # 先从客户端获取音频,使用音频文件格式转换工具ffmpeg
  313. # 并根据uid生成音频特征(一个名字对应一个特征),提交后创建特征库并添加特征id,(每个用户的8个声音指令=8个特征id,所有数据都在特征列表中)
  314. # 同时该音频存储到数据库对应uid下,下次提交音频的时候,根据用户id查询存储在数据库的音纹,
  315. # 提交数据库的音纹给检索出特征列表判断是否有数据,如有,则判断新音纹执行特征比对方法,返回结果中,取出text解密出得分0.0~1.0,给到前端做逻辑判断执行
  316. # 用户移除,则删掉对应音纹
  317. # apiname取值:
  318. # 1.创建声纹特征库 createGroup
  319. # req_url(api_name='createGroup', APPId=APPId,
  320. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  321. # 2.添加音频特征 createFeature
  322. # req_url(api_name='createFeature', APPId=APPId,
  323. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  324. # 3.查询特征列表 queryFeatureList
  325. # req_url(api_name='queryFeatureList', APPId=APPId,
  326. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  327. # 4.特征比对1:1 searchScoreFea
  328. req_url(api_name='searchScoreFea', APPId=APPId,
  329. APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  330. # 5.特征比对1:N searchFea
  331. # req_url(api_name='searchFea', APPId=APPId,
  332. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  333. # 6.更新音频特征 updateFeature
  334. # req_url(api_name='updateFeature', APPId=APPId,
  335. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  336. # 7.删除指定特征 deleteFeature
  337. # req_url(api_name='deleteFeature', APPId=APPId,
  338. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)
  339. # 8.删除声纹特征库 deleteGroup
  340. # req_url(api_name='deleteGroup', APPId=APPId,
  341. # APIKey=APIKey, APISecret=APISecret, file_path=file_path)