VoicePult/web/index.html
2026-10-03 11:07:47 +02:00

34 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="de">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="theme-color" content="#f4f5ef"><title>VoicePult · Dein Audio, verbunden.</title><link rel="icon" href="/icon.svg"><link rel="stylesheet" href="/style.css"><script src="/app.js" defer></script></head>
<body>
<aside class="sidebar"><a class="brand" href="/" aria-label="VoicePult Startseite"><img src="/icon.svg" alt=""><span>voicepult<span class="brand-dot">.</span></span></a><div class="workspace"><span class="workspace-icon">V</span><div>Mein Studio<small>Lokaler Arbeitsbereich</small></div><span class="local-dot"></span></div><div class="nav-label">ARBEITSBEREICH</div><a class="nav-item selected" data-workspace="patchpanel" href="#patchpanel"><span data-icon="routing"></span>Patchpanel<span class="nav-count" id="nav-count">0</span></a><a class="nav-item" data-workspace="saved-apps" href="#saved-apps"><span data-icon="apps"></span>Gespeicherte Apps<span class="nav-count" id="saved-count">0</span></a><button class="nav-item" id="help-button"><span data-icon="book"></span>So funktioniert’s<span data-icon="arrow"></span></button><div class="sidebar-bottom"><div class="engine"><span class="status-dot" id="engine-dot"></span><div id="engine-label">Audio verbinden…</div></div><p>Ein Ort für deinen Sound.<br>Alles bleibt auf deinem Rechner.</p><span class="version">VOICEPULT / 01</span></div></aside>
<div class="page"><header class="topbar"><div class="breadcrumb">Mein Studio <span>/</span> <strong id="workspace-title">Patchpanel</strong></div><label class="toggle-label theme-toggle" for="dark-mode">Darkmode<input id="dark-mode" type="checkbox" role="switch"></label><div class="local-badge"><span class="local-dot"></span> Lokal verbunden</div></header>
<nav class="mobile-workspaces" aria-label="Arbeitsbereiche"><a data-workspace="patchpanel" href="#patchpanel">Patchpanel</a><a data-workspace="saved-apps" href="#saved-apps">Gespeicherte Apps</a></nav>
<div class="error-banner workspace-error" id="error-banner" role="alert" hidden></div>
<main id="patchpanel"><div class="page-heading"><div><div class="eyebrow">DEIN AUDIO. DEINE VERBINDUNGEN.</div><h1>Alles im richtigen Kanal<span>.</span></h1><p>Verbinde deine Anwendungen. Bestimme, wer was hört.</p></div><button class="button primary" id="add-channel"><span data-icon="plus"></span>Neuer Kanal</button></div>
<section class="overview" aria-label="Übersicht"><div><span class="overview-icon" data-icon="apps"></span><div><strong id="app-count">—</strong><span>Anwendungen</span></div><span class="stat-note">Audioquellen</span></div><div><span class="overview-icon" data-icon="sliders"></span><div><strong id="channel-count">0</strong><span>Virtuelle Kanäle</span></div><span class="stat-note">Dein Mix</span></div><div><span class="overview-icon" data-icon="routing"></span><div><strong id="route-count">0</strong><span>Verbindungen</span></div><span class="stat-note"><span class="local-dot"></span>Live-Routing</span></div></section>
<section class="scope-panel" aria-label="Live-Wellenform und Mixer">
<div class="scope-heading"><div><span class="eyebrow">LIVE AUDIO</span><h2>Deinen Sound im Blick.</h2></div><div class="scope-controls"><label for="scope-source">Signal</label><select id="scope-source"><option value="voicepult_microphone">Mikrofon-Mix</option></select><button class="button" id="scope-toggle" aria-pressed="true">Anzeige pausieren</button></div></div>
<div class="wave-gain"><label for="wave-gain">Wellenform vergrößern</label><input id="wave-gain" type="range" min="1" max="32" value="8"><output id="wave-gain-value">×8</output><small>Nur die Darstellung wird verstärkt.</small></div><div class="scope-layout"><div class="scope-display"><div class="scope-meta"><span id="scope-status" role="status">Verbinde Audioanzeige…</span><span>50 ms · Stereo</span></div><canvas id="scope-canvas" height="180" aria-label="Live-Wellenform, linker und rechter Audiokanal"></canvas><div class="scope-scale"><span>L / R</span><span id="wave-scale-label">Ansicht ×8 · Pegel unverändert</span><span id="scope-clip">Kein Clipping</span></div></div><div class="scope-mixer"><h3>Mikrofon-Mix</h3><p>Gesamtlautstärke für Element, OBS & Co.</p><div class="meter-line"><label for="meter-left">L</label><meter id="meter-left" min="-60" max="0" low="-12" high="-3" optimum="-18" value="-60"></meter><output id="level-left">−∞ dBFS</output></div><div class="meter-line"><label for="meter-right">R</label><meter id="meter-right" min="-60" max="0" low="-12" high="-3" optimum="-18" value="-60"></meter><output id="level-right">−∞ dBFS</output></div><label class="field-label" for="mix-volume">MIX-LAUTSTÄRKE</label><div class="volume-row"><button class="icon-button" id="mix-mute" aria-label="Mikrofon-Mix stummschalten" aria-pressed="false" data-icon="volume"></button><input id="mix-volume" type="range" min="0" max="100" value="100"><output id="mix-value">100%</output></div><small>Die Pegel zeigen das oben gewählte Signal. Kanal-Lautstärken regelst du im Patchpanel.</small></div></div>
</section>
<div class="board-heading"><div><h2>Patchpanel</h2><span>Von der Quelle bis zum Ziel.</span></div><div class="live-label"><span class="local-dot"></span><span id="live-label">Wird verbunden</span></div></div>
<section class="patch-grid" aria-label="Audio-Routing">
<div class="patch-column"><div class="column-title"><span class="step">01</span><h3>Anwendungen</h3><span data-icon="arrow"></span></div><p class="column-description">Wähle einen Kanal für jeden Sound.</p><div id="microphone-routing"></div><div class="app-list" id="apps"></div><div class="source-hint"><span data-icon="info"></span><p>Eine Anwendung fehlt? Starte dort die Audiowiedergabe – sie erscheint automatisch. Bereits zugeordnete Apps findest du auch unter <a href="#saved-apps">Gespeicherte Apps</a>.</p></div></div>
<div class="patch-column channels-column"><div class="column-title"><span class="step">02</span><h3>Virtuelle Kanäle</h3><span data-icon="arrow"></span></div><p class="column-description">Mischen, regeln und weiterleiten.</p><div class="channel-list" id="channels"></div><button class="add-card" id="add-channel-secondary"><span data-icon="plus"></span>Kanal hinzufügen</button></div>
<div class="patch-column"><div class="column-title"><span class="step">03</span><h3>Ziele</h3><span class="terminal-dot"></span></div><p class="column-description">Zum Hören und als Mikrofon für Apps.</p><div id="outputs"></div><div id="extra-targets"></div><button class="add-card" id="add-target"><span data-icon="plus"></span>Virtuelles Mikrofon hinzufügen</button><div class="mic-explainer"><span class="mini-label">FÜR CALLS & STREAMS</span><h4>Dein Mix als Mikrofon.</h4><p>Wähle <strong>VoicePult Mikrofon</strong> als Eingabegerät in Discord, OBS oder deiner Konferenz-App.</p><button class="text-button" id="help-inline">Kurzanleitung <span data-icon="arrow"></span></button></div></div>
</section><section class="network-panel" id="network-panel" hidden><div><span class="eyebrow">HANDY & TABLET</span><h3>Im selben Netzwerk verbinden</h3><p id="network-links"></p></div><div><label for="network-code">Zugangscode</label><input id="network-code" readonly type="password"><button class="button" id="reveal-code">Code anzeigen</button><p>Auf dem anderen Gerät die Adresse öffnen und den Code eingeben.</p></div></section><footer><span><span class="local-dot"></span> Änderungen werden automatisch gespeichert</span><span>Entwickelt für deinen Signalfluss.</span></footer></main>
<main id="saved-apps" hidden><div class="page-heading"><div><div class="eyebrow">DEINE DAUERHAFTEN ZUORDNUNGEN</div><h1>Gespeicherte Apps<span>.</span></h1><p>Ändere deine Zielkanäle – auch wenn eine Anwendung pausiert oder geschlossen ist.</p></div><a class="button" href="#patchpanel">Zum Patchpanel</a></div>
<div class="saved-info"><span data-icon="info"></span><p>Vorhandene Audiostreams werden sofort umgeleitet. Ohne Audiostream gilt die neue Auswahl bei der nächsten Wiedergabe. Wenn du alle Kanäle abwählst, wird die gespeicherte Zuordnung entfernt.</p></div>
<section id="saved-app-list" class="saved-app-grid" aria-label="Gespeicherte App-Zuordnungen"></section>
<footer><span><span class="local-dot"></span> Änderungen werden automatisch gespeichert</span></footer></main></div>
<dialog id="target-dialog"><form id="target-form"><div class="dialog-header"><span class="eyebrow">EIN NEUES ZIEL FÜR DEINEN MIX</span><button class="icon-button" type="button" data-close="target-dialog" aria-label="Schließen" data-icon="close"></button></div><h2>Virtuelles Mikrofon erstellen</h2><p>Zum Beispiel „OBS“ oder „Gespräch“. Anschließend bei deinen Kanälen als Ziel aktivieren.</p><label for="target-name">Name</label><input id="target-name" maxlength="40" required autocomplete="off" placeholder="z. B. OBS"><div class="dialog-actions"><button type="button" class="button" data-close="target-dialog">Abbrechen</button><button type="submit" class="button primary" id="target-submit">Mikrofon erstellen</button></div></form></dialog>
<dialog id="target-delete-dialog"><h2>Virtuelles Mikrofon löschen?</h2><p id="target-delete-message"></p><p>Anwendungen, die dieses Mikrofon verwenden, benötigen danach ein anderes Eingabegerät.</p><div class="dialog-actions"><button class="button" data-close="target-delete-dialog">Abbrechen</button><button class="button danger" id="target-delete-confirm">Mikrofon löschen</button></div></dialog>
<dialog id="channel-dialog"><form id="channel-form"><div class="dialog-header"><span class="eyebrow" id="dialog-eyebrow">MEHR PLATZ FÜR DEINEN SOUND</span><button class="icon-button" type="button" data-close="channel-dialog" aria-label="Schließen" data-icon="close"></button></div><h2 id="dialog-title">Neuer virtueller Kanal</h2><p>Zum Beispiel Browser, Musik oder Spiel.</p><label for="channel-name">Kanalname</label><input id="channel-name" maxlength="40" required placeholder="z. B. Browser" autocomplete="off"><p class="form-note">Neue Kanäle spielen auf deinem gewählten Ausgang. Den Mikrofon-Mix schaltest du bei Bedarf dazu.</p><div class="dialog-actions"><button type="button" class="button" data-close="channel-dialog">Abbrechen</button><button type="submit" class="button primary" id="channel-submit">Kanal erstellen</button></div></form></dialog>
<dialog id="help-dialog"><div class="dialog-header"><span class="eyebrow">IN DREI SCHRITTEN VERBUNDEN</span><button class="icon-button" data-close="help-dialog" aria-label="Schließen" data-icon="close"></button></div><h2>Firefox hören. Und teilen.</h2><ol class="help-steps"><li><strong>Erstelle einen Kanal</strong><p>Nenne ihn beispielsweise „Browser“ und wähle ihn bei Firefox aus. Firefox muss zuvor Audio abgespielt haben.</p></li><li><strong>Wähle deine Ziele</strong><p>Aktiviere am Kanal „Kopfhörer“ und „Mikrofon-Mix“. Wähle rechts den tatsächlichen Kopfhörer-Ausgang.</p></li><li><strong>Wähle das virtuelle Mikrofon</strong><p>Stelle in deiner Gesprächs-App „VoicePult Mikrofon“ als Eingabe ein. Mit „Stimme direkt in den Mix“ wird dein echtes Mikrofon beigemischt.</p></li></ol><div class="help-note">Leite die Gesprächs-App selbst nicht in den Mikrofon-Mix, damit Gesprächspartner sich nicht als Echo hören. Audiodaten der Live-Anzeige werden nur kurz im Arbeitsspeicher ausgewertet und nicht gespeichert.</div><button class="button primary full" data-close="help-dialog">Alles klar</button></dialog>
<dialog id="delete-dialog"><h2>Kanal löschen?</h2><p id="delete-message"></p><div class="dialog-actions"><button class="button" data-close="delete-dialog">Abbrechen</button><button class="button danger" id="confirm-delete">Kanal löschen</button></div></dialog>
<dialog id="access-dialog"><form id="access-form"><h2>Mit VoicePult verbinden</h2><p>Den Zugangscode findest du auf deinem Rechner unten in VoicePult unter „Handy & Tablet“.</p><label for="access-code">Zugangscode</label><input id="access-code" type="password" required autocomplete="current-password"><p id="access-error" role="alert"></p><button class="button primary" type="submit">Verbinden</button></form></dialog>
<div id="toast" role="status" hidden></div>
</body></html>