Lumi/plugins/lumi_transcription/views/settings.ejs
2026-07-22 11:01:49 +02:00

60 lines
3.8 KiB
Plaintext

<link rel="stylesheet" href="/plugins/lumi_transcription/assets/transcription.css">
<main class="transcription-shell" data-transcription-admin>
<header class="transcription-hero">
<div>
<p class="eyebrow">Experimental companion</p>
<h1>Lumi Transcription</h1>
<p>Server-hosted speech recognition for selected OBS sources. Live Twitch delivery remains blocked until the native OBS caption compatibility test passes on the target setup.</p>
</div>
<span class="health-pill <%= providerHealth.healthy ? 'is-ready' : 'is-blocked' %>">
<span aria-hidden="true"></span><%= providerHealth.healthy ? 'Inference ready' : 'Inference setup required' %>
</span>
</header>
<section class="setup-path" aria-labelledby="setup-title">
<div class="section-heading"><div><p class="eyebrow">First usable path</p><h2 id="setup-title">Setup progress</h2></div></div>
<ol>
<li class="is-current"><strong>Pair a companion</strong><span>Create a single-use package for the streaming computer.</span></li>
<li><strong>Install the OBS bridge</strong><span>Managed by Lumi Companion; no separate bridge settings.</span></li>
<li><strong>Install and benchmark a model</strong><span>Small English is recommended. Nothing downloads without confirmation.</span></li>
<li><strong>Select and test a microphone</strong><span>Test mode must pass before live delivery is enabled.</span></li>
</ol>
<button class="primary-action" type="button" data-create-pairing>Create pairing package</button>
<p class="inline-status" role="status" data-status></p>
</section>
<div class="transcription-grid">
<section aria-labelledby="runtime-title">
<div class="section-heading"><div><p class="eyebrow">Lumi host</p><h2 id="runtime-title">Inference</h2></div></div>
<dl class="health-list">
<div><dt>Provider</dt><dd>whisper.cpp <%= runtimeManifest.tested_version %></dd></div>
<div><dt>Worker</dt><dd><%= providerHealth.state %></dd></div>
<div><dt>Selected model</dt><dd><%= providerHealth.model || 'Not loaded' %></dd></div>
<div><dt>Active sessions</dt><dd><%= providerHealth.sessions || 0 %></dd></div>
</dl>
<p class="notice">Lumi AI may already occupy most GPU memory. The MVP warns and benchmarks; it does not unload Lumi AI models automatically.</p>
</section>
<section aria-labelledby="devices-title">
<div class="section-heading"><div><p class="eyebrow">Access</p><h2 id="devices-title">Paired devices</h2></div><span><%= devices.length %></span></div>
<% if (!devices.length) { %><p class="empty-state">No companion is paired yet.</p><% } %>
<ul class="plain-list">
<% devices.forEach((device) => { %>
<li><div><strong><%= device.name %></strong><span><%= device.revoked_at ? 'Revoked' : 'Last connected ' + new Date(device.last_connected_at).toLocaleString() %></span></div><code><%= device.id %></code></li>
<% }) %>
</ul>
</section>
</div>
<section aria-labelledby="models-title">
<div class="section-heading"><div><p class="eyebrow">Curated choices</p><h2 id="models-title">Speech models</h2></div></div>
<div class="model-row">
<% models.forEach((model) => { %>
<article><div><h3><%= model.label %></h3><p><%= model.recommended ? 'Recommended starting point' : 'Fallback option' %> · <%= Math.round(model.bytes / 1048576) %> MiB</p></div><span class="state-label"><%= model.status.valid ? 'Verified' : model.status.installed ? 'Checksum failed' : 'Not installed' %></span></article>
<% }) %>
</div>
<p class="privacy-note"><strong>Privacy:</strong> raw audio is held only in bounded memory and is never written to disk by default. Diagnostic caption text is retained for seven days unless disabled.</p>
</section>
</main>
<script src="/plugins/lumi_transcription/assets/transcription.js" defer></script>