Voice-over's side panel shows who reads, speed, the language (one line while detected) and the tone with a listen button; the comparison, the numbers and the links fold under More. GPT-SoVITS Settings opens with one status line and the tone to use; the language rules, base files, places and version are folded and open by themselves when they need the user. Plainer words throughout: tone, Steady / Natural / Lively, As the character, Always read like this, Own settings, base files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
140 lines
5.8 KiB
JavaScript
140 lines
5.8 KiB
JavaScript
import { t } from './interface_settings.js';
|
|
import { anomalousAlert, anomalousConfirm } from './ui_dialog.js';
|
|
import { button, el } from './usage_view.js';
|
|
|
|
/**
|
|
* "Anomalous_TTS version" in GPT-SoVITS Settings: the installed version (local), its
|
|
* published releases only after "Check for updates" (network), and an update to the
|
|
* newest stable one, or back to where the last update came from; then the restart
|
|
* question (ComfyUI Manager's reboot when there is one). The backend only acts on a git
|
|
* clone of the official repository (api/tts_version.py).
|
|
*/
|
|
|
|
async function request(url, options = {}) {
|
|
try {
|
|
const resp = await fetch(url, options);
|
|
return await resp.json().catch(() => ({ success: false, error: `HTTP ${resp.status}` }));
|
|
} catch (e) {
|
|
return { success: false, code: 'offline', error: e.message };
|
|
}
|
|
}
|
|
|
|
const post = (url, body = {}) => request(url, {
|
|
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body),
|
|
});
|
|
|
|
function errorText(result) {
|
|
const key = `versionError_${result.code}`;
|
|
const text = t(key, { error: result.error || '' });
|
|
const message = text === key ? t('versionErrorGeneric', { error: result.error || result.code || '' }) : text;
|
|
return result.files?.length ? `${message}\n\n${result.files.join('\n')}` : message;
|
|
}
|
|
|
|
function versionOf(state) {
|
|
return state.tag || state.base_tag || state.label;
|
|
}
|
|
|
|
async function askRestart(message) {
|
|
const restart = await anomalousConfirm(`${message}\n\n${t('versionRestartQuestion')}`, t('ttsVersionTitle'), {
|
|
okLabel: t('versionRestartNow'), cancelLabel: t('versionRestartLater'),
|
|
});
|
|
if (!restart) return '';
|
|
// Manager's reboot exits the server, so a dropped connection means it is restarting.
|
|
const reboot = await post('/api/manager/reboot');
|
|
if (reboot.code === 'offline' || reboot.success !== false) return t('versionRestarting');
|
|
await anomalousAlert(t('versionRestartManual'));
|
|
return '';
|
|
}
|
|
|
|
/** The settings group; `local` false (another device) leaves the buttons out. */
|
|
export function renderTtsVersion(local) {
|
|
const group = el('div', 'anomalous-tts-setup-group');
|
|
const row = el('div', 'anomalous-tts-setup-row');
|
|
const value = el('span', 'anomalous-tts-setup-path', '…');
|
|
const note = el('span', 'anomalous-tts-setup-meta', '');
|
|
const actions = el('span', 'anomalous-tts-version-actions');
|
|
row.append(value, note, actions);
|
|
const hint = el('div', 'anomalous-tts-hint', t('ttsVersionHint'));
|
|
group.append(row, hint); // its title is the fold's (ui_tts_setup.js)
|
|
|
|
let busy = false;
|
|
const run = async (label, work) => {
|
|
if (busy) return;
|
|
busy = true;
|
|
actions.querySelectorAll('button').forEach(btn => { btn.disabled = true; });
|
|
note.textContent = label;
|
|
try { await work(); } finally { busy = false; }
|
|
};
|
|
|
|
const show = (state, listing = null) => {
|
|
value.textContent = versionOf(state);
|
|
note.textContent = '';
|
|
actions.replaceChildren();
|
|
if (!local) return;
|
|
const latest = listing?.releases.find(item => item.latest);
|
|
if (!listing) {
|
|
actions.append(button('anomalous-tts-add', t('ttsVersionCheck'), () => run(t('ttsVersionChecking'), check)));
|
|
} else if (!latest || latest.current || latest.direction !== 'newer') {
|
|
note.textContent = t('ttsVersionUpToDate');
|
|
} else {
|
|
note.textContent = t('ttsVersionNew', { tag: latest.tag });
|
|
actions.append(button('anomalous-tts-add', t('ttsVersionUpdate', { tag: latest.tag }),
|
|
() => run(t('versionSwitching', { tag: latest.tag }), () => update(state, latest))));
|
|
if (latest.url) {
|
|
const notes = el('a', 'anomalous-tts-link', t('ttsVersionNotes'));
|
|
notes.href = latest.url;
|
|
notes.target = '_blank';
|
|
notes.rel = 'noopener noreferrer';
|
|
actions.append(notes);
|
|
}
|
|
}
|
|
if (state.previous?.label) {
|
|
actions.append(button('anomalous-tts-link', t('ttsVersionUndo', { tag: state.previous.label }),
|
|
() => run(t('versionSwitching', { tag: state.previous.label }), () => undo(state))));
|
|
}
|
|
};
|
|
|
|
const check = async () => {
|
|
const listing = await request('/anomalous/tts_version/releases?refresh=1');
|
|
if (!listing.success) {
|
|
await anomalousAlert(errorText(listing));
|
|
return load();
|
|
}
|
|
show(listing.state, listing);
|
|
};
|
|
|
|
const finish = async (result, tag) => {
|
|
if (!result.success) {
|
|
await anomalousAlert(errorText(result));
|
|
return load();
|
|
}
|
|
show(result.state);
|
|
note.textContent = await askRestart(t('ttsVersionUpdated', { tag })) || t('versionPendingRestart');
|
|
};
|
|
|
|
const update = async (state, release) => {
|
|
if (!await anomalousConfirm(t('ttsVersionConfirm', { tag: release.tag, from: versionOf(state) }), t('ttsVersionTitle'))) return show(state);
|
|
await finish(await post('/anomalous/tts_version/update', { tag: release.tag }), release.tag);
|
|
};
|
|
|
|
const undo = async (state) => {
|
|
const tag = state.previous.label;
|
|
if (!await anomalousConfirm(t('versionConfirmUndo', { label: tag }), t('ttsVersionTitle'))) return show(state);
|
|
await finish(await post('/anomalous/tts_version/undo'), tag);
|
|
};
|
|
|
|
const load = async () => {
|
|
const data = await request('/anomalous/tts_version');
|
|
if (!data.success || !data.found) {
|
|
value.textContent = t('ttsVersionUnknown');
|
|
note.textContent = '';
|
|
actions.replaceChildren();
|
|
hint.textContent = t('ttsVersionNoGit');
|
|
return;
|
|
}
|
|
show(data.state);
|
|
};
|
|
load();
|
|
return group;
|
|
}
|