From cfab493becd198b87cfce84af6b0e54e745168c4 Mon Sep 17 00:00:00 2001 From: HuangHai <10402852@qq.com> Date: Tue, 15 Apr 2025 16:58:51 +0800 Subject: [PATCH] 'commit' --- .../test/voiceprint/confirmFeature.mp3 | Bin 0 -> 32256 bytes .../test/voiceprint/createFeature.mp3 | Bin 0 -> 14112 bytes .../test/voiceprint/vpr-demo.py | 291 ++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 XiaoZhi/xiaozhi-esp32-server/main/xiaozhi-server/test/voiceprint/confirmFeature.mp3 create mode 100644 XiaoZhi/xiaozhi-esp32-server/main/xiaozhi-server/test/voiceprint/createFeature.mp3 create mode 100644 XiaoZhi/xiaozhi-esp32-server/main/xiaozhi-server/test/voiceprint/vpr-demo.py diff --git a/XiaoZhi/xiaozhi-esp32-server/main/xiaozhi-server/test/voiceprint/confirmFeature.mp3 b/XiaoZhi/xiaozhi-esp32-server/main/xiaozhi-server/test/voiceprint/confirmFeature.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..eee97e768cd87f60a884df31435d22ec8fc4bb03 GIT binary patch literal 32256 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 JtNK4b{s)I7)lC2Z literal 0 HcmV?d00001 diff --git a/XiaoZhi/xiaozhi-esp32-server/main/xiaozhi-server/test/voiceprint/vpr-demo.py b/XiaoZhi/xiaozhi-esp32-server/main/xiaozhi-server/test/voiceprint/vpr-demo.py new file mode 100644 index 00000000..ab81eab2 --- /dev/null +++ b/XiaoZhi/xiaozhi-esp32-server/main/xiaozhi-server/test/voiceprint/vpr-demo.py @@ -0,0 +1,291 @@ +import base64 +import hashlib +import json +import time +import uuid + +import requests + +# API访问信息 +host = 'https://ai-vpr.hivoice.cn' +appkey = "e63ansycfbbrnkczs4a24kjxqy4x6plzuehpjyyo" +secret = 'f70584766f88e09aa1ebe19315a1c481' +# 文档 +# https://ai-vpr.hivoice.cn +# https://ai.unisound.com/doc/savpr/WebAPI.html + +# 用户名和密码 +# 18686619970 +# DsideaL@123 + +groupId = '1' +groupInfo = '黄海的测试声纹组' + +# 需要对比的声纹id +featureId = '**************************' +featureInfo = '*******我的声纹信息描述********' + +createGroupEndPoint = '/vpr/v1/createGroup' +createFeatureEndPoint = '/vpr/v1/createFeature' +confirmFeatureEndPoint = '/vpr/v1/confirmFeature' +identifyFeatureByGroupIdEndPoint = '/vpr/v1/identifyFeatureByGroupId' +identifyFeatureByIdsEndPoint = '/vpr/v1/identifyFeatureByIds' +updateFeatureByIdEndPoint = '/vpr/v1/updateFeatureById' +delFeatureByIdEndPoint = '/vpr/v1/delFeatureById' +delGroupByIdEndPoint = '/vpr/v1/delGroupById' +findFeatureListByGroupIdEndPoint = '/vpr/v1/findFeatureListByGroupId' +#需要辨认的音频文件名, 将需要辨认的声纹音频放到项目目录下, 文件名自行定义|修改 +confirmFeatureFileName = 'confirmFeature.mp3' +#需要创建的音频文件名, 将需要辨认的声纹音频放到项目目录下, 文件名自行定义|修改 +createFeatureFileName = 'createFeature.mp3' +class Client: + def findFeatureListByGroupId(self): + timestamp = str(int(time.time() * 1000)) + nonce = str(uuid.uuid1()).replace('-', '') + sign = self.getSign(timestamp, nonce) + headers = {"Content-Type": "application/json"} + find_feature_list_by_group_id_param = { + "appkey": appkey, + "timestamp": timestamp, + "nonce": nonce, + "sign": sign, + "groupId": groupId, + } + print('find_feature_list_by_group_id_param', find_feature_list_by_group_id_param) + find_feature_list_by_group_id_resp = requests.post(url=host + findFeatureListByGroupIdEndPoint, + data=json.dumps(find_feature_list_by_group_id_param), + headers=headers) + find_feature_list_by_group_id_result = json.loads(find_feature_list_by_group_id_resp.content) + print('find_feature_list_by_group_id_result', find_feature_list_by_group_id_result) + print('------------------------------------------------------------') + + # 删除声纹组 + def delGroupById(self): + timestamp = str(int(time.time() * 1000)) + nonce = str(uuid.uuid1()).replace('-', '') + sign = self.getSign(timestamp, nonce) + headers = {"Content-Type": "application/json"} + del_group_by_id_param = { + "appkey": appkey, + "timestamp": timestamp, + "nonce": nonce, + "sign": sign, + "groupId": groupId, + } + print('del_group_by_id_param', del_group_by_id_param) + del_group_by_id_resp = requests.post(url=host + delGroupByIdEndPoint, + data=json.dumps(del_group_by_id_param), + headers=headers) + del_group_by_id_result = json.loads(del_group_by_id_resp.content) + print('del_group_by_id_result', del_group_by_id_result) + print('------------------------------------------------------------') + + # 删除声纹 + def delFeatureById(self): + timestamp = str(int(time.time() * 1000)) + nonce = str(uuid.uuid1()).replace('-', '') + sign = self.getSign(timestamp, nonce) + headers = {"Content-Type": "application/json"} + del_feature_by_id_param = { + "appkey": appkey, + "timestamp": timestamp, + "nonce": nonce, + "sign": sign, + "groupId": groupId, + "featureId": featureId + } + print('del_feature_by_id_param', del_feature_by_id_param) + del_feature_by_id_resp = requests.post(url=host + delFeatureByIdEndPoint, + data=json.dumps(del_feature_by_id_param), + headers=headers) + del_feature_by_id_result = json.loads(del_feature_by_id_resp.content) + print('del_feature_by_id_result', del_feature_by_id_result) + print('------------------------------------------------------------') + + # 修改声纹 + def updateFeatureById(self): + update_feature = open(confirmFeatureFileName, 'rb').read() + # 声纹base64字符串 + audio_data = base64.b64encode(update_feature) + timestamp = str(int(time.time() * 1000)) + nonce = str(uuid.uuid1()).replace('-', '') + sign = self.getSign(timestamp, nonce) + headers = {"Content-Type": "application/json"} + update_feature_by_id_param = { + "appkey": appkey, + "timestamp": timestamp, + "nonce": nonce, + "sign": sign, + "groupId": groupId, + "featureId": featureId, + "featureInfo": '修改后的声纹', + "audioData": audio_data.decode(), + "audioSampleRate": 16000, + "audioFormat": "mp3" + } + #print('update_feature_by_id_param', update_feature_by_id_param) + update_feature_by_id_resp = requests.post(url=host + updateFeatureByIdEndPoint, + data=json.dumps(update_feature_by_id_param), + headers=headers) + update_feature_by_id_result = json.loads(update_feature_by_id_resp.content) + print('update_feature_by_id_result', update_feature_by_id_result) + print('------------------------------------------------------------') + + # 声纹确认 1:N 不同组的多个声纹 将需要辨认的声纹音频放到resource目录下, 文件名自行定义, 获取方式自行修改 + def identifyFeatureByIds(self): + identify_feature = open(createFeatureFileName, 'rb').read() + # 声纹base64字符串 + audio_data = base64.b64encode(identify_feature) + timestamp = str(int(time.time() * 1000)) + nonce = str(uuid.uuid1()).replace('-', '') + sign = self.getSign(timestamp, nonce) + headers = {"Content-Type": "application/json"} + feature_list = [{'groupId': groupId, "featureId": featureId}, {'groupId': groupId, "featureId": featureId}] + identify_feature_param = { + "appkey": appkey, + "timestamp": timestamp, + "nonce": nonce, + "sign": sign, + "featureList": feature_list, + "topN": 1, + "audioData": audio_data.decode(), + "audioSampleRate": 16000, + "audioFormat": "mp3" + } + #print('identify_feature_param', identify_feature_param) + identify_feature_resp = requests.post(url=host + identifyFeatureByIdsEndPoint, + data=json.dumps(identify_feature_param), + headers=headers) + identify_feature_result = json.loads(identify_feature_resp.content) + print('identify_feature_result', identify_feature_result) + print('------------------------------------------------------------') + + # 声纹辨认【1:N】组内所有声纹作对比 将需要辨认的声纹音频放到项目目录下, 文件名自行定义, 获取方式自行修改 + def identifyFeatureByGroupId(self): + identify_feature = open(confirmFeatureFileName, 'rb').read() + # 声纹base64字符串 + audio_data = base64.b64encode(identify_feature) + timestamp = str(int(time.time() * 1000)) + nonce = str(uuid.uuid1()).replace('-', '') + sign = self.getSign(timestamp, nonce) + headers = {"Content-Type": "application/json"} + identify_feature_param = { + "appkey": appkey, + "timestamp": timestamp, + "nonce": nonce, + "sign": sign, + "groupId": groupId, + "topN": 1, + "audioData": audio_data.decode(), + "audioSampleRate": 16000, + "audioFormat": "mp3" + } + #print('identify_feature_param', identify_feature_param) + identify_feature_resp = requests.post(url=host + identifyFeatureByGroupIdEndPoint, + data=json.dumps(identify_feature_param), + headers=headers) + identify_feature_result = json.loads(identify_feature_resp.content) + print('identify_feature_result', identify_feature_result) + print('------------------------------------------------------------') + + # 声纹确认【1:1】 将需要辨认的声纹音频放到项目目录下, 文件名自行定义, 获取方式自行修改 + def confirmFeature(self): + confirm_feature = open(confirmFeatureFileName, 'rb').read() + # 声纹base64字符串 + audio_data = base64.b64encode(confirm_feature) + timestamp = str(int(time.time() * 1000)) + nonce = str(uuid.uuid1()).replace('-', '') + sign = self.getSign(timestamp, nonce) + headers = {"Content-Type": "application/json"} + confirm_feature_param = { + "appkey": appkey, + "timestamp": timestamp, + "nonce": nonce, + "sign": sign, + "groupId": groupId, + "featureId": featureId, + "audioData": audio_data.decode(), + "audioSampleRate": 16000, + "audioFormat": "mp3" + } + #print('confirm_feature_param', confirm_feature_param) + confirm_feature_resp = requests.post(url=host + confirmFeatureEndPoint, data=json.dumps(confirm_feature_param), + headers=headers) + confirm_feature_result = json.loads(confirm_feature_resp.content) + print('confirm_feature_result', confirm_feature_result) + print('------------------------------------------------------------') + + # 创建声纹 将声纹音频放到项目目录下, 文件名自行定义, 获取方式自行修改 + def createFeature(self): + create_feature = open(createFeatureFileName, 'rb').read() + # 声纹base64字符串 + audio_data = base64.b64encode(create_feature) + timestamp = str(int(time.time() * 1000)) + nonce = str(uuid.uuid1()).replace('-', '') + sign = self.getSign(timestamp, nonce) + headers = {"Content-Type": "application/json"} + create_feature_param = { + "appkey": appkey, + "timestamp": timestamp, + "nonce": nonce, + "sign": sign, + "groupId": groupId, + "featureId": featureId, + "featureInfo": featureInfo, + "audioData": audio_data.decode(), + "audioSampleRate": 16000, + "audioFormat": "mp3" + } + #print('create_feature_param', create_feature_param) + create_feature_resp = requests.post(url=host + createFeatureEndPoint, data=json.dumps(create_feature_param), + headers=headers) + create_feature_result = json.loads(create_feature_resp.content) + print('create_feature_result', create_feature_result) + print('------------------------------------------------------------') + + def createGroup(self): + timestamp = str(int(time.time() * 1000)) + nonce = str(uuid.uuid1()).replace('-', '') + sign = self.getSign(timestamp, nonce) + headers = {"Content-Type": "application/json"} + creat_group_param = { + "appkey": appkey, + "timestamp": timestamp, + "nonce": nonce, + "sign": sign, + "groupId": groupId, + "groupInfo": groupInfo + } + print('creat_group_param', creat_group_param) + creat_group_resp = requests.post(url=host + createGroupEndPoint, data=json.dumps(creat_group_param), + headers=headers) + creat_group_result = json.loads(creat_group_resp.content) + print('creat_group_result', creat_group_result) + print('------------------------------------------------------------') + + @staticmethod + def getSign(timestamp, nonce): + hs = hashlib.sha256() + hs.update((appkey + timestamp + secret + nonce).encode('utf-8')) + signature = hs.hexdigest().upper() + return signature +################################################### +if __name__ == '__main__': + client = Client() + # 创建声纹组 + client.createGroup() + # 创建声纹 + client.createFeature() + # 确认声纹 + client.confirmFeature() + + # 在声纹组中搜索声纹 + client.identifyFeatureByGroupId() + + #client.identifyFeatureByIds() + client.findFeatureListByGroupId() + + + #client.updateFeatureById() + #client.delFeatureById() + #client.delGroupById()