35 lines
1.9 KiB
JavaScript
35 lines
1.9 KiB
JavaScript
// Optional "Remove background music" for URL/YouTube imports. Button appears only when the
|
|
// server reports features.vocal_isolation. Original stays loadable via the toggle (before/after).
|
|
function setupVocalIsolation({ btn, toggle, msg, getId, getDur, apply }) {
|
|
const b = $(btn), t = $(toggle), m = $(msg);
|
|
let pair = null, showing = 'clean';
|
|
const say = text => { m.textContent = text; status(text); };
|
|
fetch('/api/version').then(r => r.json()).then(v => { if (v?.features?.vocal_isolation) b.hidden = false; }).catch(() => {});
|
|
const label = () => { t.textContent = showing === 'clean' ? 'Play original' : 'Play without music'; };
|
|
b.addEventListener('click', async () => {
|
|
const id = getId();
|
|
if (!id) { say('Load audio first, then remove the background music.'); return; }
|
|
b.disabled = true; t.hidden = true;
|
|
say('Removing background music. This can take a few minutes.');
|
|
try {
|
|
const r = await fetch('/api/isolate-vocals', { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({ id }) });
|
|
const d = await r.json().catch(() => ({}));
|
|
if (!r.ok) throw new Error(d.detail || r.statusText);
|
|
pair = { orig:id, origDur:getDur(), clean:d.id, cleanDur:d.duration };
|
|
showing = 'clean'; apply(d.id, d.duration);
|
|
t.hidden = false; label();
|
|
say('Background music removed. Use the button next to it to compare with the original.');
|
|
} catch (e) {
|
|
say('Could not remove background music: ' + e.message);
|
|
toast('Vocal isolation failed: ' + e.message, 'error');
|
|
} finally { b.disabled = false; }
|
|
});
|
|
t.addEventListener('click', () => {
|
|
if (!pair) return;
|
|
showing = showing === 'clean' ? 'orig' : 'clean';
|
|
if (showing === 'clean') apply(pair.clean, pair.cleanDur); else apply(pair.orig, pair.origDur);
|
|
label();
|
|
say(showing === 'clean' ? 'Playing the version without background music.' : 'Playing the original audio.');
|
|
});
|
|
}
|