This commit is contained in:
DelLevin-Home
2026-06-17 10:43:33 +08:00
parent db033c661f
commit 05e733e872
18 changed files with 3399 additions and 254 deletions

View File

@@ -93,7 +93,7 @@
}
.slider-value { font-weight: 600; color: #0078d4; font-size: 12px; }
input[type="range"] {
width: 100%; height: 4px; -webkit-appearance: none; appearance: none;
width: 50%; height: 4px; -webkit-appearance: none; appearance: none;
background: #e0e0e0; border-radius: 2px; outline: none;
}
input[type="range"]::-webkit-slider-thumb {
@@ -212,9 +212,34 @@
}
.right-header h2 { font-size: 15px; font-weight: 600; color: #333; }
.right-body {
flex: 1; overflow-y: auto; padding: 16px 24px 24px;
flex: 1; overflow-y: auto; padding: 16px 24px 24px; min-height: 0;
}
/* 日志区域 */
.log-area {
flex: 1; flex-shrink: 0; display: flex; flex-direction: column;
background: #1e1e1e; color: #d4d4d4; border-top: 1px solid #3e3e3e;
min-height: 0;
}
.log-header {
display: flex; align-items: center; justify-content: space-between;
padding: 6px 10px; background: #2d2d2d; border-bottom: 1px solid #3e3e3e;
font-size: 11px; color: #888; flex-shrink: 0;
}
.log-header i { margin-right: 4px; }
.log-clear-btn {
background: none; border: 1px solid #555; color: #999;
border-radius: 4px; padding: 2px 8px; font-size: 10px;
cursor: pointer; transition: all 0.15s;
}
.log-clear-btn:hover { background: #3e3e3e; color: #ccc; border-color: #777; }
.log-content {
flex: 1; overflow-y: auto; padding: 6px 10px;
font-size: 11px; font-family: Consolas, "Courier New", monospace; line-height: 1.6;
}
.log-content::-webkit-scrollbar { width: 4px; }
.log-content::-webkit-scrollbar-thumb { background: #555; border-radius: 2px; }
/* 进度条 */
.progress-bar {
width: 100%; height: 8px; background: #f0f0f0; border-radius: 4px;
@@ -248,8 +273,8 @@
.stem-icon.vocals { background: linear-gradient(135deg, #0078d4, #005fa3); }
.stem-icon.instrumental { background: linear-gradient(135deg, #0a7a1a, #065f12); }
.stem-icon.other { background: linear-gradient(135deg, #f57c00, #e65100); }
.stem-info { flex: 1; }
.stem-name { font-size: 14px; font-weight: 600; color: #333; }
.stem-info { width: 180px; flex-shrink: 0; }
.stem-name { font-size: 14px; font-weight: 600; color: #333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stem-filename { font-size: 11px; color: #999; margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stem-actions { display: flex; gap: 6px; }
.stem-btn {
@@ -261,6 +286,35 @@
.stem-btn:hover { background: #f0f0f0; color: #333; border-color: #ccc; }
.stem-btn.play-btn:hover { color: #0078d4; border-color: #0078d4; }
/* 音频播放器 */
.stem-player {
display: none; align-items: center; gap: 8px;
flex: 1; min-width: 0;
}
.stem-player.active { display: flex; }
.player-btn {
width: 26px; height: 26px; border-radius: 50%; border: none;
background: #0078d4; color: #fff; cursor: pointer; display: flex;
align-items: center; justify-content: center; font-size: 10px;
flex-shrink: 0; transition: all 0.15s;
}
.player-btn:hover { background: #006cbd; }
.player-btn.playing { background: #e53935; }
.player-btn.playing:hover { background: #c62828; }
.player-progress {
width: 200px; flex-shrink: 0; height: 4px;
-webkit-appearance: none; appearance: none;
background: #e0e0e0; border-radius: 2px; outline: none; cursor: pointer;
}
.player-progress::-webkit-slider-thumb {
-webkit-appearance: none; width: 12px; height: 12px;
background: #0078d4; border-radius: 50%; cursor: pointer;
}
.player-time {
font-size: 11px; color: #999; flex-shrink: 0;
font-variant-numeric: tabular-nums; min-width: 70px; text-align: right;
}
/* 顶部操作栏 */
.top-actions {
display: flex; gap: 8px; margin-bottom: 16px;
@@ -368,7 +422,7 @@
<div class="input-group">
<label>选择模型</label>
<select id="modelSelect" style="width:100%;padding:8px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;transition:all 0.15s ease;">
<select id="modelSelect" onchange="onModelSelect(this)" style="width:100%;padding:8px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;transition:all 0.15s ease;">
<option value="">-- 请先扫描模型目录 --</option>
</select>
</div>
@@ -399,17 +453,16 @@
</div>
<div class="input-group">
<label>Segment分割参数大小</label>
<input type="text" id="demucsSegment" placeholder="如 Default、1、2、4"
list="demucsSegmentOptions"
style="width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<datalist id="demucsSegmentOptions">
<option value="Default">
<option value="1"><option value="2"><option value="3">
<option value="4"><option value="5"><option value="6">
<option value="7"><option value="8"><option value="10">
<option value="12"><option value="15"><option value="20">
<option value="30"><option value="40"><option value="50">
</datalist>
<select id="demucsSegment" onchange="toggleCustom(this,'demucsSegmentCustom')" style="width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<option value="Default">Default</option>
<option value="1">1</option><option value="2">2</option><option value="3">3</option>
<option value="4">4</option><option value="5">5</option><option value="6">6</option>
<option value="7">7</option><option value="8">8</option><option value="10">10</option>
<option value="12">12</option><option value="15">15</option><option value="20">20</option>
<option value="30">30</option><option value="40">40</option><option value="50">50</option>
<option value="__custom__">自定义...</option>
</select>
<input type="text" id="demucsSegmentCustom" placeholder="输入自定义值" style="display:none;margin-top:4px;width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<div class="param-desc">较小的尺寸占用资源较少。较大的尺寸效果可能更好。</div>
</div>
</div>
@@ -419,24 +472,25 @@
<div class="arch-params-label"><i class="fas fa-cog"></i> MDX-Net 参数</div>
<div class="input-group">
<label>Segment分割参数大小</label>
<input type="text" id="mdxSegmentSize" placeholder="如 Default、256、512、1024"
list="mdxSegmentOptions"
style="width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<datalist id="mdxSegmentOptions">
<option value="Default">
<option value="128"><option value="256"><option value="512">
<option value="1024"><option value="2048"><option value="4096">
</datalist>
<select id="mdxSegmentSize" onchange="toggleCustom(this,'mdxSegmentSizeCustom')" style="width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<option value="Default">Default</option>
<option value="128">128</option><option value="256">256</option>
<option value="512">512</option><option value="1024">1024</option>
<option value="2048">2048</option><option value="4096">4096</option>
<option value="__custom__">自定义...</option>
</select>
<input type="text" id="mdxSegmentSizeCustom" placeholder="输入自定义值" style="display:none;margin-top:4px;width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<div class="param-desc">默认大小为 256。音质可能会因你的选择而有所不同。</div>
</div>
<div class="input-group">
<label>Overlap重叠度</label>
<input type="text" id="mdxOverlap" placeholder="如 0.250(范围 0.10 ~ 0.99"
list="mdxOverlapOptions"
style="width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<datalist id="mdxOverlapOptions">
<option value="0.100"><option value="0.250"><option value="0.500"><option value="0.750"><option value="0.990">
</datalist>
<select id="mdxOverlap" onchange="toggleCustom(this,'mdxOverlapCustom')" style="width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<option value="0.100">0.100</option><option value="0.250">0.250</option>
<option value="0.500">0.500</option><option value="0.750">0.750</option>
<option value="0.990">0.990</option>
<option value="__custom__">自定义...</option>
</select>
<input type="text" id="mdxOverlapCustom" placeholder="输入自定义值,如 0.350" style="display:none;margin-top:4px;width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<div class="param-desc">较高的值可能会带来更好的效果,但也会导致处理时间延长。</div>
</div>
</div>
@@ -446,22 +500,28 @@
<div class="arch-params-label"><i class="fas fa-cog"></i> VR Arc 参数</div>
<div class="input-group">
<label>Window Size窗口大小</label>
<input type="text" id="vrWindowSize" placeholder="如 1024、512、320"
list="vrWindowSizeOptions"
style="width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<datalist id="vrWindowSizeOptions">
<option value="1024"><option value="512"><option value="320">
</datalist>
<select id="vrWindowSize" onchange="toggleCustom(this,'vrWindowSizeCustom')" style="width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<option value="320">320</option>
<option value="512">512</option>
<option value="1024">1024</option>
<option value="2048">2048</option>
<option value="4096">4096</option>
<option value="__custom__">自定义...</option>
</select>
<input type="text" id="vrWindowSizeCustom" placeholder="输入自定义值" style="display:none;margin-top:4px;width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<div class="param-desc">选择窗口大小,以平衡音质与处理速度。</div>
</div>
<div class="input-group">
<label>Aggression分离强度</label>
<input type="text" id="vrAggression" placeholder="如 5范围 -100 ~ 100"
list="vrAggressionOptions"
style="width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<datalist id="vrAggressionOptions">
<option value="5"><option value="10"><option value="0"><option value="-5"><option value="100"><option value="-100">
</datalist>
<select id="vrAggression" onchange="toggleCustom(this,'vrAggressionCustom')" style="width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<option value="-100">-100</option><option value="-50">-50</option>
<option value="-10">-10</option><option value="-5">-5</option>
<option value="0">0</option><option value="5">5</option>
<option value="10">10</option><option value="50">50</option>
<option value="100">100</option>
<option value="__custom__">自定义...</option>
</select>
<input type="text" id="vrAggressionCustom" placeholder="输入自定义值,如 20" style="display:none;margin-top:4px;width:100%;padding:7px 10px;border:1px solid #e0e0e0;border-radius:6px;font-size:13px;background:#fff;color:#333;outline:none;">
<div class="param-desc">数值越大,提取越深入。对于人声和伴奏,通常设置为 5。</div>
</div>
</div>
@@ -540,6 +600,13 @@
<div id="stemsList"></div>
</div>
</div>
<div class="log-area" id="logArea">
<div class="log-header">
<span><i class="fas fa-code"></i> 控制台日志</span>
<button class="log-clear-btn" onclick="clearLogs()" title="清除日志">清除</button>
</div>
<div class="log-content" id="logContent"></div>
</div>
</div>
<!-- 设置弹窗 -->
@@ -605,6 +672,37 @@
var currentArch = 'Demucs';
var scannedModels = [];
// ── 自定义输入切换 ──────────────────────────────────────────────────────
function toggleCustom(sel, customId) {
var customEl = document.getElementById(customId);
if (!customEl) return;
customEl.style.display = sel.value === '__custom__' ? 'block' : 'none';
if (sel.value === '__custom__') customEl.focus();
}
function getSelectValue(selectId, customId) {
var sel = document.getElementById(selectId);
if (!sel) return '';
if (sel.value === '__custom__') {
var custom = document.getElementById(customId);
return custom ? custom.value.trim() : '';
}
return sel.value;
}
function restoreCustomSelect(selectId, customId, value) {
var sel = document.getElementById(selectId);
if (!sel) return;
// Try matching a preset option
for (var i = 0; i < sel.options.length; i++) {
if (sel.options[i].value === value) { sel.selectedIndex = i; return; }
}
// No match — use custom
sel.value = '__custom__';
var custom = document.getElementById(customId);
if (custom) { custom.style.display = 'block'; custom.value = value; }
}
// ── 设置弹窗 ──────────────────────────────────────────────────────────
function openSettings() {
var dirs = window._savedModelDirs || {};
@@ -893,19 +991,14 @@
// 架构特异参数
if (currentArch === 'Demucs') {
var demucsStemSelect = document.getElementById('demucsStemSelect');
var demucsSegment = document.getElementById('demucsSegment');
formData.append('demucs_stems', demucsStemSelect ? demucsStemSelect.value : 'All Stems');
formData.append('segment', demucsSegment ? demucsSegment.value : 'Default');
formData.append('segment', getSelectValue('demucsSegment', 'demucsSegmentCustom') || 'Default');
} else if (currentArch === 'MDX-Net') {
var mdxSegmentSize = document.getElementById('mdxSegmentSize');
var mdxOverlap = document.getElementById('mdxOverlap');
formData.append('segment', mdxSegmentSize ? mdxSegmentSize.value : 'Default');
formData.append('mdx_overlap', mdxOverlap ? mdxOverlap.value : '0.250');
formData.append('segment', getSelectValue('mdxSegmentSize', 'mdxSegmentSizeCustom') || 'Default');
formData.append('mdx_overlap', getSelectValue('mdxOverlap', 'mdxOverlapCustom') || '0.250');
} else if (currentArch === 'VR Arc') {
var vrWindowSize = document.getElementById('vrWindowSize');
var vrAggression = document.getElementById('vrAggression');
formData.append('vr_window_size', vrWindowSize ? vrWindowSize.value : '1024');
formData.append('vr_aggression', vrAggression ? vrAggression.value : '5');
formData.append('vr_window_size', getSelectValue('vrWindowSize', 'vrWindowSizeCustom') || '1024');
formData.append('vr_aggression', getSelectValue('vrAggression', 'vrAggressionCustom') || '5');
}
var startBtn = document.getElementById('startBtn');
@@ -921,6 +1014,8 @@
if (progressSection) progressSection.style.display = 'block';
if (progressFill) progressFill.style.width = '0%';
if (statusText) statusText.textContent = '正在上传并初始化...';
var logContent = document.getElementById('logContent');
if (logContent) logContent.innerHTML = '';
fetch('/uvr-sep/separate', { method: 'POST', body: formData })
.then(function(r) { return r.json(); })
@@ -944,6 +1039,22 @@
});
}
// ── 日志 ──────────────────────────────────────────────────────────────
function renderLogs(logs) {
var el = document.getElementById('logContent');
if (!el || !logs || !logs.length) return;
el.innerHTML = logs.map(function(l) { return l.replace(/</g, '&lt;'); }).join('<br>');
el.scrollTop = el.scrollHeight;
}
function clearLogs() {
var el = document.getElementById('logContent');
if (el) el.innerHTML = '';
if (currentTaskId) {
fetch('/uvr-sep/clear-logs/' + currentTaskId, { method: 'POST' });
}
}
// ── 轮询状态 ──────────────────────────────────────────────────────────
function pollStatus() {
if (!currentTaskId) return;
@@ -960,6 +1071,7 @@
var emptyState = document.getElementById('emptyState');
if (progressFill) progressFill.style.width = data.progress + '%';
if (data.logs) renderLogs(data.logs);
var devInfo = data.device ? ' [' + data.device + ']' : '';
if (data.status === 'done') {
clearInterval(pollTimer); pollTimer = null;
@@ -990,14 +1102,25 @@
var name = s.stem.toLowerCase();
if (name === 'vocals' || name === 'vocal') { iconClass = 'vocals'; icon = 'fa-microphone'; }
else if (name === 'instrumental' || name === 'no vocals') { iconClass = 'instrumental'; icon = 'fa-folder'; }
var safeStem = s.stem.replace(/'/g, "\\'");
var row = document.createElement('div');
row.className = 'stem-row';
row.innerHTML =
'<div class="stem-icon ' + iconClass + '"><i class="fas ' + icon + '"></i></div>' +
'<div class="stem-info"><div class="stem-name">' + s.stem + '</div><div class="stem-filename">' + s.filename + '</div></div>' +
'<div class="stem-actions">' +
'<button class="stem-btn play-btn" onclick="playStem(\'' + currentTaskId + '\',\'' + s.stem + '\')"><i class="fas fa-play"></i></button>' +
'<button class="stem-btn" onclick="downloadStem(\'' + currentTaskId + '\',\'' + s.stem + '\')"><i class="fas fa-folder-plus"></i></button>' +
'<div style="display:flex;align-items:center;gap:10px;margin-left:auto;">' +
'<div class="stem-player active" id="player_' + safeStem + '">' +
'<button class="player-btn" id="playerBtn_' + safeStem + '" onclick="playStem(\'' + currentTaskId + '\',\'' + safeStem + '\')" title="播放"><i class="fas fa-play"></i></button>' +
'<input type="range" class="player-progress" id="progress_' + safeStem + '" min="0" max="100" value="0" step="0.1"' +
' onmousedown="startSeeking(\'' + safeStem + '\')"' +
' onmouseup="doSeek(\'' + safeStem + '\')"' +
' ontouchstart="startSeeking(\'' + safeStem + '\')"' +
' ontouchend="doSeek(\'' + safeStem + '\')">' +
'<span class="player-time" id="time_' + safeStem + '">0:00 / 0:00</span>' +
'</div>' +
'<div class="stem-actions">' +
'<button class="stem-btn" onclick="downloadStem(\'' + currentTaskId + '\',\'' + safeStem + '\')" title="下载"><i class="fas fa-folder-plus"></i></button>' +
'</div>' +
'</div>';
list.appendChild(row);
});
@@ -1007,12 +1130,115 @@
if (resultSection) resultSection.style.display = 'block';
}
// ── 音频播放控制 ─────────────────────────────────────────────────────
var currentStem = '';
var playTimer = null;
var seeking = false;
function playStem(taskId, stem) {
var audio = document.getElementById('previewAudio');
if (audio) {
if (!audio) return;
// 切换音轨
if (currentStem !== stem) {
stopCurrentStem();
currentStem = stem;
audio.src = '/uvr-sep/download/' + encodeURIComponent(taskId) + '/' + encodeURIComponent(stem);
audio.play();
}
// 播放/暂停切换
if (audio.paused) {
audio.play();
} else {
audio.pause();
}
}
function stopCurrentStem() {
var audio = document.getElementById('previewAudio');
if (!audio) return;
audio.pause();
audio.removeAttribute('src');
if (playTimer) { clearInterval(playTimer); playTimer = null; }
if (currentStem) {
var btn = document.getElementById('playerBtn_' + currentStem);
var prog = document.getElementById('progress_' + currentStem);
var time = document.getElementById('time_' + currentStem);
if (btn) { btn.className = 'player-btn'; btn.innerHTML = '<i class="fas fa-play"></i>'; }
if (prog) prog.value = 0;
if (time) time.textContent = '0:00 / 0:00';
}
currentStem = '';
}
// audio 事件
(function() {
var audio = document.getElementById('previewAudio');
if (!audio) return;
audio.addEventListener('play', function() {
if (!currentStem) return;
var btn = document.getElementById('playerBtn_' + currentStem);
if (btn) { btn.className = 'player-btn playing'; btn.innerHTML = '<i class="fas fa-pause"></i>'; }
if (playTimer) clearInterval(playTimer);
playTimer = setInterval(updatePlayProgress, 200);
});
audio.addEventListener('pause', function() {
if (!currentStem) return;
var btn = document.getElementById('playerBtn_' + currentStem);
if (btn) { btn.className = 'player-btn'; btn.innerHTML = '<i class="fas fa-play"></i>'; }
if (playTimer) { clearInterval(playTimer); playTimer = null; }
});
audio.addEventListener('ended', function() {
if (!currentStem) return;
var btn = document.getElementById('playerBtn_' + currentStem);
var prog = document.getElementById('progress_' + currentStem);
var time = document.getElementById('time_' + currentStem);
if (btn) { btn.className = 'player-btn'; btn.innerHTML = '<i class="fas fa-play"></i>'; }
if (prog) prog.value = 100;
if (time) time.textContent = formatPlayerTime(audio.duration) + ' / ' + formatPlayerTime(audio.duration);
if (playTimer) { clearInterval(playTimer); playTimer = null; }
});
audio.addEventListener('loadedmetadata', function() {
updatePlayProgress();
});
})();
function updatePlayProgress() {
var audio = document.getElementById('previewAudio');
if (!audio || !currentStem || isNaN(audio.duration)) return;
var prog = document.getElementById('progress_' + currentStem);
var time = document.getElementById('time_' + currentStem);
if (prog && !seeking) {
prog.value = audio.currentTime / audio.duration * 100;
}
if (time) {
time.textContent = formatPlayerTime(audio.currentTime) + ' / ' + formatPlayerTime(audio.duration);
}
}
function startSeeking(stem) {
if (stem === currentStem) seeking = true;
}
function doSeek(stem) {
seeking = false;
var audio = document.getElementById('previewAudio');
if (!audio || stem !== currentStem || isNaN(audio.duration)) return;
var prog = document.getElementById('progress_' + stem);
if (prog) {
audio.currentTime = parseFloat(prog.value) / 100 * audio.duration;
}
}
function formatPlayerTime(sec) {
if (isNaN(sec)) return '0:00';
var m = Math.floor(sec / 60);
var s = Math.floor(sec % 60);
return m + ':' + (s < 10 ? '0' : '') + s;
}
function downloadStem(taskId, stem) {
@@ -1048,11 +1274,6 @@
var isSecondaryOnly = document.getElementById('isSecondaryOnly');
var saveFormat = document.getElementById('saveFormat');
var demucsStemSelect = document.getElementById('demucsStemSelect');
var demucsSegment = document.getElementById('demucsSegment');
var mdxSegmentSize = document.getElementById('mdxSegmentSize');
var mdxOverlap = document.getElementById('mdxOverlap');
var vrWindowSize = document.getElementById('vrWindowSize');
var vrAggression = document.getElementById('vrAggression');
var cfg = {
uvr_project_path: uvrPath ? uvrPath.value.trim() : '',
@@ -1069,11 +1290,11 @@
is_secondary_stem_only: isSecondaryOnly ? isSecondaryOnly.checked : false,
save_format: saveFormat ? saveFormat.value : 'wav',
demucs_stems: demucsStemSelect ? demucsStemSelect.value : 'All Stems',
demucs_segment: demucsSegment ? demucsSegment.value : 'Default',
mdx_segment_size: mdxSegmentSize ? mdxSegmentSize.value : 'Default',
mdx_overlap: mdxOverlap ? parseFloat(mdxOverlap.value) : 0.25,
vr_window_size: vrWindowSize ? parseInt(vrWindowSize.value) : 1024,
vr_aggression: vrAggression ? parseInt(vrAggression.value) : 5,
demucs_segment: getSelectValue('demucsSegment', 'demucsSegmentCustom') || 'Default',
mdx_segment_size: getSelectValue('mdxSegmentSize', 'mdxSegmentSizeCustom') || 'Default',
mdx_overlap: parseFloat(getSelectValue('mdxOverlap', 'mdxOverlapCustom')) || 0.25,
vr_window_size: parseInt(getSelectValue('vrWindowSize', 'vrWindowSizeCustom')) || 1024,
vr_aggression: parseInt(getSelectValue('vrAggression', 'vrAggressionCustom')) || 5,
};
// 保存选中模型(按架构区分)
@@ -1190,20 +1411,15 @@
if (demucsStemSel.options[i].value === cfg.demucs_stems) { demucsStemSel.selectedIndex = i; break; }
}
}
var demucsSegSel = document.getElementById('demucsSegment');
if (demucsSegSel) demucsSegSel.value = cfg.demucs_segment;
restoreCustomSelect('demucsSegment', 'demucsSegmentCustom', cfg.demucs_segment);
// 恢复 MDX 参数
var mdxSegSel = document.getElementById('mdxSegmentSize');
if (mdxSegSel) mdxSegSel.value = cfg.mdx_segment_size;
var mdxOverlap = document.getElementById('mdxOverlap');
if (mdxOverlap) mdxOverlap.value = cfg.mdx_overlap.toFixed(3);
restoreCustomSelect('mdxSegmentSize', 'mdxSegmentSizeCustom', cfg.mdx_segment_size);
restoreCustomSelect('mdxOverlap', 'mdxOverlapCustom', cfg.mdx_overlap.toFixed(3));
// 恢复 VR 参数
var vrWinSel = document.getElementById('vrWindowSize');
if (vrWinSel) vrWinSel.value = cfg.vr_window_size;
var vrAggression = document.getElementById('vrAggression');
if (vrAggression) vrAggression.value = cfg.vr_aggression;
restoreCustomSelect('vrWindowSize', 'vrWindowSizeCustom', String(cfg.vr_window_size));
restoreCustomSelect('vrAggression', 'vrAggressionCustom', String(cfg.vr_aggression));
// 恢复通用参数
var isGpu = document.getElementById('isGpu');