mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 15:13:55 +08:00
添加判断
--AgentVoicePrintServiceImpl.java 1.声纹音频保存,增加了保存前识别一下声纹是否有相似的声音,有则不保存 2.声纹音频修改,增加了保存前识别一下声纹是否有相似的声音且相似声纹id和本次修改id不一样的,则不修改 3.添加了识别声纹http的请求的方法 --IdentifyVoicePrintResponse.java 识别声纹响应类型
This commit is contained in:
+18
@@ -0,0 +1,18 @@
|
||||
package xiaozhi.modules.agent.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 声纹识别接口返回的对象
|
||||
*/
|
||||
@Data
|
||||
public class IdentifyVoicePrintResponse {
|
||||
/**
|
||||
* 最匹配的声纹id
|
||||
*/
|
||||
private String speakerId;
|
||||
/**
|
||||
* 声纹的分数
|
||||
*/
|
||||
private Double score;
|
||||
}
|
||||
+75
-2
@@ -15,9 +15,11 @@ import org.springframework.web.client.RestTemplate;
|
||||
import xiaozhi.common.constant.Constant;
|
||||
import xiaozhi.common.exception.RenException;
|
||||
import xiaozhi.common.utils.ConvertUtils;
|
||||
import xiaozhi.common.utils.JsonUtils;
|
||||
import xiaozhi.modules.agent.dao.AgentVoicePrintDao;
|
||||
import xiaozhi.modules.agent.dto.AgentVoicePrintSaveDTO;
|
||||
import xiaozhi.modules.agent.dto.AgentVoicePrintUpdateDTO;
|
||||
import xiaozhi.modules.agent.dto.IdentifyVoicePrintResponse;
|
||||
import xiaozhi.modules.agent.entity.AgentVoicePrintEntity;
|
||||
import xiaozhi.modules.agent.service.AgentChatAudioService;
|
||||
import xiaozhi.modules.agent.service.AgentChatHistoryService;
|
||||
@@ -25,10 +27,11 @@ import xiaozhi.modules.agent.service.AgentVoicePrintService;
|
||||
import xiaozhi.modules.agent.vo.AgentVoicePrintVO;
|
||||
import xiaozhi.modules.sys.service.SysParamsService;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author zjy
|
||||
@@ -44,13 +47,19 @@ public class AgentVoicePrintServiceImpl extends ServiceImpl<AgentVoicePrintDao,
|
||||
private final AgentChatHistoryService agentChatHistoryService;
|
||||
// Springboot提供的编程事务类
|
||||
private final TransactionTemplate transactionTemplate;
|
||||
// 识别度
|
||||
private final Double RECOGNITION = 0.3;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean insert(AgentVoicePrintSaveDTO dto) {
|
||||
// 获取音频数据
|
||||
ByteArrayResource resource = getVoicePrintAudioWAV(dto.getAgentId(),dto.getAudioId());
|
||||
|
||||
// 识别一下此声音是否注册过
|
||||
IdentifyVoicePrintResponse response = identifyVoicePrint(dto.getAgentId(), resource);
|
||||
if(response != null && response.getScore() > RECOGNITION){
|
||||
throw new RenException("此声音已经注册为声纹过了");
|
||||
}
|
||||
AgentVoicePrintEntity entity = ConvertUtils.sourceToTarget(dto, AgentVoicePrintEntity.class);
|
||||
// 开启事务
|
||||
return Boolean.TRUE.equals(transactionTemplate.execute(status -> {
|
||||
@@ -134,6 +143,16 @@ public class AgentVoicePrintServiceImpl extends ServiceImpl<AgentVoicePrintDao,
|
||||
// audioId不等于空,且audioId和之前的保存的音频id不一样,则需要重新获取音频数据生成声纹
|
||||
if (!StringUtils.isEmpty(audioId) && !audioId.equals(agentVoicePrintEntity.getAudioId())) {
|
||||
resource = getVoicePrintAudioWAV(agentId,audioId);
|
||||
|
||||
// 识别一下此声音是否注册过
|
||||
IdentifyVoicePrintResponse response = identifyVoicePrint(agentId, resource);
|
||||
// 返回分数高于RECOGNITION说明这个声纹已经有了
|
||||
if(response != null && response.getScore() > RECOGNITION){
|
||||
// 判断返回的id如果不是要修改的声纹id,说明这个声纹id,现在要注册的声音已经存在且不是原来的声纹,不允许修改
|
||||
if(!response.getSpeakerId().equals(dto.getId())){
|
||||
throw new RenException("此次修改不允许,此声音已经注册为声纹了");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resource = null;
|
||||
}
|
||||
@@ -299,4 +318,58 @@ public class AgentVoicePrintServiceImpl extends ServiceImpl<AgentVoicePrintDao,
|
||||
throw new RenException("声纹注销失败,请求处理失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送识别声纹http请求
|
||||
* @param agentId 智能体id
|
||||
* @param resource 声纹音频资源
|
||||
* @return 返回识别数据
|
||||
*/
|
||||
private IdentifyVoicePrintResponse identifyVoicePrint(String agentId, ByteArrayResource resource) {
|
||||
|
||||
// 获取该智能体所有注册的声纹
|
||||
List<AgentVoicePrintEntity> agentVoicePrintList = baseMapper.selectList(new LambdaQueryWrapper<AgentVoicePrintEntity>()
|
||||
.select(AgentVoicePrintEntity::getId)
|
||||
.eq(AgentVoicePrintEntity::getAgentId,agentId));
|
||||
|
||||
// 声纹数量为0,说明还没注册过声纹不需要发生识别请求
|
||||
if(agentVoicePrintList.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
// 处理声纹接口地址,获取前缀
|
||||
URI uri = getVoicePrintURI();
|
||||
String baseUrl = getBaseUrl(uri);
|
||||
String requestUrl = baseUrl + "/voiceprint/identify";
|
||||
// 创建请求体
|
||||
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
||||
|
||||
|
||||
//创建speaker_id参数
|
||||
String speakerIds = agentVoicePrintList.stream()
|
||||
.map(AgentVoicePrintEntity::getId)
|
||||
.collect(Collectors.joining(","));
|
||||
body.add("speaker_ids", speakerIds);
|
||||
body.add("file", resource);
|
||||
|
||||
// 创建请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Authorization", getAuthorization(uri));
|
||||
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
||||
// 创建请求体
|
||||
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
|
||||
// 发送 POST 请求
|
||||
ResponseEntity<String> response = restTemplate.postForEntity(requestUrl, requestEntity, String.class);
|
||||
|
||||
if (response.getStatusCode() != HttpStatus.OK) {
|
||||
log.error("声纹识别请求失败,请求路径:{}", requestUrl);
|
||||
throw new RenException("声纹识别失败,请求不成功");
|
||||
}
|
||||
// 检查响应内容
|
||||
String responseBody = response.getBody();
|
||||
if(responseBody != null ){
|
||||
return JsonUtils.parseObject(responseBody, IdentifyVoicePrintResponse.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user