mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-29 18:23:59 +08:00
update:优化克隆失败显示
This commit is contained in:
+9
@@ -392,6 +392,15 @@ public class ConfigServiceImpl implements ConfigService {
|
|||||||
((Map<String, Object>) model.getConfigJson()).put("ref_audio", referenceAudio);
|
((Map<String, Object>) model.getConfigJson()).put("ref_audio", referenceAudio);
|
||||||
if (referenceText != null)
|
if (referenceText != null)
|
||||||
((Map<String, Object>) model.getConfigJson()).put("ref_text", referenceText);
|
((Map<String, Object>) model.getConfigJson()).put("ref_text", referenceText);
|
||||||
|
|
||||||
|
// 火山引擎声音克隆需要替换resource_id
|
||||||
|
Map<String, Object> map = (Map<String, Object>) model.getConfigJson();
|
||||||
|
if ("huoshan_double_stream".equals(map.get("type"))) {
|
||||||
|
// 如果voice是”S_“开头的,使用seed-icl-1.0
|
||||||
|
if (voice != null && voice.startsWith("S_")) {
|
||||||
|
map.put("resource_id", "seed-icl-1.0");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 如果是Intent类型,且type=intent_llm,则给他添加附加模型
|
// 如果是Intent类型,且type=intent_llm,则给他添加附加模型
|
||||||
if ("Intent".equals(modelTypes[i])) {
|
if ("Intent".equals(modelTypes[i])) {
|
||||||
|
|||||||
+47
-45
@@ -315,61 +315,63 @@ public class VoiceCloneServiceImpl extends BaseServiceImpl<VoiceCloneDao, VoiceC
|
|||||||
System.out.println(">>> HTTP status = " + response.statusCode());
|
System.out.println(">>> HTTP status = " + response.statusCode());
|
||||||
System.out.println(">>> response body = " + response.body());
|
System.out.println(">>> response body = " + response.body());
|
||||||
|
|
||||||
if (response.statusCode() == 200) {
|
Map<String, Object> rsp = objectMapper.readValue(response.body(),
|
||||||
Map<String, Object> rsp = objectMapper.readValue(response.body(),
|
new TypeReference<Map<String, Object>>() {
|
||||||
new TypeReference<Map<String, Object>>() {
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// 获取BaseResp对象
|
// 获取BaseResp对象
|
||||||
Map<String, Object> baseResp = objectMapper.convertValue(rsp.get("BaseResp"),
|
Map<String, Object> baseResp = objectMapper.convertValue(rsp.get("BaseResp"),
|
||||||
new TypeReference<Map<String, Object>>() {
|
new TypeReference<Map<String, Object>>() {
|
||||||
});
|
});
|
||||||
if (baseResp != null) {
|
if (baseResp != null) {
|
||||||
Integer statusCode = objectMapper.convertValue(baseResp.get("StatusCode"), Integer.class);
|
Integer statusCode = objectMapper.convertValue(baseResp.get("StatusCode"), Integer.class);
|
||||||
String statusMessage = objectMapper.convertValue(baseResp.getOrDefault("StatusMessage", ""),
|
String statusMessage = objectMapper.convertValue(baseResp.getOrDefault("StatusMessage", ""),
|
||||||
String.class);
|
String.class);
|
||||||
|
|
||||||
// 获取speaker_id
|
// 获取speaker_id
|
||||||
String speakerId = objectMapper.convertValue(rsp.get("speaker_id"), String.class);
|
String speakerId = objectMapper.convertValue(rsp.get("speaker_id"), String.class);
|
||||||
|
|
||||||
// StatusCode == 0 表示成功
|
// StatusCode == 0 表示成功
|
||||||
if (statusCode != null && statusCode == 0 && StringUtils.isNotBlank(speakerId)) {
|
if (statusCode != null && statusCode == 0 && StringUtils.isNotBlank(speakerId)) {
|
||||||
entity.setTrainStatus(2);
|
entity.setTrainStatus(2);
|
||||||
entity.setVoiceId(speakerId);
|
entity.setVoiceId(speakerId);
|
||||||
entity.setTrainError("");
|
entity.setTrainError("");
|
||||||
baseDao.updateById(entity);
|
baseDao.updateById(entity);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 检查speaker_id是否已经被使用
|
// 检查speaker_id是否已经被使用
|
||||||
if (timbreService.existsByTtsVoice(speakerId)) {
|
if (timbreService.existsByTtsVoice(speakerId)) {
|
||||||
log.info("音色编码speaker_id[{}]已存在,不重复写入数据库", speakerId);
|
log.info("音色编码speaker_id[{}]已存在,不重复写入数据库", speakerId);
|
||||||
} else {
|
} else {
|
||||||
xiaozhi.modules.timbre.dto.TimbreDataDTO timbreDataDTO = new xiaozhi.modules.timbre.dto.TimbreDataDTO();
|
xiaozhi.modules.timbre.dto.TimbreDataDTO timbreDataDTO = new xiaozhi.modules.timbre.dto.TimbreDataDTO();
|
||||||
timbreDataDTO.setTtsModelId(entity.getModelId());
|
timbreDataDTO.setTtsModelId(entity.getModelId());
|
||||||
timbreDataDTO.setName(entity.getName());
|
timbreDataDTO.setName(entity.getName());
|
||||||
timbreDataDTO.setTtsVoice(speakerId);
|
timbreDataDTO.setTtsVoice(speakerId);
|
||||||
timbreDataDTO.setSort(1);
|
timbreDataDTO.setSort(1);
|
||||||
timbreDataDTO.setLanguages("zh-CN");
|
timbreDataDTO.setLanguages("zh-CN");
|
||||||
timbreDataDTO.setRemark("复刻音色");
|
timbreDataDTO.setRemark("复刻音色");
|
||||||
|
|
||||||
// 保存到音色表
|
// 保存到音色表
|
||||||
timbreService.save(timbreDataDTO);
|
timbreService.save(timbreDataDTO);
|
||||||
log.info("成功将复刻音色添加到音色表,speaker_id: {}", speakerId);
|
log.info("成功将复刻音色添加到音色表,speaker_id: {}", speakerId);
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// 记录错误但不影响主流程
|
|
||||||
log.error("将复刻音色添加到音色表失败: " + e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
} else {
|
} catch (Exception e) {
|
||||||
// 失败时使用StatusMessage作为错误信息
|
// 记录错误但不影响主流程
|
||||||
String errorMsg = StringUtils.isNotBlank(statusMessage) ? statusMessage : "训练失败";
|
log.error("将复刻音色添加到音色表失败: " + e.getMessage(), e);
|
||||||
throw new RenException(errorMsg);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new RenException(ErrorCode.VOICE_CLONE_RESPONSE_FORMAT_ERROR);
|
// 失败时使用StatusMessage作为错误信息
|
||||||
|
String errorMsg = StringUtils.isNotBlank(statusMessage) ? statusMessage : "训练失败";
|
||||||
|
throw new RenException(errorMsg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new RenException(ErrorCode.VOICE_CLONE_REQUEST_FAILED + ",状态码: " + response.statusCode());
|
String errorMsg = objectMapper.convertValue(rsp.get("message"),
|
||||||
|
new TypeReference<String>() {
|
||||||
|
});
|
||||||
|
if (StringUtils.isNotBlank(errorMsg)) {
|
||||||
|
throw new RenException(errorMsg);
|
||||||
|
}
|
||||||
|
throw new RenException(ErrorCode.VOICE_CLONE_RESPONSE_FORMAT_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1112,5 +1112,5 @@ export default {
|
|||||||
'voiceClone.updateNameSuccess': 'Name updated successfully',
|
'voiceClone.updateNameSuccess': 'Name updated successfully',
|
||||||
'voiceClone.updateNameFailed': 'Failed to update name',
|
'voiceClone.updateNameFailed': 'Failed to update name',
|
||||||
'voiceClone.playFailed': 'Play failed',
|
'voiceClone.playFailed': 'Play failed',
|
||||||
'voiceClone.Details': 'Details',
|
'voiceClone.Details': 'Error Details',
|
||||||
}
|
}
|
||||||
@@ -1112,5 +1112,5 @@ export default {
|
|||||||
'voiceClone.updateNameSuccess': '名称更新成功',
|
'voiceClone.updateNameSuccess': '名称更新成功',
|
||||||
'voiceClone.updateNameFailed': '名称更新失败',
|
'voiceClone.updateNameFailed': '名称更新失败',
|
||||||
'voiceClone.playFailed': '播放失败',
|
'voiceClone.playFailed': '播放失败',
|
||||||
'voiceClone.Details': '详情',
|
'voiceClone.Details': '错误详情',
|
||||||
}
|
}
|
||||||
@@ -1112,5 +1112,5 @@ export default {
|
|||||||
'voiceClone.updateNameSuccess': '名稱更新成功',
|
'voiceClone.updateNameSuccess': '名稱更新成功',
|
||||||
'voiceClone.updateNameFailed': '名稱更新失敗',
|
'voiceClone.updateNameFailed': '名稱更新失敗',
|
||||||
'voiceClone.playFailed': '播放失敗',
|
'voiceClone.playFailed': '播放失敗',
|
||||||
'voiceClone.Details': '詳情',
|
'voiceClone.Details': '錯誤詳情',
|
||||||
}
|
}
|
||||||
@@ -189,73 +189,7 @@ export default {
|
|||||||
case 3:
|
case 3:
|
||||||
// 训练失败时,根据错误信息智能展示
|
// 训练失败时,根据错误信息智能展示
|
||||||
if (row.trainError) {
|
if (row.trainError) {
|
||||||
const errorMsg = row.trainError;
|
return `训练失败:${row.trainError}`;
|
||||||
|
|
||||||
// 火山引擎语音复刻业务错误码映射表
|
|
||||||
const voiceCloneErrorMap = {
|
|
||||||
'1001': '请求参数有误',
|
|
||||||
'1101': '音频上传失败',
|
|
||||||
'1102': 'ASR(语音识别成文字)转写失败',
|
|
||||||
'1103': 'SID声纹检测失败',
|
|
||||||
'1104': '声纹检测未通过,声纹跟名人相似度过高',
|
|
||||||
'1105': '获取音频数据失败',
|
|
||||||
'1106': 'SpeakerID重复',
|
|
||||||
'1107': 'SpeakerID未找到',
|
|
||||||
'1108': '音频转码失败',
|
|
||||||
'1109': 'WER检测错误,上传音频与请求携带文本对比字错率过高',
|
|
||||||
'1111': 'AED检测错误,通常由于音频不包含说话声',
|
|
||||||
'1112': 'SNR检测错误,通常由于信噪比过高',
|
|
||||||
'1113': '降噪处理失败',
|
|
||||||
'1114': '音频质量低,降噪失败',
|
|
||||||
'1122': '未检测到人声',
|
|
||||||
'1123': '已达上传次数限制(同一个音色支持10次上传)'
|
|
||||||
};
|
|
||||||
|
|
||||||
// HTTP 公共错误码映射表
|
|
||||||
const httpErrorMap = {
|
|
||||||
'400': '请求参数错误',
|
|
||||||
'401': 'Access Key不合法或签名错误',
|
|
||||||
'403': '权限不足',
|
|
||||||
'404': '接口不存在',
|
|
||||||
'429': '请求过于频繁',
|
|
||||||
'500': '服务器内部错误',
|
|
||||||
'502': '服务故障',
|
|
||||||
'503': '服务暂时不可用',
|
|
||||||
'504': '服务超时'
|
|
||||||
};
|
|
||||||
|
|
||||||
// 匹配业务错误码
|
|
||||||
const businessErrorMatch = errorMsg.match(/业务错误\s*(\d+):/);
|
|
||||||
if (businessErrorMatch) {
|
|
||||||
const code = businessErrorMatch[1];
|
|
||||||
const desc = voiceCloneErrorMap[code] || errorMsg.split(':')[1]?.trim() || '未知错误';
|
|
||||||
return `训练失败:${desc}\n(业务错误码 ${code})`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 匹配旧格式的业务错误码
|
|
||||||
for (const [code, desc] of Object.entries(voiceCloneErrorMap)) {
|
|
||||||
if (errorMsg.includes(code)) {
|
|
||||||
return `训练失败:${desc}\n(业务错误码 ${code})`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 匹配HTTP状态码
|
|
||||||
const httpErrorMatch = errorMsg.match(/HTTP\s*(\d+)/);
|
|
||||||
if (httpErrorMatch) {
|
|
||||||
const code = httpErrorMatch[1];
|
|
||||||
const desc = httpErrorMap[code] || '请求失败';
|
|
||||||
// 提取完整的错误信息
|
|
||||||
return `训练失败:${desc}\n(HTTP ${code})\n${errorMsg}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 匹配旧格式的HTTP状态码
|
|
||||||
for (const [code, desc] of Object.entries(httpErrorMap)) {
|
|
||||||
if (errorMsg.includes(`状态码: ${code}`) || errorMsg.includes(`状态码:${code}`)) {
|
|
||||||
return `训练失败:${desc}\n(HTTP ${code})`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return `训练失败:${errorMsg}`;
|
|
||||||
}
|
}
|
||||||
return '训练失败';
|
return '训练失败';
|
||||||
default:
|
default:
|
||||||
@@ -384,7 +318,7 @@ export default {
|
|||||||
}, (error) => {
|
}, (error) => {
|
||||||
// API调用失败,刷新列表以获取最新状态
|
// API调用失败,刷新列表以获取最新状态
|
||||||
console.error('API调用失败:', error);
|
console.error('API调用失败:', error);
|
||||||
this.$message.error('请求失败');
|
this.$message.error('克隆失败,请将鼠标悬停在错误提示上,查看错误详情');
|
||||||
this.fetchVoiceCloneList();
|
this.fetchVoiceCloneList();
|
||||||
row._submitting = false;
|
row._submitting = false;
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user