- Sidebar collapses to a 56px icon rail; hovering flies the full menu out as an overlay (icons + titles/nested items). Language picker moved to Settings. - Unify settings collapsibles to the app's standard card-collapse style: Conversation, Read Aloud (drag-&-drop now inside), Try It Out, Casting panel. - Read Aloud: reordered (settings → toolbar → document → transport/synth) and the document fits the viewport height so controls below stay visible; remove the redundant My Books card (lives in Library → Books). - Conversation: stacked full-width config, fills viewport height; fix intermittent webm decode in hands-free mode (recorder restarts cleanly, in-browser WAV encode); barge-in via Live agent. - Fix casting feed overflow that pushed the sidebar off-screen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
281 lines
17 KiB
HTML
281 lines
17 KiB
HTML
<div class="section-head">
|
|
<span class="section-icon"><span class="mdi mdi-cog-outline"></span></span>
|
|
<div class="section-title">
|
|
<h2>Settings</h2>
|
|
<p>Configure general app behaviour, default parameters, and persistent storage settings.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tab-content" id="tab-settings">
|
|
|
|
<!-- ── General ─────────────────────────────────────────────── -->
|
|
<div class="s-settings-page" data-page="general">
|
|
<div class="card">
|
|
<div class="s-page-head">
|
|
<h3>General</h3>
|
|
<p>Interface preferences.</p>
|
|
</div>
|
|
<div class="settings-grid settings-behavior-grid">
|
|
<div class="s-field">
|
|
<label>Theme</label>
|
|
<select id="s-theme-select">
|
|
<option value="light">Light</option>
|
|
<option value="dark">Dark</option>
|
|
</select>
|
|
<span class="s-hint">Switch between light and dark interface. Saved instantly.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>Language</label>
|
|
<select id="s-lang-select"></select>
|
|
<span class="s-hint">Interface language. Saved instantly — the app reloads to apply.</span>
|
|
</div>
|
|
<div class="s-field" style="grid-column: 1 / -1">
|
|
<label>Default Seed Finder text</label>
|
|
<textarea id="s-seed-finder-text" placeholder="Leave empty for language-specific defaults..." style="min-height:60px; font-family:inherit; resize:vertical;"></textarea>
|
|
<span class="s-hint">Custom test sentence used when opening the Seed Finder.</span>
|
|
</div>
|
|
</div>
|
|
<div class="s-page-actions">
|
|
<button class="btn-primary s-save-btn">Save settings</button>
|
|
<button class="btn-secondary s-reload-btn">Reload settings</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ── Payloads ─────────────────────────────────────────────── -->
|
|
<div class="s-settings-page" data-page="payloads">
|
|
<div class="card">
|
|
<div class="s-page-head">
|
|
<h3>Payloads</h3>
|
|
<p>Extra JSON fields sent alongside each backend request. Usually only needed for advanced tuning.</p>
|
|
</div>
|
|
<div class="settings-grid three settings-param-grid">
|
|
<div class="s-field">
|
|
<label>Voice Clone / Base params</label>
|
|
<textarea id="s-tts-extra-voice-clone" spellcheck="false" placeholder='{"temperature":0.1,"top_p":0.8,"seed":0}'></textarea>
|
|
<span class="s-hint">Extra fields for the 8020 WAV voice clone/base model.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>Streaming params</label>
|
|
<textarea id="s-tts-extra-streaming" spellcheck="false" placeholder='{"temperature":0.1,"top_p":0.8,"seed":0}'></textarea>
|
|
<span class="s-hint">Extra fields for the 8023 streaming model.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>CustomVoice params</label>
|
|
<textarea id="s-tts-extra-customvoice" spellcheck="false" placeholder='{"temperature":0.1,"top_p":0.8,"seed":0}'></textarea>
|
|
<span class="s-hint">Extra fields for the CustomVoice backend.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>Voice Design params</label>
|
|
<textarea id="s-tts-extra-voice-design" spellcheck="false" placeholder='{"temperature":0.1,"top_p":0.8,"seed":0}'></textarea>
|
|
<span class="s-hint">Extra fields for Voice Design and virtual <code>vd_...</code> voices.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>NVIDIA Magpie params</label>
|
|
<textarea id="s-tts-extra-nvidia-magpie" spellcheck="false" placeholder="{}"></textarea>
|
|
<span class="s-hint">Usually empty. Magpie accepts fixed speakers: sofia, aria, jason, leo, john.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>NVIDIA Zeroshot params</label>
|
|
<textarea id="s-tts-extra-nvidia-zeroshot" spellcheck="false" placeholder='{"zero_shot_quality":20}'></textarea>
|
|
<span class="s-hint">Optional multipart fields. The app supplies <code>text</code>, <code>language</code>, <code>audio_prompt</code>.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>NVIDIA Flow params</label>
|
|
<textarea id="s-tts-extra-nvidia-flow" spellcheck="false" placeholder="{}"></textarea>
|
|
<span class="s-hint">Optional multipart fields. The app also sends the saved reference transcript.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>Kokoro FastAPI params</label>
|
|
<textarea id="s-tts-extra-kokoro" spellcheck="false" placeholder="{}"></textarea>
|
|
<span class="s-hint">Extra JSON fields for Kokoro. Usually empty — voice is selected from the dropdown.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>VibeVoice params</label>
|
|
<textarea id="s-tts-extra-vibevoice" spellcheck="false" placeholder="{}"></textarea>
|
|
<span class="s-hint">Extra JSON fields for VibeVoice. Usually empty — service only requires text.</span>
|
|
</div>
|
|
</div>
|
|
<div class="s-page-actions">
|
|
<button class="btn-primary s-save-btn">Save settings</button>
|
|
<button class="btn-secondary s-reload-btn">Reload settings</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── Storage ─────────────────────────────────────────────── -->
|
|
<div class="s-settings-page" data-page="storage">
|
|
<div class="card">
|
|
<div class="s-page-head">
|
|
<h3>Storage</h3>
|
|
<p>Container paths for voice files. Match these to your Portainer volume mounts.</p>
|
|
</div>
|
|
<div class="settings-grid">
|
|
<div class="s-field">
|
|
<label>Voice scan directory</label>
|
|
<div class="s-key-row">
|
|
<input type="text" id="s-voices-scan-dir" placeholder="/voices">
|
|
<button type="button" class="btn-secondary s-browse-dir-btn" data-target="s-voices-scan-dir" title="Browse container folders"><span class="mdi mdi-folder-search-outline"></span></button>
|
|
</div>
|
|
<span class="s-hint">Contains <code>active_voices</code>, <code>hidden_voices</code>, sounds, and metadata.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>Active voices directory</label>
|
|
<div class="s-key-row">
|
|
<input type="text" id="s-output-dir" placeholder="/voices/active_voices">
|
|
<button type="button" class="btn-secondary s-browse-dir-btn" data-target="s-output-dir" title="Browse container folders"><span class="mdi mdi-folder-search-outline"></span></button>
|
|
</div>
|
|
<span class="s-hint">New cloned/exported voices are saved here.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>Seed Finder Sample Files</label>
|
|
<div class="s-key-row">
|
|
<input type="text" id="s-seed-finder-dir" placeholder="/voices/seed_finder">
|
|
<button type="button" class="btn-secondary s-browse-dir-btn" data-target="s-seed-finder-dir" title="Browse container folders"><span class="mdi mdi-folder-search-outline"></span></button>
|
|
</div>
|
|
<span class="s-hint">Directory containing generated seed finder samples.</span>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>PT Files</label>
|
|
<div class="s-key-row">
|
|
<input type="text" id="s-pt-dir" placeholder="/voices/pt_files">
|
|
<button type="button" class="btn-secondary s-browse-dir-btn" data-target="s-pt-dir" title="Browse container folders"><span class="mdi mdi-folder-search-outline"></span></button>
|
|
</div>
|
|
<span class="s-hint">Directory for saved embedding models (.pt files).</span>
|
|
</div>
|
|
</div>
|
|
<div class="s-page-actions">
|
|
<button class="btn-primary s-save-btn">Save settings</button>
|
|
<button class="btn-secondary s-reload-btn">Reload settings</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── API Keys ─────────────────────────────────────────────── -->
|
|
<div class="s-settings-page" data-page="apikeys">
|
|
<div class="card">
|
|
<div class="s-page-head">
|
|
<h3>API Keys</h3>
|
|
<p>Usually empty for local containers. Set a dummy value like <code>sk-local</code> if a backend requires an Authorization header.</p>
|
|
</div>
|
|
<div class="settings-grid three">
|
|
<div class="s-field">
|
|
<label>TTS API key <span class="s-label-note">(optional)</span></label>
|
|
<div class="s-key-row">
|
|
<input type="password" id="s-tts-key" placeholder="dummy, sk-local, or leave empty" autocomplete="off">
|
|
<button type="button" class="s-eye-btn" data-target="s-tts-key"><span class="mdi mdi-eye-outline"></span></button>
|
|
</div>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>Voice Design API key <span class="s-label-note">(optional)</span></label>
|
|
<div class="s-key-row">
|
|
<input type="password" id="s-vd-key" placeholder="dummy, sk-local, or leave empty" autocomplete="off">
|
|
<button type="button" class="s-eye-btn" data-target="s-vd-key"><span class="mdi mdi-eye-outline"></span></button>
|
|
</div>
|
|
</div>
|
|
<div class="s-field">
|
|
<label>Whisper API key <span class="s-label-note">(optional)</span></label>
|
|
<div class="s-key-row">
|
|
<input type="password" id="s-whisper-key" placeholder="dummy, sk-local, or leave empty" autocomplete="off">
|
|
<button type="button" class="s-eye-btn" data-target="s-whisper-key"><span class="mdi mdi-eye-outline"></span></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="s-page-actions">
|
|
<button class="btn-primary s-save-btn">Save settings</button>
|
|
<button class="btn-secondary s-reload-btn">Reload settings</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── Backup ─────────────────────────────────────────────── -->
|
|
<div class="s-settings-page" data-page="backup">
|
|
<div class="card">
|
|
<div class="s-page-head">
|
|
<h3>Backup & restore</h3>
|
|
<p>Export all voices and settings as a ZIP for backup or migration. API keys are excluded from exports.</p>
|
|
</div>
|
|
<div class="btn-row" style="gap:10px;flex-wrap:wrap">
|
|
<a class="btn-secondary" id="s-export-voices-btn" href="/api/voices/export" download><span class="mdi mdi-download"></span> Export voices</a>
|
|
<label class="btn-secondary" style="cursor:pointer" title="Import a voices ZIP">
|
|
<span class="mdi mdi-upload"></span> Import voices
|
|
<input type="file" id="s-import-voices-file" accept=".zip" style="display:none">
|
|
</label>
|
|
<span class="note" id="s-import-status"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── Logs ─────────────────────────────────────────────────── -->
|
|
<div class="s-settings-page" data-page="logs">
|
|
<div class="card">
|
|
<div class="s-page-head">
|
|
<h3>Logs</h3>
|
|
<p>Recent server activity. Useful for debugging backend connections and API errors.</p>
|
|
</div>
|
|
<div class="s-log-toolbar">
|
|
<button class="btn-secondary" id="s-logs-refresh-btn" type="button"><span class="mdi mdi-refresh"></span> Refresh</button>
|
|
<button class="btn-secondary" id="s-logs-clear-btn" type="button"><span class="mdi mdi-trash-can-outline"></span> Clear</button>
|
|
<label class="s-log-live-label">
|
|
<input type="checkbox" id="s-logs-live-toggle">
|
|
<span>Auto-refresh</span>
|
|
</label>
|
|
<span class="s-log-count" id="s-log-count"></span>
|
|
</div>
|
|
<div class="s-log-filters">
|
|
<button class="s-log-filter is-active" data-log-level="">All</button>
|
|
<button class="s-log-filter" data-log-level="ERROR">Error</button>
|
|
<button class="s-log-filter" data-log-level="WARNING">Warning</button>
|
|
<button class="s-log-filter" data-log-level="INFO">Info</button>
|
|
</div>
|
|
<div class="s-log-viewer" id="s-log-viewer">
|
|
<div class="s-log-empty">Click Refresh to load logs</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── About ─────────────────────────────────────────────────── -->
|
|
<div class="s-settings-page" data-page="about">
|
|
<div class="card">
|
|
<div class="s-page-head">
|
|
<h3>About</h3>
|
|
</div>
|
|
<div class="s-about-block">
|
|
<div class="s-about-name">
|
|
<span class="mdi mdi-microphone-variant"></span> TTS Voice Creator
|
|
<span id="s-about-version" style="font-size:13px;font-weight:500;color:var(--subtext);margin-left:8px;vertical-align:middle"></span>
|
|
</div>
|
|
<p class="s-about-desc">Clone, design, and deploy custom voices using local AI backends. Compatible with Qwen3-TTS, Kokoro FastAPI, NVIDIA Magpie, and any OpenAI-compatible TTS/STT endpoint.</p>
|
|
<div class="s-about-stack">
|
|
<span class="s-about-chip"><span class="mdi mdi-language-python"></span> FastAPI</span>
|
|
<span class="s-about-chip"><span class="mdi mdi-language-javascript"></span> Vanilla JS</span>
|
|
<span class="s-about-chip"><span class="mdi mdi-music-note"></span> WaveSurfer.js v7</span>
|
|
<span class="s-about-chip"><span class="mdi mdi-vector-square"></span> MDI v7.4.47</span>
|
|
</div>
|
|
<div class="s-about-backends" id="s-about-backends"></div>
|
|
<div style="margin-top:14px;display:flex;gap:10px;flex-wrap:wrap">
|
|
<a href="https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/releases" target="_blank" rel="noopener" class="btn-secondary" style="text-decoration:none;display:inline-flex;align-items:center;gap:6px"><span class="mdi mdi-tag-outline"></span> Releases & Changelog</a>
|
|
<a href="https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2" target="_blank" rel="noopener" class="btn-secondary" style="text-decoration:none;display:inline-flex;align-items:center;gap:6px"><span class="mdi mdi-github"></span> GitHub</a>
|
|
</div>
|
|
<p class="note" style="margin-top:10px">MCP server, REST /speak endpoint, and global hotkey daemon are documented under <strong>Connect Apps</strong>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="card" style="margin-top:0">
|
|
<details id="about-changelog-details">
|
|
<summary style="cursor:pointer;font-weight:600;font-size:15px;padding:4px 0;list-style:none;display:flex;align-items:center;gap:8px">
|
|
<span class="mdi mdi-history"></span> Changelog
|
|
<span id="about-changelog-status" style="font-size:12px;color:var(--subtext);font-weight:400;margin-left:auto"></span>
|
|
</summary>
|
|
<pre id="about-changelog-content" style="margin-top:12px;white-space:pre-wrap;font-size:12px;line-height:1.6;color:var(--text);font-family:monospace;max-height:400px;overflow-y:auto;background:var(--surface);border:1px solid var(--border);border-radius:6px;padding:12px"></pre>
|
|
</details>
|
|
</div>
|
|
</div>
|
|
|
|
</div><!-- /tab-settings -->
|