Merge pull request #3001 from xinnan-tech/py_fix_clone_languages

fix: 克隆音色未显示
This commit is contained in:
wengzh
2026-03-12 15:51:57 +08:00
committed by GitHub
17 changed files with 60 additions and 5 deletions
@@ -17,4 +17,7 @@ public class VoiceCloneDTO {
@Schema(description = "用户ID")
private Long userId;
@Schema(description = "语言")
private String languages;
}
@@ -28,6 +28,9 @@ public class VoiceCloneResponseDTO {
@Schema(description = "声音id")
private String voiceId;
@Schema(description = "语言")
private String languages;
@Schema(description = "用户ID(关联用户表)")
private Long userId;
@@ -31,6 +31,9 @@ public class VoiceCloneEntity {
@Schema(description = "声音id")
private String voiceId;
@Schema(description = "语言")
private String languages;
@Schema(description = "用户 ID(关联用户表)")
private Long userId;
@@ -116,6 +116,7 @@ public class VoiceCloneServiceImpl extends BaseServiceImpl<VoiceCloneDao, VoiceC
entity.setVoiceId(voiceId);
entity.setName(namePrefix + "_" + index);
entity.setUserId(dto.getUserId());
entity.setLanguages(dto.getLanguages());
entity.setTrainStatus(0); // 默认训练中
batchInsertList.add(entity);
}
@@ -0,0 +1,4 @@
-- 给声音克隆表添加语言字段
SET @col_exists = (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'ai_voice_clone' AND COLUMN_NAME = 'languages');
SET @sql = IF(@col_exists = 0, 'ALTER TABLE `ai_voice_clone` ADD COLUMN `languages` VARCHAR(50) DEFAULT NULL COMMENT ''语言'' AFTER `voice_id`', 'SELECT ''Column languages already exists'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
@@ -557,6 +557,13 @@ databaseChangeLog:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202603091051.sql
- changeSet:
id: 202603101723
author: RanChen
changes:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202603101723.sql
- changeSet:
id: 202603111131
author: DaGou12138
@@ -564,4 +571,3 @@ databaseChangeLog:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202603111131.sql
@@ -3,7 +3,7 @@
<mapper namespace="xiaozhi.modules.voiceclone.dao.VoiceCloneDao">
<select id="getTrainSuccess" resultType="xiaozhi.modules.model.dto.VoiceDTO">
select id, name, voice_id as voiceDemo
select id, name, voice_id as voiceDemo, languages
from ai_voice_clone
where model_id = #{modelId} and user_id = #{userId} and train_status = 2
</select>
@@ -25,6 +25,11 @@
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('voiceClone.languages')" prop="languages">
<el-input v-model="form.languages" :placeholder="$t('voiceClone.languagesPlaceholder')" style="width: 100%">
</el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
@@ -70,6 +75,9 @@ export default {
],
userId: [
{ required: true, message: this.$t('voiceClone.userIdRequired'), trigger: 'change' }
],
languages: [
{ required: true, message: this.$t('voiceClone.languagesRequired'), trigger: 'blur' }
]
}
}
+3
View File
@@ -1132,6 +1132,9 @@ export default {
'voiceClone.platformNamePlaceholder': 'Bitte Plattformname auswählen',
'voiceClone.voiceIdPlaceholder': 'Bitte Stimmen-ID eingeben und Enter drücken',
'voiceClone.userIdPlaceholder': 'Bitte Schlüsselwort eingeben, um Kontoinhaber auszuwählen',
'voiceClone.languages': 'Sprachen',
'voiceClone.languagesPlaceholder': 'Bitte Sprachen eingeben, z.B.: Deutsch, English',
'voiceClone.languagesRequired': 'Bitte Sprachen eingeben',
'voiceClone.waitingUpload': 'Wartet auf Upload',
'voiceClone.waitingTraining': 'Wartet auf Klon',
'voiceClone.training': 'Training',
+3
View File
@@ -1132,6 +1132,9 @@ export default {
'voiceClone.platformNamePlaceholder': 'Please select platform name',
'voiceClone.voiceIdPlaceholder': 'Please enter voice ID and press Enter',
'voiceClone.userIdPlaceholder': 'Please enter keyword to select account owner',
'voiceClone.languages': 'Languages',
'voiceClone.languagesPlaceholder': 'Please enter languages, e.g.: Chinese, English',
'voiceClone.languagesRequired': 'Please enter languages',
'voiceClone.waitingUpload': 'Waiting for upload',
'voiceClone.waitingTraining': 'Waiting for clone',
'voiceClone.training': 'Training',
+3
View File
@@ -1132,6 +1132,9 @@ export default {
'voiceClone.platformNamePlaceholder': 'Por favor, selecione o nome da plataforma',
'voiceClone.voiceIdPlaceholder': 'Por favor, insira o ID da voz e pressione Enter',
'voiceClone.userIdPlaceholder': 'Por favor, insira palavra-chave para selecionar o proprietário da conta',
'voiceClone.languages': 'Idiomas',
'voiceClone.languagesPlaceholder': 'Por favor, insira idiomas, ex.: Português, English',
'voiceClone.languagesRequired': 'Por favor, insira idiomas',
'voiceClone.waitingUpload': 'Aguardando envio',
'voiceClone.waitingTraining': 'Aguardando clonagem',
'voiceClone.training': 'Treinando',
+3
View File
@@ -1132,6 +1132,9 @@ export default {
'voiceClone.platformNamePlaceholder': 'Vui lòng chọn tên nền tảng',
'voiceClone.voiceIdPlaceholder': 'Vui lòng nhập ID giọng nói và nhấn Enter',
'voiceClone.userIdPlaceholder': 'Vui lòng nhập từ khóa để chọn chủ sở hữu tài khoản',
'voiceClone.languages': 'Ngôn ngữ',
'voiceClone.languagesPlaceholder': 'Vui lòng nhập ngôn ngữ, ví dụ: Tiếng Việt, English',
'voiceClone.languagesRequired': 'Vui lòng nhập ngôn ngữ',
'voiceClone.waitingUpload': 'Đang chờ tải lên',
'voiceClone.waitingTraining': 'Đang chờ nhân bản',
'voiceClone.training': 'Đang huấn luyện',
+3
View File
@@ -1132,6 +1132,9 @@ export default {
'voiceClone.platformNamePlaceholder': '请选择平台名称',
'voiceClone.voiceIdPlaceholder': '请输入音色ID并按回车',
'voiceClone.userIdPlaceholder': '请输入关键词选择归属账号',
'voiceClone.languages': '语言',
'voiceClone.languagesPlaceholder': '请输入语言,如:中文、English',
'voiceClone.languagesRequired': '请输入语言',
'voiceClone.waitingUpload': '待上传',
'voiceClone.waitingTraining': '待复刻',
'voiceClone.training': '训练中',
+3
View File
@@ -1132,6 +1132,9 @@ export default {
'voiceClone.platformNamePlaceholder': '請選擇平台名稱',
'voiceClone.voiceIdPlaceholder': '請輸入音色ID並按回车',
'voiceClone.userIdPlaceholder': '請輸入关键词選擇歸屬帳號',
'voiceClone.languages': '語言',
'voiceClone.languagesPlaceholder': '請輸入語言,如:中文、English',
'voiceClone.languagesRequired': '請輸入語言',
'voiceClone.waitingUpload': '待上傳',
'voiceClone.waitingTraining': '待複刻',
'voiceClone.training': '訓練中',
@@ -34,6 +34,8 @@
</span>
</template>
</el-table-column>
<el-table-column :label="$t('voiceClone.languages')" prop="languages"
align="center"></el-table-column>
<el-table-column :label="$t('voiceClone.trainStatus')" prop="trainStatus" align="center">
<template slot-scope="scope">
<div class="status-button" :class="getStatusButtonClass(scope.row)">
@@ -32,6 +32,8 @@
align="center"></el-table-column>
<el-table-column :label="$t('voiceClone.platformName')" prop="modelName"
align="center"></el-table-column>
<el-table-column :label="$t('voiceClone.languages')" prop="languages"
align="center"></el-table-column>
<el-table-column :label="$t('voiceClone.trainStatus')" prop="trainStatus" align="center">
<template slot-scope="scope">
{{ getTrainStatusText(scope.row) }}
@@ -122,7 +124,8 @@ export default {
voiceCloneForm: {
modelId: "",
voiceIds: [],
userId: null
userId: null,
languages: ""
}
};
},
@@ -198,7 +201,8 @@ export default {
this.voiceCloneForm = {
modelId: "",
voiceIds: [],
userId: null
userId: null,
languages: ""
};
this.$nextTick(() => {
if (this.$refs.voiceCloneForm) {
+4 -1
View File
@@ -753,7 +753,10 @@ export default {
// 根据选中的语言筛选音色
const filteredVoices = allVoices.filter(voice => {
if (!voice.languages) return false;
if (!voice.languages) {
// 对于没有语言信息的克隆音色,始终显示
return Boolean(voice.isClone);
}
const languagesArray = voice.languages.split(/[、;;,]/).map(lang => lang.trim()).filter(lang => lang);
return languagesArray.includes(this.selectedLanguage);
});