Install native audio separator with model packages WAV tests and restore recipe
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
window.SeparatorUI=(()=>{
|
||||
const e=v=>String(v??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
|
||||
async function api(path,data){const response=await fetch('/api/v1/'+path,data===undefined?{}:{method:'POST',headers:{'Content-Type':'application/json','X-Athena-Deck':'1'},body:JSON.stringify(data)});const value=await response.json();if(!response.ok)throw Error(value.error||'Anfrage fehlgeschlagen');return value;}
|
||||
function render(test=false){if(document.querySelector('#separator-panel')?.dataset.test===String(test))return;
|
||||
document.querySelector('#view').innerHTML=`<div id="separator-panel" data-test="${test}"><div class="kicker">${test?'STIMMWERKZEUGE':'EINSTELLUNGEN / LAUFZEITEN'}</div><h1>${test?'Audio trennen':'Audio Separator'}</h1><p>BS-RoFormer und MelBand RoFormer trennen Gesang und Instrumental. Die native Laufzeit wird einmal installiert und für passende Modellpakete wiederverwendet.</p><p id="sep-message" role="status"></p><section class="card"><div id="sep-status"></div><button id="sep-install">Laufzeit installieren</button><button class="secondary" id="sep-cancel">Einrichtung abbrechen</button><p>Version 0.47.0 · mindestens 15 GiB frei. Installiert CUDA-PyTorch und Audio Separator in einer eigenen Umgebung. Keine Änderungen an Host-Treibern oder alten Diensten.</p><div id="sep-models"></div><details><summary>Installationsausgabe</summary><pre id="sep-log" style="max-height:240px;overflow:auto;white-space:pre-wrap"></pre></details></section><section class="card"><h2>Kurzer Trenntest</h2><p>PCM-WAV, 16 Bit, Mono oder Stereo, bis 30 Sekunden und 8 MiB. Im LLM-Modus koordiniert Deck die GPU-Nutzung und entlädt gegebenenfalls eigene Modelle. Fremde Dienste bleiben unberührt. Das Trennmodell wird nach dem Test entladen.</p><form id="sep-test"><label>Modellpaket<select name="model" id="sep-model"></select></label><label>Audiodatei<input name="file" type="file" accept=".wav,audio/wav" required></label><button>Audio trennen</button><button type="button" class="secondary" id="sep-test-cancel">Test abbrechen</button></form><div id="sep-job" role="status"></div><div id="sep-results"></div></section></div>`;
|
||||
const root=document.querySelector('#separator-panel'),msg=root.querySelector('#sep-message');let pending=false,signature='';
|
||||
async function action(path,data){pending=true;try{await api(path,data);msg.textContent='Aktion gestartet.';}catch(error){msg.textContent=error.message;}finally{pending=false;signature='';poll();}}
|
||||
async function poll(){if(!root.isConnected)return;try{const [s,t]=await Promise.all([api('separator-runtime'),api('separator-tests')]);if(!root.isConnected)return;
|
||||
const running=s.job?.state==='running';if(s.job){const log=await api('separator-runtime/log');if(!root.isConnected)return;root.querySelector('#sep-log').textContent=log.text;}root.querySelector('#sep-status').innerHTML=`<p><strong>${s.installed?'Installiert':'Noch nicht installiert'}</strong> · ${e(s.version)}</p>${s.job?`<p>${e(s.job.state)} · ${e(s.job.phase)}</p>${running?'<progress aria-label="Einrichtung läuft"></progress>':''}`:''}`;
|
||||
root.querySelector('#sep-install').disabled=pending||running||s.installed;root.querySelector('#sep-cancel').disabled=pending||!running;
|
||||
const key=JSON.stringify(s.models);if(key!==signature){signature=key;root.querySelector('#sep-models').innerHTML='<h2>Unterstützte Modellpakete</h2><p>Gewichte und passende Konfiguration werden zusammen beschafft. Diese Pakete sind getrennt von ungeprüften Hugging-Face-Dateien.</p>'+s.models.map(m=>`<p><strong>${e(m.name)}</strong> · ${m.installed?'Bereit':'Fehlt'}<br><span class="small">${e(m.id)} + ${e(m.configuration)}</span><br><button data-sep-model="${e(m.id)}" ${m.installed?'disabled':''}>Modell und Konfiguration herunterladen</button></p>`).join('');root.querySelector('#sep-model').innerHTML=s.models.filter(m=>m.installed).map(m=>`<option value="${e(m.id)}">${e(m.name)}</option>`).join('');root.querySelectorAll('[data-sep-model]').forEach(b=>b.onclick=()=>action('separator-runtime/download',{model:b.dataset.sepModel}));}
|
||||
root.querySelectorAll('[data-sep-model]').forEach(b=>b.disabled=pending||running||!s.installed||s.models.find(m=>m.id===b.dataset.sepModel)?.installed);
|
||||
const j=t.job;root.querySelector('#sep-test button').disabled=pending||running||!s.models.some(m=>m.installed)||j?.state==='running';root.querySelector('#sep-test-cancel').disabled=j?.state!=='running';root.querySelector('#sep-job').innerHTML=j?`<p>${e(j.state)} · ${e(j.phase)} ${j.elapsed_seconds?e(j.elapsed_seconds)+' s':''}</p>${j.state==='running'?'<progress aria-label="Audio wird getrennt"></progress>':''}`:'';
|
||||
const results=root.querySelector('#sep-results');if(results.dataset.job!==String(j?.id+':'+j?.state)){results.dataset.job=String(j?.id+':'+j?.state);results.innerHTML=j?.state==='complete'?j.files.map(f=>`<p>${e(f.name)}</p><audio controls src="/api/v1/separator-tests/audio?id=${e(j.id)}&index=${f.index}"></audio><p><a href="/api/v1/separator-tests/audio?id=${e(j.id)}&index=${f.index}" download="${e(f.name)}">Spur herunterladen</a></p>`).join(''):'';}
|
||||
}catch(error){if(root.isConnected)msg.textContent=error.message;}clearTimeout(root.pollTimer);if(root.isConnected)root.pollTimer=setTimeout(poll,3000);}
|
||||
root.querySelector('#sep-install').onclick=()=>action('separator-runtime/install',{});root.querySelector('#sep-cancel').onclick=()=>action('separator-runtime/cancel',{});root.querySelector('#sep-test-cancel').onclick=()=>action('separator-tests/cancel',{});
|
||||
root.querySelector('#sep-test').onsubmit=async event=>{event.preventDefault();pending=true;msg.textContent='Audio wird hochgeladen …';try{const response=await fetch('/api/v1/separator-tests/start',{method:'POST',headers:{'X-Athena-Deck':'1'},body:new FormData(event.target)}),value=await response.json();if(!response.ok)throw Error(value.error);msg.textContent='Trenntest gestartet.';}catch(error){msg.textContent=error.message;}finally{pending=false;poll();}};poll();
|
||||
}
|
||||
return {render};
|
||||
})();
|
||||
Reference in New Issue
Block a user