sprecher-analyse / index.html
Monstermango's picture
Put download within reach in the history
cfda667 verified
Raw
History Blame Contribute Delete
9.82 kB
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Sprecher-Analyse</title>
<meta name="theme-color" content="#f5f5f7" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#101014" media="(prefers-color-scheme: dark)">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="Sprecher">
<link rel="manifest" href="manifest.webmanifest">
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<link rel="icon" type="image/png" href="icon-192.png">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="topbar">
<h1>Sprecher-Analyse</h1>
<div class="row">
<span id="gpu-status" class="status" hidden
title="Verbleibendes GPU-Tageskontingent"></span>
<span id="token-status" class="status" hidden></span>
<button id="btn-key" class="icon-btn" title="Einstellungen"
aria-label="Einstellungen">
<svg viewBox="0 0 24 24" width="26" height="26" fill="currentColor"
aria-hidden="true">
<path d="M19.14 12.94c.04-.3.06-.61.06-.94s-.02-.64-.07-.94l2.03-1.58a.49.49 0 0 0 .12-.61l-1.92-3.32a.49.49 0 0 0-.59-.22l-2.39.96a7.03 7.03 0 0 0-1.62-.94l-.36-2.54a.48.48 0 0 0-.48-.41h-3.84a.48.48 0 0 0-.48.41l-.36 2.54c-.59.24-1.13.56-1.62.94l-2.39-.96a.48.48 0 0 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58a.49.49 0 0 0-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.48-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32a.49.49 0 0 0-.12-.61l-2.01-1.58ZM12 15.6a3.6 3.6 0 1 1 0-7.2 3.6 3.6 0 0 1 0 7.2Z"/>
</svg>
</button>
</div>
</header>
<main>
<!-- Analyse -->
<section id="view-analyse" class="view">
<div id="rec-area" class="card">
<button id="btn-datei" class="primary">Audiodatei auswählen</button>
<div class="dim klein mitte">Sprachmemo aus „Dateien“ oder iCloud.
Ohne Audio geht es nicht — die Sprechertrennung wird daraus
gemessen.</div>
<!-- Nebenweg: bewusst als schlichter Textlink, nicht als zweite
Hauptaktion — aufgenommen wird in aller Regel in Sprachmemos. -->
<button id="btn-record" class="textlink">oder direkt hier aufnehmen</button>
<div id="rec-status" class="dim klein mitte" hidden></div>
<!-- Kein enger Filter: iOS blendet sonst m4a-Dateien aus iCloud aus. -->
<input type="file" id="file-input" hidden>
</div>
<div id="anleitung" class="card">
<ol class="schritte">
<li><b>Meeting aufnehmen</b><span class="dim klein">
mit Sprachmemos auf dem iPhone</span></li>
<li><b>Audiodatei hier auswählen <span class="marke">nötig</span></b>
<span class="dim klein">
Aus der Aufnahme kommt, wer wann gesprochen hat</span></li>
<li><b>Transkript einfügen
<span class="marke bonus">Bonus</span></b>
<span class="dim klein">
Aus Sprachmemos kopieren — macht den Wortlaut genauer. Ohne das
erkennt die App die Wörter selbst</span></li>
<li><b>Als Markdown sichern</b><span class="dim klein">
Sprecher benennen, herunterladen oder teilen</span></li>
</ol>
</div>
<div id="audio-panel" class="card" hidden>
<div class="row">
<span id="audio-name" class="grow"></span>
<button id="btn-verwerfen" class="icon-btn" title="Verwerfen"></button>
</div>
<audio id="audio-preview" controls></audio>
<details id="transkript-box" open>
<summary><b>Transkript aus Sprachmemos</b>
<span class="marke bonus">Bonus</span></summary>
<p class="dim klein">Rein optional. In Sprachmemos die Aufnahme
öffnen, Transkript anzeigen, kopieren, hier einfügen. Der Text wird
dann wortgetreu übernommen und nur noch den Sprechern zugeordnet —
genauer und schneller als eigene Erkennung. Leer lassen, wenn die
App die Wörter selbst erkennen soll; die Sprechertrennung kommt so
oder so aus der Audiodatei.</p>
<textarea id="transkript" rows="4"
placeholder="Transkript hier einfügen …"></textarea>
<div id="transkript-info" class="dim klein"></div>
<label class="row opt">
<span class="grow">Zusätzlich selbst erkennen
<span class="dim klein">Markiert strittige Wörter — verdoppelt
aber die Rechenzeit</span></span>
<input id="abgleich" type="checkbox">
</label>
</details>
<!-- Sichtbar statt unter „Optionen“: die automatische Schätzung
erkennt regelmäßig zu viele Sprecher, und wer das Meeting
aufgenommen hat, weiß die Zahl. -->
<label class="row opt">
<span class="grow">Anzahl Sprecher
<span class="dim klein">0 = automatisch schätzen</span></span>
<input id="num-speakers" type="number" min="0" max="8" value="0" inputmode="numeric">
</label>
<details>
<summary>Optionen</summary>
<label class="opt-block">
<span>Namen & Begriffe (hilft der Erkennung)</span>
<input id="kontext" type="text" placeholder="z. B. Hedi, Marta, Kita, Entwicklungsgespräch">
</label>
<label class="row opt">
<span class="grow">Sprache</span>
<select id="sprache">
<option value="german" selected>Deutsch</option>
<option value="english">Englisch</option>
<option value="french">Französisch</option>
<option value="spanish">Spanisch</option>
<option value="italian">Italienisch</option>
<option value="turkish">Türkisch</option>
<option value="">Automatisch</option>
</select>
</label>
</details>
<button id="btn-analyse" class="primary">Analysieren</button>
</div>
<div id="fortsetzen" class="card" hidden>
<div id="fortsetzen-text">Eine begonnene Analyse wurde unterbrochen.</div>
<button id="btn-fortsetzen" class="primary">Analyse fortsetzen</button>
</div>
<div id="progress" class="card center" hidden>
<div class="spinner"></div>
<div id="progress-text" class="dim">Analysiere …</div>
<div class="dim klein">Läuft seit <span id="progress-zeit">0:00</span>.</div>
<!-- Der Hinweis wechselt, sobald der Auftrag im Space angelegt ist.
Vorher wäre „du kannst schließen“ schlicht falsch: bricht der
Upload ab, entsteht nie ein Auftrag. -->
<div id="progress-hinweis" class="dim klein mitte">Bitte geöffnet
lassen, bis die Aufnahme übertragen ist.</div>
</div>
<div id="ergebnis"></div>
</section>
<!-- Verlauf -->
<section id="view-verlauf" class="view" hidden>
<div id="verlauf-liste"></div>
<div id="eintrag-detail" hidden>
<!-- Bleibt beim Scrollen stehen: ein Protokoll ist lang, und der
Knopf zum Herunterladen lag vorher dahinter. -->
<div class="detail-kopf row">
<button id="btn-zurueck" class="ghost">← Verlauf</button>
<button id="btn-download" class="primary knapp">⬇︎ Markdown</button>
<button id="btn-teilen-verlauf" class="ghost" hidden>Teilen</button>
</div>
<div id="eintrag-inhalt" class="card md"></div>
</div>
</section>
</main>
<nav class="tabbar">
<button data-view="analyse" class="tab active">
<span class="tab-icon">🎙️</span><span>Analyse</span>
</button>
<button data-view="verlauf" class="tab">
<span class="tab-icon">📋</span><span>Verlauf</span>
</button>
</nav>
<!-- Login -->
<div id="login" class="overlay" hidden>
<div class="sheet">
<div class="sheet-kopf">
<h2>Einstellungen</h2>
<button id="btn-schliessen" class="icon-btn" title="Schließen"
aria-label="Schließen" hidden></button>
</div>
<p class="dim">Bitte den Zugangsschlüssel der App eingeben.</p>
<div id="login-status" class="dim klein"></div>
<input id="key-input" type="text" placeholder="Zugangsschlüssel"
autocomplete="off" autocapitalize="none" autocorrect="off"
spellcheck="false">
<input id="hf-input" type="text" placeholder="Hugging-Face-Token (hf_…)"
autocomplete="off" autocapitalize="none" autocorrect="off"
spellcheck="false">
<p class="dim klein">Das HF-Token sorgt dafür, dass dein eigenes
GPU-Kontingent genutzt wird.</p>
<button id="btn-login" class="primary">Weiter</button>
<div id="login-fehler" class="fehler"></div>
<button id="btn-push-test" class="ghost breit">Probe-Benachrichtigung
senden</button>
<div id="push-status" class="dim klein"></div>
<details id="glossar-box">
<summary>Glossar ansehen</summary>
<p class="dim klein">Wiederkehrende Namen und Begriffe werden nach jeder
Analyse automatisch gesammelt und der Erkennung als Vorwissen
mitgegeben. Änderungen sind selten nötig — die Reihenfolge legt fest,
was Vorrang hat.</p>
<label class="opt-block">
<span>Begriffe</span>
<textarea id="g-begriffe" rows="6"></textarea>
</label>
<label class="opt-block">
<span>Sprechernamen</span>
<textarea id="g-sprecher" rows="3"></textarea>
</label>
<button id="btn-glossar-speichern" class="ghost breit">Glossar sichern</button>
</details>
</div>
</div>
<div id="toast" hidden></div>
<script type="module" src="app.js"></script>
</body>
</html>