diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/IdentifyVoicePrintResponse.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/IdentifyVoicePrintResponse.java new file mode 100644 index 00000000..3680ae49 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/IdentifyVoicePrintResponse.java @@ -0,0 +1,18 @@ +package xiaozhi.modules.agent.dto; + +import lombok.Data; + +/** + * 声纹识别接口返回的对象 + */ +@Data +public class IdentifyVoicePrintResponse { + /** + * 最匹配的声纹id + */ + private String speakerId; + /** + * 声纹的分数 + */ + private Double score; +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java index 6715b1b4..928079ff 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentVoicePrintServiceImpl.java @@ -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 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 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 agentVoicePrintList = baseMapper.selectList(new LambdaQueryWrapper() + .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 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> requestEntity = new HttpEntity<>(body, headers); + // 发送 POST 请求 + ResponseEntity 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; + } }