This commit is contained in:
DelLevin-Home
2026-06-16 13:03:06 +08:00
parent 2e05854f9d
commit bb66913eab
5 changed files with 63 additions and 24 deletions

View File

@@ -58,8 +58,9 @@ def _default_config():
'top_k': 5, 'top_p': 1.0, 'temperature': 1.0,
'batch_size': 1, 'speed_factor': 1.0, 'seed': -1,
'gpt_model_dir': '', 'sovits_model_dir': '',
'gpt_model_dir_mode': 'absolute', 'sovits_model_dir_mode': 'absolute',
'last_gpt_model': '', 'last_sovits_model': '',
'refer_audio_folder': '',
'refer_audio_folder': '', 'refer_audio_folder_mode': 'absolute',
}
@@ -230,12 +231,16 @@ def get_config():
cfg = _load_config()
cfg['engine_status'] = _engine_status
# 扫描模型列表
gpt_dir = cfg.get('gpt_model_dir', '')
sovits_dir = cfg.get('sovits_model_dir', '')
sovits_path = cfg.get('sovits_project_path', '')
gpt_dir_raw = cfg.get('gpt_model_dir', '')
gpt_dir = gpt_dir_raw if cfg.get('gpt_model_dir_mode') == 'absolute' else os.path.join(sovits_path, gpt_dir_raw)
sovits_dir_raw = cfg.get('sovits_model_dir', '')
sovits_dir = sovits_dir_raw if cfg.get('sovits_model_dir_mode') == 'absolute' else os.path.join(sovits_path, sovits_dir_raw)
cfg['gpt_models'] = _scan_models(gpt_dir, '*.ckpt')
cfg['sovits_models'] = _scan_models(sovits_dir, '*.pth')
# 扫描参考音频
refer_folder = cfg.get('refer_audio_folder', '')
refer_raw = cfg.get('refer_audio_folder', '')
refer_folder = refer_raw if cfg.get('refer_audio_folder_mode') == 'absolute' else os.path.join(sovits_path, refer_raw)
if refer_folder and os.path.isdir(refer_folder):
AUDIO_EXTS = ('.wav', '.mp3', '.flac', '.ogg', '.aac', '.m4a', '.wma')
files = [os.path.join(refer_folder, f) for f in os.listdir(refer_folder)
@@ -255,8 +260,9 @@ def save_config():
'last_prompt_text', 'last_prompt_lang',
'last_text_lang', 'last_text_split_method',
'top_k', 'top_p', 'temperature', 'batch_size', 'speed_factor', 'seed',
'gpt_model_dir', 'sovits_model_dir',
'last_gpt_model', 'last_sovits_model', 'refer_audio_folder'):
'gpt_model_dir', 'sovits_model_dir', 'refer_audio_folder',
'gpt_model_dir_mode', 'sovits_model_dir_mode', 'refer_audio_folder_mode',
'last_gpt_model', 'last_sovits_model'):
if key in data:
cfg[key] = data[key]
_save_config(cfg)
@@ -329,8 +335,10 @@ def switch_model():
return jsonify({'success': False, 'error': '缺少参数'}), 400
cfg = _load_config()
sovits_path = cfg.get('sovits_project_path', '')
if model_type == 'gpt':
model_dir = cfg.get('gpt_model_dir', '')
model_dir_raw = cfg.get('gpt_model_dir', '')
model_dir = model_dir_raw if cfg.get('gpt_model_dir_mode') == 'absolute' else os.path.join(sovits_path, model_dir_raw)
full_path = os.path.join(model_dir, filename) if model_dir else filename
ok, err = _reload_model('reload_gpt', full_path)
if ok:
@@ -339,7 +347,8 @@ def switch_model():
return jsonify({'success': True, 'message': f'GPT 模型已切换: {filename}'})
return jsonify({'success': False, 'error': err})
elif model_type == 'sovits':
model_dir = cfg.get('sovits_model_dir', '')
model_dir_raw = cfg.get('sovits_model_dir', '')
model_dir = model_dir_raw if cfg.get('sovits_model_dir_mode') == 'absolute' else os.path.join(sovits_path, model_dir_raw)
full_path = os.path.join(model_dir, filename) if model_dir else filename
ok, err = _reload_model('reload_sovits', full_path)
if ok:

View File

@@ -13,8 +13,11 @@
"seed": -1,
"gpt_model_dir": "E:\\AI\\GPT-SoVITS-v4\\GPT_weights_v2",
"sovits_model_dir": "E:\\AI\\GPT-SoVITS-v4\\SoVITS_weights_v2",
"gpt_model_dir_mode": "absolute",
"sovits_model_dir_mode": "absolute",
"last_gpt_model": "bubu-e15.ckpt",
"last_sovits_model": "bubu_e4_s68.pth",
"refer_audio_folder": "D:\\UserData\\Desktop\\声音素材\\参考音频",
"last_sovits_model": "bubu_e8_s136.pth",
"refer_audio_folder": "E:\\AI\\GPT-SoVITS-v4\\参考音频",
"refer_audio_folder_mode": "absolute",
"config_yaml": "GPT_SoVITS/configs/tts_infer.yaml"
}

Binary file not shown.

View File

@@ -60,6 +60,9 @@
border-color: #0078d4; box-shadow: 0 0 0 2px rgba(0,120,212,0.06);
}
.input-group.no-icon input, .input-group.no-icon select { padding-left: 10px; }
.path-row { display: flex; gap: 6px; align-items: flex-end; }
.path-row select { width: 90px; flex-shrink: 0; padding: 7px 6px; font-size: 12px; }
.path-row input { flex: 1; padding-left: 10px !important; }
.text-input {
width: 100%; padding: 10px 12px; border: 1px solid #e0e0e0; border-radius: 6px;
@@ -301,7 +304,7 @@
<select id="quickSwitch" style="flex:1;">
<option value="">选择模型组</option>
</select>
<button class="btn btn-outline btn-sm" onclick="quickSwitchRandom()" style="white-space:nowrap;"><i class="fas fa-refresh"></i> 随机</button>
<button class="btn btn-outline btn-sm" onclick="quickSwitchRandom()" style="white-space:nowrap;"><i class="fas fa-refresh"></i> 模型随机参数</button>
</div>
<div style="display:flex;gap:6px;margin-top:6px;">
<button class="btn btn-outline btn-sm" onclick="quickSwitchPreset('rich_emotion')" style="flex:1;font-size:11px;">情感更丰富</button>
@@ -313,8 +316,8 @@
<div class="section-title-row" style="margin-top:8px;">
<span class="title-left"><i class="fas fa-brain"></i> 模型切换</span>
<div style="display:flex;gap:4px;">
<button class="btn btn-outline btn-sm" onclick="switchModels()"><i class="fas fa-refresh"></i> 切换</button>
<button class="btn btn-outline btn-sm" onclick="saveModelSelection()"><i class="fas fa-floppy-disk"></i> 保存</button>
<button class="btn btn-outline btn-sm" onclick="switchModels()"><i class="fas fa-refresh"></i> 切换模型(接口)</button>
<button class="btn btn-outline btn-sm" onclick="saveModelSelection()"><i class="fas fa-floppy-disk"></i> 保存配置</button>
</div>
</div>
<div class="input-group">
@@ -392,7 +395,7 @@
<div class="section-card">
<div class="section-title" style="display:flex;align-items:center;justify-content:space-between;">
<span><i class="fas fa-tags"></i> 推理参数</span>
<button class="btn btn-outline btn-sm" onclick="saveInferConfig()"><i class="fas fa-floppy-disk"></i> 保存</button>
<button class="btn btn-outline btn-sm" onclick="saveInferConfig()"><i class="fas fa-floppy-disk"></i> 保存推理配置</button>
</div>
<div class="input-group no-icon">
<label>文本分段</label>
@@ -526,15 +529,21 @@
<div class="section-title"><i class="fas fa-folder"></i> 模型文件夹</div>
<div class="input-group">
<label for="modalGptModelDir">GPT 模型文件夹</label>
<div class="input-wrap">
<i class="fas fa-folder-open"></i>
<div class="path-row">
<select id="modalGptModelDirMode">
<option value="absolute">绝对路径</option>
<option value="relative">相对路径</option>
</select>
<input type="text" id="modalGptModelDir" placeholder="含 .ckpt 文件的文件夹路径">
</div>
</div>
<div class="input-group">
<label for="modalSovitsModelDir">SoVITS 模型文件夹</label>
<div class="input-wrap">
<i class="fas fa-folder-open"></i>
<div class="path-row">
<select id="modalSovitsModelDirMode">
<option value="absolute">绝对路径</option>
<option value="relative">相对路径</option>
</select>
<input type="text" id="modalSovitsModelDir" placeholder="含 .pth 文件的文件夹路径">
</div>
</div>
@@ -547,8 +556,11 @@
<div class="section-title"><i class="fas fa-folder-open"></i> 参考音频文件夹</div>
<div class="input-group">
<label for="modalAudioFolder">音频文件夹路径</label>
<div class="input-wrap">
<i class="fas fa-folder-open"></i>
<div class="path-row">
<select id="modalAudioFolderMode">
<option value="absolute">绝对路径</option>
<option value="relative">相对路径</option>
</select>
<input type="text" id="modalAudioFolder" placeholder="例如 D:\声音素材\参考音频">
</div>
</div>
@@ -620,6 +632,9 @@
if (cfg.gpt_model_dir) document.getElementById('modalGptModelDir').value = cfg.gpt_model_dir;
if (cfg.sovits_model_dir) document.getElementById('modalSovitsModelDir').value = cfg.sovits_model_dir;
if (cfg.refer_audio_folder) document.getElementById('modalAudioFolder').value = cfg.refer_audio_folder;
document.getElementById('modalGptModelDirMode').value = cfg.gpt_model_dir_mode || 'absolute';
document.getElementById('modalSovitsModelDirMode').value = cfg.sovits_model_dir_mode || 'absolute';
document.getElementById('modalAudioFolderMode').value = cfg.refer_audio_folder_mode || 'absolute';
} catch (e) { showMessage('加载配置失败: ' + e.message, 'error'); }
checkEngineStatus();
}
@@ -635,7 +650,10 @@
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sovits_project_path: sovitsPath, sovits_config_yaml: configYaml,
gpt_model_dir: gptDir, sovits_model_dir: sovitsDir, refer_audio_folder: audioFolder
gpt_model_dir: gptDir, sovits_model_dir: sovitsDir, refer_audio_folder: audioFolder,
gpt_model_dir_mode: document.getElementById('modalGptModelDirMode').value,
sovits_model_dir_mode: document.getElementById('modalSovitsModelDirMode').value,
refer_audio_folder_mode: document.getElementById('modalAudioFolderMode').value
})
});
showMessage('设置已保存', 'success');
@@ -662,7 +680,11 @@
var sovitsDir = document.getElementById('modalSovitsModelDir').value.trim();
await fetch('/ai-dubbing/config', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ gpt_model_dir: gptDir, sovits_model_dir: sovitsDir })
body: JSON.stringify({
gpt_model_dir: gptDir, sovits_model_dir: sovitsDir,
gpt_model_dir_mode: document.getElementById('modalGptModelDirMode').value,
sovits_model_dir_mode: document.getElementById('modalSovitsModelDirMode').value
})
});
showMessage('文件夹配置已保存', 'success');
refreshModels();
@@ -672,7 +694,10 @@
var folder = document.getElementById('modalAudioFolder').value.trim();
fetch('/ai-dubbing/config', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refer_audio_folder: folder })
body: JSON.stringify({
refer_audio_folder: folder,
refer_audio_folder_mode: document.getElementById('modalAudioFolderMode').value
})
}).then(function() { showMessage('已保存', 'success'); });
}

View File

@@ -10,7 +10,9 @@ from config import JIEBA_DICT_FILE, TOKEN_FILE_PATH
# 可选依赖
try:
import jieba
import contextlib, io
with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(io.StringIO()):
import jieba
JIEBA_AVAILABLE = True
except ImportError:
JIEBA_AVAILABLE = False