window.SeparatorUI=(()=>{ const e=v=>String(v??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); let section='discover'; 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 sources(m){return `

Quelle: ${e(m.source?.publisher||'Nicht belegt')}

Originalquellen und Prüfsummen${(m.source?.files||[]).map(f=>`

${e(f.file)}
${f.urls.map(u=>`Downloadquelle`).join(' · ')}
${e(f.sha256)}

`).join('')}
`;} function rows(models,library){const list=models.filter(m=>!library||m.installed);return list.length?`
${list.map(m=>`
${e(m.name)}${m.installed?'Bereit':'Nicht heruntergeladen'}${m.source?.files?.length||0} Dateien

${e(m.id)}

${sources(m)}

Vollständiges Modellpaket · einschließlich Konfiguration und benötigter Teilmodelle. Die Laufzeit wird wiederverwendet.

${m.installed?'In der Steuerung Audio-Trennung starten →':``}
`).join('')}
`:'

Noch keine Modellpakete

Unter Entdecken ein geprüftes Modellpaket herunterladen.

';} function render(tool=false,force=false){if(!force&&document.querySelector('#separator-panel')?.dataset.tool===String(tool))return; const tabs=[['discover','Entdecken'],['library','Bibliothek'],['downloads','Downloads'],['test','Testen']]; document.querySelector('#view').innerHTML=`
${tool?'ATHENA / MODELLVERWALTUNG':'EINSTELLUNGEN / LAUFZEITEN'}

${tool?'Audio-Trennung':'Audio Separator'}

${tool?'Gesang, Schlagzeug, Bass, Gitarre, Klavier oder die übrige Begleitung aus einer Aufnahme herauslösen.':'Native CUDA-Laufzeit für BS-Roformer, MelBand und Demucs. Einmal installieren und für passende Modellpakete wiederverwenden.'}

${tool?`
${tabs.map(([id,label])=>``).join('')}
`:''}

`; const root=document.querySelector('#separator-panel'),msg=root.querySelector('#sep-message'),content=root.querySelector('#sep-content');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();}} function bind(s,t){ root.querySelectorAll('[data-sep-model]').forEach(b=>{b.disabled=pending||s.job?.state==='running'||!s.installed;b.onclick=()=>action('separator-runtime/download',{model:b.dataset.sepModel});}); const install=root.querySelector('#sep-install');if(install){install.disabled=pending||s.installed||s.job?.state==='running';install.onclick=()=>action('separator-runtime/install',{});} const cancel=root.querySelector('#sep-cancel');if(cancel){cancel.disabled=s.job?.state!=='running';cancel.onclick=()=>action('separator-runtime/cancel',{});} const stop=root.querySelector('#sep-test-cancel');if(stop){stop.disabled=t.job?.state!=='running';stop.onclick=()=>action('separator-tests/cancel',{});} const form=root.querySelector('#sep-test');if(form){form.querySelector('button').disabled=pending||t.job?.state==='running'||!s.models.some(m=>m.installed);form.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(form)}),value=await response.json();if(!response.ok)throw Error(value.error);msg.textContent='Trenntest 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 key=JSON.stringify([s,t,pending]);if(key!==signature&& (!root.querySelector('#sep-test')?.contains(document.activeElement)||t.job?.state==='running'||root.dataset.jobState!==String(t.job?.state))){signature=key;root.dataset.jobState=String(t.job?.state); if(!tool){content.innerHTML=`

Laufzeit

${s.installed?'Installiert':'Noch nicht installiert'} · Version ${e(s.version)}

Mindestens 15 GiB frei. Keine Änderung an Host-Treibern oder alten Diensten.

Audio-Trennung öffnen →

${e(s.job?.phase||'')}

${s.job?.state==='running'?'':''}
Installationsausgabe
`; const log=await api('separator-runtime/log');if(root.isConnected)root.querySelector('#sep-log').textContent=log.text; }else if(section==='discover'||section==='library'){content.innerHTML=`${section==='discover'?'

Geprüfte Pakete mit allen benötigten Zusatzdateien. Downloads prüfen die Originalquellen per SHA-256.

':''}${!s.installed?'

Laufzeit fehlt. Audio Separator installieren →

':''}${rows(s.models,section==='library')}`; }else if(section==='downloads'){content.innerHTML=s.job?`
${e(s.job.state)}

Einrichtungsauftrag

${e(s.job.phase)}

${s.job.state==='running'?'':''}

Abgeschlossene Modellpakete findest du in der Bibliothek.

`:'

Keine Downloads

Unter Entdecken ein Modellpaket auswählen.

'; }else{const j=t.job;content.innerHTML=`

Audio-Trennung testen

Kurzer PCM-WAV-Test: 16 Bit, Mono/Stereo, bis 30 Sekunden und 8 MiB. Für längere Dateien die Weboberfläche verwenden.

Audio-Trennoberfläche öffnen → · Audio-Trennung in der Steuerung starten →

Gewichte laden bei Auftrag und werden anschließend entladen. Fremde Dienste bleiben unberührt.

${j?`

${e(j.state)} · ${e(j.phase)} ${j.elapsed_seconds?e(j.elapsed_seconds)+' s':''}

${j.state==='running'?'':''}`:''}
${j?.state==='complete'?j.files.map(f=>`

${e(f.name)}

Spur herunterladen

`).join(''):''}
`;} } bind(s,t); }catch(error){if(root.isConnected)msg.textContent=error.message;}clearTimeout(root.pollTimer);if(root.isConnected)root.pollTimer=setTimeout(poll,3000);} root.querySelectorAll('[data-sep-tab]').forEach(b=>b.onclick=()=>{section=b.dataset.sepTab;render(tool,true);});poll(); } return {render}; })();