Expose video test and mode controls in the Video category
This commit is contained in:
+9
-4
@@ -9,15 +9,20 @@ window.VideoUI=(()=>{
|
||||
root.querySelectorAll('[data-mode]').forEach(b=>b.onclick=()=>act('video/mode',{mode:b.dataset.mode}));
|
||||
root.querySelector('#active-video').onchange=ev=>{if(ev.target.value)act('video/profile',{id:ev.target.value});};
|
||||
}
|
||||
function html(testing=false){return `<section id="video-runtime-page">${testing?'<h2>Video testen</h2><p>Profil auswählen, Video-Modus aktivieren und einen kurzen Test starten.</p><div id="video-test-mode"></div>':'<h1>LTX-Video-Laufzeit</h1>'}<div ${testing?'hidden':''}><p>Eigene Python-Umgebung, gepinnte LTX-Pipelines, CUDA 12.8. Installation verändert keine Host-Treiber. Erster Ausführungsweg: Text → Video mit dem Distilled-BF16-Rezept und Disk-Streaming auf der RTX 5080.</p><p id="video-status"></p><button id="video-install">Laufzeit installieren</button><button id="video-cancel">Installation abbrechen</button><p><a href="#home">Modus und aktives Profil in der Übersicht auswählen →</a></p></div><p id="video-message" role="status"></p><section class="card"><h2>Video-Test</h2><p>Zuerst den Video-Modus aktivieren. Werte überschreiben die Profilstandards für diesen Auftrag. Distilled nutzt seine feste Schrittfolge. Noch kein Bild-/Audio-Upload.</p><form id="video-test"><label>Prompt<textarea name="prompt" required maxlength="8000"></textarea></label>${[['width','Breite',256],['height','Höhe',256],['frames','Bilder (8n+1)',9],['fps','FPS',24],['seed','Seed',42]].map(([n,l,v])=>`<label>${l}<input type="number" name="${n}" value="${v}" required></label>`).join('')}<button>Video erzeugen</button></form><p id="video-job"></p><div id="video-result"></div><p>API: POST /v1/videos · GET /v1/videos/{id} · GET /v1/videos/{id}/content. Gleicher Port und API-Token wie Chat; eigenständige Deck-Video-API.</p></section></section>`;}
|
||||
async function runtime(){
|
||||
const view=document.querySelector('#view');if(view.querySelector('#video-runtime-page'))return;
|
||||
view.innerHTML=`<section id="video-runtime-page"><h1>LTX-Video-Laufzeit</h1><p>Eigene Python-Umgebung, gepinnte LTX-Pipelines, CUDA 12.8. Installation verändert keine Host-Treiber. Erster Ausführungsweg: Text → Video mit dem Distilled-BF16-Rezept und Disk-Streaming auf der RTX 5080.</p><p id="video-status"></p><button id="video-install">Laufzeit installieren</button><button id="video-cancel">Installation abbrechen</button><p id="video-message" role="status"></p><p><a href="#home">Modus und aktives Profil in der Übersicht auswählen →</a></p><section class="card"><h2>Video-Test</h2><p>Vorher in der Übersicht Video aktivieren. Werte überschreiben die Profilstandards für diesen Auftrag. Distilled nutzt seine feste Schrittfolge. Noch kein Bild-/Audio-Upload.</p><form id="video-test"><label>Prompt<textarea name="prompt" required maxlength="8000"></textarea></label>${[['width','Breite',512],['height','Höhe',320],['frames','Bilder (8n+1)',9],['fps','FPS',24],['seed','Seed',42]].map(([n,l,v])=>`<label>${l}<input type="number" name="${n}" value="${v}" required></label>`).join('')}<button>Video erzeugen</button></form><p id="video-job"></p><div id="video-result"></div><p>API: POST /v1/videos · GET /v1/videos/{id} · GET /v1/videos/{id}/content. Gleicher Port und API-Token wie Chat; eigenständige Deck-Video-API.</p></section></section>`;
|
||||
const root=view.firstElementChild,msg=root.querySelector('#video-message');
|
||||
view.innerHTML=html();bind(view.firstElementChild);
|
||||
}
|
||||
function bind(root=document.querySelector('#video-runtime-page')){
|
||||
if(!root)return;
|
||||
const msg=root.querySelector('#video-message');
|
||||
async function action(path,data){try{await api(path,data);msg.textContent='Auftrag angenommen.';}catch(x){msg.textContent=x.message;}}
|
||||
root.querySelector('#video-install').onclick=()=>action('video-runtime/install',{});
|
||||
root.querySelector('#video-cancel').onclick=()=>action('video-runtime/cancel',{});
|
||||
root.querySelector('#video-test button').disabled=true;
|
||||
root.querySelector('#video-test').onsubmit=ev=>{ev.preventDefault();const d=Object.fromEntries(new FormData(ev.target));for(const k of ['width','height','frames','fps','seed'])d[k]=Number(d[k]);action('video/generate',d);};
|
||||
async function poll(){if(!root.isConnected)return;try{const s=await api('video');root.querySelector('#video-status').textContent=s.runtime.installed?'Installiert · '+s.runtime.revision:(s.runtime.job?.phase||'Noch nicht installiert');root.querySelector('#video-install').disabled=s.runtime.installed||s.runtime.job?.state==='running';root.querySelector('#video-cancel').disabled=s.runtime.job?.state!=='running';root.querySelector('#video-job').textContent=s.job?`${s.job.state} · ${s.job.phase||''} · ${s.job.id} · ${s.job.error||''}`:'Noch kein Video-Auftrag.';if(s.job?.state==='complete'&&root.querySelector('#video-result').dataset.id!==s.job.id){root.querySelector('#video-result').dataset.id=s.job.id;root.querySelector('#video-result').innerHTML=`<video controls preload="metadata" style="max-width:100%" src="/api/v1/video/content?id=${e(s.job.id)}"></video><a href="/api/v1/video/content?id=${e(s.job.id)}" download="athena-video.mp4">Video herunterladen</a>`;}}catch(x){msg.textContent=x.message;}if(root.isConnected)setTimeout(poll,2000);}poll();
|
||||
async function poll(){if(!root.isConnected)return;try{const s=await api('video');if(!root.isConnected)return;const panel=root.querySelector('#video-test-mode');if(panel){const p=await api('profiles');if(!root.isConnected)return;mode(panel,s,p.profiles);}root.querySelector('#video-status').textContent=s.runtime.installed?'Installiert · '+s.runtime.revision:(s.runtime.job?.phase||'Noch nicht installiert');root.querySelector('#video-install').disabled=s.runtime.installed||s.runtime.job?.state==='running';root.querySelector('#video-cancel').disabled=s.runtime.job?.state!=='running';root.querySelector('#video-test button').disabled=s.mode!=='video'||s.state!=='ready'||s.job?.state==='running';root.querySelector('#video-job').textContent=s.job?`${s.job.state} · ${s.job.phase||''} · ${s.job.id} · ${s.job.error||''}`:'Noch kein Video-Auftrag.';if(s.job?.state==='complete'&&root.querySelector('#video-result').dataset.id!==s.job.id){root.querySelector('#video-result').dataset.id=s.job.id;root.querySelector('#video-result').innerHTML=`<video controls preload="metadata" style="max-width:100%" src="/api/v1/video/content?id=${e(s.job.id)}"></video><a href="/api/v1/video/content?id=${e(s.job.id)}" download="athena-video.mp4">Video herunterladen</a>`;}}catch(x){msg.textContent=x.message;}if(root.isConnected)setTimeout(poll,2000);}poll();
|
||||
}
|
||||
return {mode,runtime};
|
||||
return {mode,runtime,html:()=>html(true),bind};
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user