mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-24 08:03:53 +08:00
@@ -23,11 +23,23 @@ public class VoiceDTO implements Serializable {
|
|||||||
@Schema(description = "音频播放地址")
|
@Schema(description = "音频播放地址")
|
||||||
private String voiceDemo;
|
private String voiceDemo;
|
||||||
|
|
||||||
|
@Schema(description = "是否为克隆音色")
|
||||||
|
private Boolean isClone;
|
||||||
|
|
||||||
// 添加双参数构造函数,保持向后兼容
|
// 添加双参数构造函数,保持向后兼容
|
||||||
public VoiceDTO(String id, String name) {
|
public VoiceDTO(String id, String name) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.voiceDemo = null;
|
this.voiceDemo = null;
|
||||||
|
this.isClone = false; // 默认不是克隆音色
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加三参数构造函数,用于普通音色
|
||||||
|
public VoiceDTO(String id, String name, String voiceDemo) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.voiceDemo = voiceDemo;
|
||||||
|
this.isClone = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+3
@@ -136,6 +136,7 @@ public class TimbreServiceImpl extends BaseServiceImpl<TimbreDao, TimbreEntity>
|
|||||||
.map(entity -> {
|
.map(entity -> {
|
||||||
VoiceDTO dto = new VoiceDTO(entity.getId(), entity.getName());
|
VoiceDTO dto = new VoiceDTO(entity.getId(), entity.getName());
|
||||||
dto.setVoiceDemo(entity.getVoiceDemo());
|
dto.setVoiceDemo(entity.getVoiceDemo());
|
||||||
|
dto.setIsClone(false); // 设置为普通音色
|
||||||
return dto;
|
return dto;
|
||||||
})
|
})
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
@@ -152,6 +153,7 @@ public class TimbreServiceImpl extends BaseServiceImpl<TimbreDao, TimbreEntity>
|
|||||||
voiceDTO.setName(MessageUtils.getMessage(ErrorCode.VOICE_CLONE_PREFIX) + entity.getName());
|
voiceDTO.setName(MessageUtils.getMessage(ErrorCode.VOICE_CLONE_PREFIX) + entity.getName());
|
||||||
// 保留从数据库查询到的voiceDemo字段
|
// 保留从数据库查询到的voiceDemo字段
|
||||||
voiceDTO.setVoiceDemo(entity.getVoiceDemo());
|
voiceDTO.setVoiceDemo(entity.getVoiceDemo());
|
||||||
|
voiceDTO.setIsClone(true); // 设置为克隆音色
|
||||||
redisUtils.set(RedisKeys.getTimbreNameById(voiceDTO.getId()), voiceDTO.getName(),
|
redisUtils.set(RedisKeys.getTimbreNameById(voiceDTO.getId()), voiceDTO.getName(),
|
||||||
RedisUtils.NOT_EXPIRE);
|
RedisUtils.NOT_EXPIRE);
|
||||||
voiceDTOs.add(0, voiceDTO);
|
voiceDTOs.add(0, voiceDTO);
|
||||||
@@ -214,6 +216,7 @@ public class TimbreServiceImpl extends BaseServiceImpl<TimbreDao, TimbreEntity>
|
|||||||
TimbreEntity entity = list.get(0);
|
TimbreEntity entity = list.get(0);
|
||||||
VoiceDTO dto = new VoiceDTO(entity.getId(), entity.getName());
|
VoiceDTO dto = new VoiceDTO(entity.getId(), entity.getName());
|
||||||
dto.setVoiceDemo(entity.getVoiceDemo());
|
dto.setVoiceDemo(entity.getVoiceDemo());
|
||||||
|
dto.setIsClone(false); // 设置为普通音色
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -779,6 +779,16 @@ export default {
|
|||||||
'roleConfig.fetchConfigFailed': 'Konfiguration konnte nicht abgerufen werden',
|
'roleConfig.fetchConfigFailed': 'Konfiguration konnte nicht abgerufen werden',
|
||||||
'roleConfig.fetchModelsFailed': 'Modellliste konnte nicht abgerufen werden',
|
'roleConfig.fetchModelsFailed': 'Modellliste konnte nicht abgerufen werden',
|
||||||
'roleConfig.fetchPluginsFailed': 'Plugin-Liste konnte nicht abgerufen werden',
|
'roleConfig.fetchPluginsFailed': 'Plugin-Liste konnte nicht abgerufen werden',
|
||||||
|
'roleConfig.cannotResumeAudio': 'Audio-Wiedergabe kann nicht fortgesetzt werden',
|
||||||
|
'roleConfig.selectVoiceFirst': 'Bitte wählen Sie zuerst eine Stimme aus',
|
||||||
|
'roleConfig.audioLoadTimeout': 'Audio-Laden dauert zu lange, bitte versuchen Sie es später erneut',
|
||||||
|
'roleConfig.cloneAudioPlayFailed': 'Klon-Audio-Wiedergabe fehlgeschlagen',
|
||||||
|
'roleConfig.cannotPlayCloneAudio': 'Klon-Audio kann nicht abgespielt werden',
|
||||||
|
'roleConfig.getCloneAudioFailed': 'Klon-Audio konnte nicht abgerufen werden',
|
||||||
|
'roleConfig.noPreviewAudio': 'Diese Stimme hat keine Vorschau-Audio-Datei',
|
||||||
|
'roleConfig.audioPlayFailed': 'Audio-Wiedergabe fehlgeschlagen',
|
||||||
|
'roleConfig.cannotPlayAudio': 'Audio kann nicht abgespielt werden',
|
||||||
|
'roleConfig.audioPlayError': 'Fehler bei der Audio-Wiedergabe',
|
||||||
|
|
||||||
// Function management dialog text
|
// Function management dialog text
|
||||||
'functionDialog.title': 'Funktionsverwaltung',
|
'functionDialog.title': 'Funktionsverwaltung',
|
||||||
@@ -919,6 +929,10 @@ export default {
|
|||||||
'ttsModel.selectVoiceToDelete': 'Bitte wählen Sie Stimmen zum Löschen aus',
|
'ttsModel.selectVoiceToDelete': 'Bitte wählen Sie Stimmen zum Löschen aus',
|
||||||
'ttsModel.warning': 'Warnung',
|
'ttsModel.warning': 'Warnung',
|
||||||
'ttsModel.confirmDeleteVoice': 'Sind Sie sicher, dass Sie {count} Stimmen löschen möchten?',
|
'ttsModel.confirmDeleteVoice': 'Sind Sie sicher, dass Sie {count} Stimmen löschen möchten?',
|
||||||
|
'ttsModel.voiceCodeNameLanguageRequired': 'Stimmcode, Stimmaname und Sprache können nicht leer sein',
|
||||||
|
'ttsModel.deleteCancelled': 'Löschvorgang abgebrochen',
|
||||||
|
'ttsModel.updateSuccess': 'Aktualisierung erfolgreich',
|
||||||
|
'ttsModel.saveSuccess': 'Speicherung erfolgreich',
|
||||||
|
|
||||||
// OTA Management Page Text
|
// OTA Management Page Text
|
||||||
'otaManagement.firmwareManagement': 'Firmware-Verwaltung',
|
'otaManagement.firmwareManagement': 'Firmware-Verwaltung',
|
||||||
|
|||||||
@@ -779,6 +779,16 @@ export default {
|
|||||||
'roleConfig.fetchConfigFailed': 'Failed to fetch configuration',
|
'roleConfig.fetchConfigFailed': 'Failed to fetch configuration',
|
||||||
'roleConfig.fetchModelsFailed': 'Failed to fetch model list',
|
'roleConfig.fetchModelsFailed': 'Failed to fetch model list',
|
||||||
'roleConfig.fetchPluginsFailed': 'Failed to fetch plugin list',
|
'roleConfig.fetchPluginsFailed': 'Failed to fetch plugin list',
|
||||||
|
'roleConfig.cannotResumeAudio': 'Cannot resume audio playback',
|
||||||
|
'roleConfig.selectVoiceFirst': 'Please select a voice first',
|
||||||
|
'roleConfig.audioLoadTimeout': 'Audio loading takes too long, please try again later',
|
||||||
|
'roleConfig.cloneAudioPlayFailed': 'Clone audio playback failed',
|
||||||
|
'roleConfig.cannotPlayCloneAudio': 'Cannot play clone audio',
|
||||||
|
'roleConfig.getCloneAudioFailed': 'Failed to get clone audio',
|
||||||
|
'roleConfig.noPreviewAudio': 'This voice has no preview audio available',
|
||||||
|
'roleConfig.audioPlayFailed': 'Audio playback failed',
|
||||||
|
'roleConfig.cannotPlayAudio': 'Cannot play audio',
|
||||||
|
'roleConfig.audioPlayError': 'Error occurred during audio playback',
|
||||||
|
|
||||||
// Function management dialog text
|
// Function management dialog text
|
||||||
'functionDialog.title': 'Function Management',
|
'functionDialog.title': 'Function Management',
|
||||||
@@ -919,6 +929,10 @@ export default {
|
|||||||
'ttsModel.selectVoiceToDelete': 'Please select voices to delete',
|
'ttsModel.selectVoiceToDelete': 'Please select voices to delete',
|
||||||
'ttsModel.warning': 'Warning',
|
'ttsModel.warning': 'Warning',
|
||||||
'ttsModel.confirmDeleteVoice': 'Are you sure to delete {count} voices?',
|
'ttsModel.confirmDeleteVoice': 'Are you sure to delete {count} voices?',
|
||||||
|
'ttsModel.voiceCodeNameLanguageRequired': 'Voice code, voice name and language type cannot be empty',
|
||||||
|
'ttsModel.deleteCancelled': 'Deletion cancelled',
|
||||||
|
'ttsModel.updateSuccess': 'Update successful',
|
||||||
|
'ttsModel.saveSuccess': 'Save successful',
|
||||||
|
|
||||||
// OTA Management Page Text
|
// OTA Management Page Text
|
||||||
'otaManagement.firmwareManagement': 'Firmware Management',
|
'otaManagement.firmwareManagement': 'Firmware Management',
|
||||||
|
|||||||
@@ -779,6 +779,16 @@ export default {
|
|||||||
'roleConfig.fetchConfigFailed': 'Không thể lấy cấu hình',
|
'roleConfig.fetchConfigFailed': 'Không thể lấy cấu hình',
|
||||||
'roleConfig.fetchModelsFailed': 'Không thể tải danh sách mô hình',
|
'roleConfig.fetchModelsFailed': 'Không thể tải danh sách mô hình',
|
||||||
'roleConfig.fetchPluginsFailed': 'Không thể tải danh sách plugin',
|
'roleConfig.fetchPluginsFailed': 'Không thể tải danh sách plugin',
|
||||||
|
'roleConfig.cannotResumeAudio': 'Không thể tiếp tục phát âm thanh',
|
||||||
|
'roleConfig.selectVoiceFirst': 'Vui lòng chọn giọng nói trước',
|
||||||
|
'roleConfig.audioLoadTimeout': 'Tải âm thanh mất quá nhiều thời gian, vui lòng thử lại sau',
|
||||||
|
'roleConfig.cloneAudioPlayFailed': 'Phát âm thanh sao chép thất bại',
|
||||||
|
'roleConfig.cannotPlayCloneAudio': 'Không thể phát âm thanh sao chép',
|
||||||
|
'roleConfig.getCloneAudioFailed': 'Không thể lấy âm thanh sao chép',
|
||||||
|
'roleConfig.noPreviewAudio': 'Giọng nói này không có âm thanh xem trước',
|
||||||
|
'roleConfig.audioPlayFailed': 'Phát âm thanh thất bại',
|
||||||
|
'roleConfig.cannotPlayAudio': 'Không thể phát âm thanh',
|
||||||
|
'roleConfig.audioPlayError': 'Lỗi trong quá trình phát âm thanh',
|
||||||
|
|
||||||
// Function management dialog text
|
// Function management dialog text
|
||||||
'functionDialog.title': 'Quản lý chức năng',
|
'functionDialog.title': 'Quản lý chức năng',
|
||||||
@@ -919,6 +929,10 @@ export default {
|
|||||||
'ttsModel.selectVoiceToDelete': 'Vui lòng chọn giọng nói để xóa',
|
'ttsModel.selectVoiceToDelete': 'Vui lòng chọn giọng nói để xóa',
|
||||||
'ttsModel.warning': 'Cảnh báo',
|
'ttsModel.warning': 'Cảnh báo',
|
||||||
'ttsModel.confirmDeleteVoice': 'Bạn có chắc chắn muốn xóa {count} giọng nói?',
|
'ttsModel.confirmDeleteVoice': 'Bạn có chắc chắn muốn xóa {count} giọng nói?',
|
||||||
|
'ttsModel.voiceCodeNameLanguageRequired': 'Mã giọng nói, tên giọng nói và loại ngôn ngữ không được để trống',
|
||||||
|
'ttsModel.deleteCancelled': 'Xóa đã bị hủy',
|
||||||
|
'ttsModel.updateSuccess': 'Cập nhật thành công',
|
||||||
|
'ttsModel.saveSuccess': 'Lưu thành công',
|
||||||
|
|
||||||
// OTA Management Page Text
|
// OTA Management Page Text
|
||||||
'otaManagement.firmwareManagement': 'Quản lý firmware',
|
'otaManagement.firmwareManagement': 'Quản lý firmware',
|
||||||
|
|||||||
@@ -779,6 +779,16 @@ export default {
|
|||||||
'roleConfig.fetchConfigFailed': '获取配置失败',
|
'roleConfig.fetchConfigFailed': '获取配置失败',
|
||||||
'roleConfig.fetchModelsFailed': '获取模型列表失败',
|
'roleConfig.fetchModelsFailed': '获取模型列表失败',
|
||||||
'roleConfig.fetchPluginsFailed': '获取插件列表失败',
|
'roleConfig.fetchPluginsFailed': '获取插件列表失败',
|
||||||
|
'roleConfig.cannotResumeAudio': '无法恢复播放音频',
|
||||||
|
'roleConfig.selectVoiceFirst': '请先选择一个音色',
|
||||||
|
'roleConfig.audioLoadTimeout': '音频加载时间较长,请稍后重试',
|
||||||
|
'roleConfig.cloneAudioPlayFailed': '克隆音频播放失败',
|
||||||
|
'roleConfig.cannotPlayCloneAudio': '无法播放克隆音频',
|
||||||
|
'roleConfig.getCloneAudioFailed': '获取克隆音频失败',
|
||||||
|
'roleConfig.noPreviewAudio': '该音色暂无可预览的音频',
|
||||||
|
'roleConfig.audioPlayFailed': '音频播放失败',
|
||||||
|
'roleConfig.cannotPlayAudio': '无法播放音频',
|
||||||
|
'roleConfig.audioPlayError': '播放音频过程出错',
|
||||||
|
|
||||||
// 功能管理对话框文本
|
// 功能管理对话框文本
|
||||||
'functionDialog.title': '功能管理',
|
'functionDialog.title': '功能管理',
|
||||||
@@ -919,6 +929,10 @@ export default {
|
|||||||
'ttsModel.selectVoiceToDelete': '请选择要删除的音色',
|
'ttsModel.selectVoiceToDelete': '请选择要删除的音色',
|
||||||
'ttsModel.warning': '警告',
|
'ttsModel.warning': '警告',
|
||||||
'ttsModel.confirmDeleteVoice': '确定要删除{count}个音色吗?',
|
'ttsModel.confirmDeleteVoice': '确定要删除{count}个音色吗?',
|
||||||
|
'ttsModel.voiceCodeNameLanguageRequired': '音色编码、音色名称和语言类型不能为空',
|
||||||
|
'ttsModel.deleteCancelled': '删除已取消',
|
||||||
|
'ttsModel.updateSuccess': '更新成功',
|
||||||
|
'ttsModel.saveSuccess': '保存成功',
|
||||||
|
|
||||||
// OTA管理页面文本
|
// OTA管理页面文本
|
||||||
'otaManagement.firmwareManagement': '固件管理',
|
'otaManagement.firmwareManagement': '固件管理',
|
||||||
|
|||||||
@@ -779,6 +779,16 @@ export default {
|
|||||||
'roleConfig.fetchConfigFailed': '獲取配置失敗',
|
'roleConfig.fetchConfigFailed': '獲取配置失敗',
|
||||||
'roleConfig.fetchModelsFailed': '獲取模型列表失敗',
|
'roleConfig.fetchModelsFailed': '獲取模型列表失敗',
|
||||||
'roleConfig.fetchPluginsFailed': '獲取插件列表失敗',
|
'roleConfig.fetchPluginsFailed': '獲取插件列表失敗',
|
||||||
|
'roleConfig.cannotResumeAudio': '無法恢復播放音訊',
|
||||||
|
'roleConfig.selectVoiceFirst': '請先選擇一個音色',
|
||||||
|
'roleConfig.audioLoadTimeout': '音訊載入時間較長,請稍後重試',
|
||||||
|
'roleConfig.cloneAudioPlayFailed': '克隆音訊播放失敗',
|
||||||
|
'roleConfig.cannotPlayCloneAudio': '無法播放克隆音訊',
|
||||||
|
'roleConfig.getCloneAudioFailed': '獲取克隆音訊失敗',
|
||||||
|
'roleConfig.noPreviewAudio': '該音色暫無可預覽的音訊',
|
||||||
|
'roleConfig.audioPlayFailed': '音訊播放失敗',
|
||||||
|
'roleConfig.cannotPlayAudio': '無法播放音訊',
|
||||||
|
'roleConfig.audioPlayError': '播放音訊過程出錯',
|
||||||
|
|
||||||
// 功能管理對話框文本
|
// 功能管理對話框文本
|
||||||
'functionDialog.title': '功能管理',
|
'functionDialog.title': '功能管理',
|
||||||
@@ -917,6 +927,10 @@ export default {
|
|||||||
'ttsModel.selectVoiceToDelete': '請選擇要刪除的音色',
|
'ttsModel.selectVoiceToDelete': '請選擇要刪除的音色',
|
||||||
'ttsModel.warning': '警告',
|
'ttsModel.warning': '警告',
|
||||||
'ttsModel.confirmDeleteVoice': '確定要刪除{count}個音色嗎?',
|
'ttsModel.confirmDeleteVoice': '確定要刪除{count}個音色嗎?',
|
||||||
|
'ttsModel.voiceCodeNameLanguageRequired': '音色編碼、音色名稱和語言類型不能為空',
|
||||||
|
'ttsModel.deleteCancelled': '刪除已取消',
|
||||||
|
'ttsModel.updateSuccess': '更新成功',
|
||||||
|
'ttsModel.saveSuccess': '保存成功',
|
||||||
'ttsModel.operationFailed': '操作失敗',
|
'ttsModel.operationFailed': '操作失敗',
|
||||||
'ttsModel.operationClosed': '操作已關閉',
|
'ttsModel.operationClosed': '操作已關閉',
|
||||||
|
|
||||||
|
|||||||
@@ -599,21 +599,15 @@ export default {
|
|||||||
this.voiceOptions = data.data.map((voice) => ({
|
this.voiceOptions = data.data.map((voice) => ({
|
||||||
value: voice.id,
|
value: voice.id,
|
||||||
label: voice.name,
|
label: voice.name,
|
||||||
// 复制音频相关字段,确保hasAudioPreview能检测到
|
// 只保留后端实际返回的音频相关字段
|
||||||
voiceDemo: voice.voiceDemo,
|
voiceDemo: voice.voiceDemo,
|
||||||
demoUrl: voice.demoUrl,
|
|
||||||
audioUrl: voice.audioUrl,
|
|
||||||
voice_demo: voice.voice_demo,
|
voice_demo: voice.voice_demo,
|
||||||
sample_voice: voice.sample_voice,
|
// 使用后端实际返回的 isClone 字段
|
||||||
referenceAudio: voice.referenceAudio,
|
isClone: Boolean(voice.isClone),
|
||||||
// 新增:添加克隆音频相关字段
|
// 保存训练状态字段
|
||||||
cloneAudioUrl: voice.cloneAudioUrl,
|
|
||||||
hasCloneAudio: voice.hasCloneAudio || false,
|
|
||||||
// 保存训练状态字段,用于判断是否为克隆音频
|
|
||||||
train_status: voice.trainStatus,
|
train_status: voice.trainStatus,
|
||||||
}));
|
}));
|
||||||
// 保存完整的音色信息,添加调试信息
|
// 保存完整的音色信息,添加调试信息
|
||||||
console.log("获取到的音色数据:", data.data);
|
|
||||||
this.voiceDetails = data.data.reduce((acc, voice) => {
|
this.voiceDetails = data.data.reduce((acc, voice) => {
|
||||||
acc[voice.id] = voice;
|
acc[voice.id] = voice;
|
||||||
return acc;
|
return acc;
|
||||||
@@ -746,32 +740,15 @@ export default {
|
|||||||
},
|
},
|
||||||
// 检查是否有音频预览
|
// 检查是否有音频预览
|
||||||
hasAudioPreview(item) {
|
hasAudioPreview(item) {
|
||||||
// 检查item中是否包含有效的音频URL字段或克隆音频字段
|
// 检查是否为克隆音频
|
||||||
// 克隆音频通过hasCloneAudio标志或ID格式判断(非TTS开头的ID)
|
// 使用后端实际返回的 isClone 字段
|
||||||
const isCloneAudio =
|
const isCloneAudio = Boolean(item.isClone);
|
||||||
item.hasCloneAudio || (item.value && !item.value.startsWith("TTS"));
|
|
||||||
|
|
||||||
const audioFields = [
|
// 检查是否有有效的音频URL,只使用后端实际返回的字段
|
||||||
item.voiceDemo,
|
const hasValidAudioUrl = !!((item.voice_demo || item.voiceDemo)?.trim());
|
||||||
item.demoUrl,
|
|
||||||
item.audioUrl,
|
|
||||||
item.voice_demo,
|
|
||||||
item.sample_voice,
|
|
||||||
item.referenceAudio,
|
|
||||||
item.cloneAudioUrl, // 克隆音频的URL
|
|
||||||
];
|
|
||||||
|
|
||||||
// 检查是否有任何音频字段是有效的URL
|
// 克隆音频始终显示播放按钮,普通音频需要有有效URL才显示
|
||||||
const hasUrlAudio = audioFields.some(
|
return isCloneAudio || hasValidAudioUrl;
|
||||||
(field) =>
|
|
||||||
field !== undefined &&
|
|
||||||
field !== null &&
|
|
||||||
typeof field === "string" &&
|
|
||||||
field.trim() !== "" &&
|
|
||||||
field.toLowerCase().startsWith("http")
|
|
||||||
);
|
|
||||||
|
|
||||||
return hasUrlAudio || isCloneAudio;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 播放/暂停音频切换
|
// 播放/暂停音频切换
|
||||||
@@ -782,7 +759,7 @@ export default {
|
|||||||
// 从暂停状态恢复播放
|
// 从暂停状态恢复播放
|
||||||
this.currentAudio.play().catch((error) => {
|
this.currentAudio.play().catch((error) => {
|
||||||
console.error("恢复播放失败:", error);
|
console.error("恢复播放失败:", error);
|
||||||
this.$message.warning("无法恢复播放音频");
|
this.$message.warning(this.$t('roleConfig.cannotResumeAudio'));
|
||||||
});
|
});
|
||||||
this.isPaused = false;
|
this.isPaused = false;
|
||||||
} else {
|
} else {
|
||||||
@@ -803,7 +780,7 @@ export default {
|
|||||||
const targetVoiceId = voiceId || this.form.ttsVoiceId;
|
const targetVoiceId = voiceId || this.form.ttsVoiceId;
|
||||||
|
|
||||||
if (!targetVoiceId) {
|
if (!targetVoiceId) {
|
||||||
this.$message.warning("请先选择一个音色");
|
this.$message.warning(this.$t('roleConfig.selectVoiceFirst'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -830,10 +807,8 @@ export default {
|
|||||||
let isCloneAudio = false;
|
let isCloneAudio = false;
|
||||||
|
|
||||||
if (voiceDetail) {
|
if (voiceDetail) {
|
||||||
// 首先检查是否是克隆音频(通过ID格式判断,非TTS开头的ID)
|
// 使用后端实际返回的 isClone 字段判断是否为克隆音频
|
||||||
isCloneAudio =
|
isCloneAudio = Boolean(voiceDetail.isClone);
|
||||||
voiceDetail.hasCloneAudio ||
|
|
||||||
(voiceDetail.id && !voiceDetail.id.startsWith("TTS"));
|
|
||||||
console.log(
|
console.log(
|
||||||
"克隆音频判断结果:",
|
"克隆音频判断结果:",
|
||||||
isCloneAudio,
|
isCloneAudio,
|
||||||
@@ -889,7 +864,7 @@ export default {
|
|||||||
// 设置超时,防止加载过长时间
|
// 设置超时,防止加载过长时间
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
if (this.currentAudio && this.playingVoice) {
|
if (this.currentAudio && this.playingVoice) {
|
||||||
this.$message.warning("音频加载时间较长,请稍后重试");
|
this.$message.warning(this.$t('roleConfig.audioLoadTimeout'));
|
||||||
this.playingVoice = false;
|
this.playingVoice = false;
|
||||||
}
|
}
|
||||||
}, 10000); // 10秒超时
|
}, 10000); // 10秒超时
|
||||||
@@ -898,7 +873,7 @@ export default {
|
|||||||
this.currentAudio.onerror = () => {
|
this.currentAudio.onerror = () => {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
console.error("克隆音频播放错误");
|
console.error("克隆音频播放错误");
|
||||||
this.$message.warning("克隆音频播放失败");
|
this.$message.warning(this.$t('roleConfig.cloneAudioPlayFailed'));
|
||||||
this.playingVoice = false;
|
this.playingVoice = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -920,12 +895,12 @@ export default {
|
|||||||
this.currentAudio.play().catch((error) => {
|
this.currentAudio.play().catch((error) => {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
console.error("播放克隆音频失败:", error);
|
console.error("播放克隆音频失败:", error);
|
||||||
this.$message.warning("无法播放克隆音频");
|
this.$message.warning(this.$t('roleConfig.cannotPlayCloneAudio'));
|
||||||
this.playingVoice = false;
|
this.playingVoice = false;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
this.$message.warning("获取克隆音频失败");
|
this.$message.warning(this.$t('roleConfig.getCloneAudioFailed'));
|
||||||
this.playingVoice = false;
|
this.playingVoice = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -933,14 +908,10 @@ export default {
|
|||||||
// 返回,避免继续执行下面的普通音频播放逻辑
|
// 返回,避免继续执行下面的普通音频播放逻辑
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// 对于普通音频,尝试各种可能的URL字段
|
// 对于普通音频,只使用后端实际返回的字段
|
||||||
audioUrl =
|
audioUrl =
|
||||||
voiceDetail.voiceDemo ||
|
voiceDetail.voiceDemo ||
|
||||||
voiceDetail.demoUrl ||
|
voiceDetail.voice_demo;
|
||||||
voiceDetail.audioUrl ||
|
|
||||||
voiceDetail.voice_demo ||
|
|
||||||
voiceDetail.sample_voice ||
|
|
||||||
voiceDetail.cloneAudioUrl; // 克隆音频URL
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有找到,尝试检查是否有URL格式的字段
|
// 如果没有找到,尝试检查是否有URL格式的字段
|
||||||
@@ -965,7 +936,7 @@ export default {
|
|||||||
|
|
||||||
if (!audioUrl) {
|
if (!audioUrl) {
|
||||||
// 如果没有音频URL,显示友好的提示
|
// 如果没有音频URL,显示友好的提示
|
||||||
this.$message.warning("该音色暂无可预览的音频");
|
this.$message.warning(this.$t('roleConfig.noPreviewAudio'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -984,7 +955,7 @@ export default {
|
|||||||
// 设置超时,防止加载过长时间
|
// 设置超时,防止加载过长时间
|
||||||
const timeoutId = setTimeout(() => {
|
const timeoutId = setTimeout(() => {
|
||||||
if (this.currentAudio && this.playingVoice) {
|
if (this.currentAudio && this.playingVoice) {
|
||||||
this.$message.warning("音频加载时间较长,请稍后重试");
|
this.$message.warning(this.$t('roleConfig.audioLoadTimeout'));
|
||||||
this.playingVoice = false;
|
this.playingVoice = false;
|
||||||
}
|
}
|
||||||
}, 10000); // 10秒超时
|
}, 10000); // 10秒超时
|
||||||
@@ -993,7 +964,7 @@ export default {
|
|||||||
this.currentAudio.onerror = () => {
|
this.currentAudio.onerror = () => {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
console.error("音频播放错误");
|
console.error("音频播放错误");
|
||||||
this.$message.warning("音频播放失败");
|
this.$message.warning(this.$t('roleConfig.audioPlayFailed'));
|
||||||
this.playingVoice = false;
|
this.playingVoice = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1011,13 +982,13 @@ export default {
|
|||||||
this.currentAudio.play().catch((error) => {
|
this.currentAudio.play().catch((error) => {
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
console.error("播放失败:", error);
|
console.error("播放失败:", error);
|
||||||
this.$message.warning("无法播放音频");
|
this.$message.warning(this.$t('roleConfig.cannotPlayAudio'));
|
||||||
this.playingVoice = false;
|
this.playingVoice = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("播放音频过程出错:", error);
|
console.error("播放音频过程出错:", error);
|
||||||
this.$message.error("播放音频过程出错");
|
this.$message.error(this.$t('roleConfig.audioPlayError'));
|
||||||
this.playingVoice = false;
|
this.playingVoice = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user