window.TTSUI=(()=>{ const e=v=>String(v??'').replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); async function api(path='',data){const r=await fetch('/api/v1/'+path,(data===undefined)?{}:{method:'POST',headers:{'Content-Type':'application/json','X-Athena-Deck':'1'},body:JSON.stringify(data)});const x=await r.json();if(!r.ok)throw Error(x.error||'TTS-Anfrage fehlgeschlagen');return x;} function html(setup=false){return `

${setup?'Qwen3-TTS einrichten':'Sprache ausprobieren'}

${setup?'

Die Einrichtung installiert eine eigene CUDA-Laufzeit und das offizielle Qwen3-TTS 1.7B CustomVoice mit eingebauten Stimmen. Dafür werden mehrere GB heruntergeladen. MLX-Dateien sind für Apple-Geräte; vorhandene Dateien werden nicht gelöscht.

Vorhandenes TTS-Profil verbinden

Ersetzt im ausgewählten Profil die Modellzuordnung durch die eingerichtete CUDA-Variante. Der Profilname bleibt erhalten.

':'

Ausführung auf der RTX 3060. Andere Deck-Modellaufträge werden koordiniert; fremde Dienste werden nicht gestoppt. Text wird nicht dauerhaft gespeichert. Ergebnisdateien bleiben auf Athena.

'}
`;} function bind(setup=false){const root=document.querySelector('#tts-panel');if(!root)return;const el=id=>root.querySelector('#'+id);let state,profiles=[],busy=false,lastResult='';const error=x=>{if(root.isConnected)el('tts-error').textContent=x;}; async function refresh(){try{state=await api('tts');if(!root.isConnected)return;const rt=state.runtime,j=state.job;el('tts-status').textContent=setup?(rt.job?.phase||(rt.installed?'TTS ist eingerichtet.':'Noch nicht eingerichtet.')):(j?.phase||'Profil wählen und Text eingeben.'); if(setup){el('tts-install').disabled=busy||rt.installed||rt.job?.state==='running';el('tts-install-cancel').disabled=rt.job?.state!=='running';el('tts-assign').disabled=busy||!rt.installed||!profiles.length;} else{el('tts-generate').disabled=busy||j?.state==='running'||!profiles.length||!rt.installed;el('tts-cancel').disabled=j?.state!=='running';if(j?.state==='complete'&&lastResult!==j.id){lastResult=j.id;el('tts-result').innerHTML=`

Ergebnis

WAV herunterladen

`;}} }catch(err){error(err.message);}finally{if(root.isConnected)setTimeout(refresh,2000);}} async function load(){const p=await api('profiles');if(!root.isConnected)return;profiles=p.profiles.filter(p=>p.kind==='audio'&&(setup||p.runnable));el('tts-profile').innerHTML=profiles.map(p=>``).join('')||'';} async function action(path,data={}){busy=true;error('');try{await api('tts/'+path,data);if(path==='assign'){await load();error('Profil verbunden. Jetzt den Reiter Testen öffnen.');}}catch(err){error(err.message);}finally{busy=false;}} if(setup){el('tts-install').onclick=()=>action('install');el('tts-install-cancel').onclick=()=>action('install-cancel');el('tts-assign').onclick=()=>{const p=profiles.find(p=>p.id===el('tts-profile').value);if(p)action('assign',{id:p.id,revision:p.revision});};} else{api('tts').then(s=>{if(!root.isConnected)return;el('tts-speaker').innerHTML=s.runtime.speakers.map(v=>``).join('');el('tts-language').innerHTML=s.runtime.languages.map(v=>``).join('');}).catch(x=>error(x.message));el('tts-form').onsubmit=ev=>{ev.preventDefault();action('start',{profile_id:el('tts-profile').value,text:el('tts-text').value,speaker:el('tts-speaker').value,language:el('tts-language').value});};el('tts-cancel').onclick=()=>action('cancel');} load().catch(x=>error(x.message));refresh(); } return {html,bind}; })();