My Voices - Top bar with search, filter toggle (active-count badge), synth-source drawer, group and table buttons; filters/sort in a collapsible labelled panel; one-line sort header with select-all/none checkbox - Groups chip list is a collapsed accordion; bottom bar is Refresh/Sync/Import plus one Actions (N) menu (Edit / Audio / Share / Danger), disabled until voices are checked; touch targets stay 44px - Copy selected works again (copyText was no longer exported), shows "N voice names copied to clipboard" and falls back to a copy dialog when the async clipboard is unavailable TTS / engines - Health probe works for /v1 card URLs and, behind a LiteLLM gateway, checks the selected model's own upstream so stopped containers are not reported as available - Unhiding a voice publishes a missing entry to the engine's voices.json (no more silent default-voice fallback) - Status-bar TTS picker also drives the My Voices and STT-test selectors; Use as TTS refreshes the status bar Includes the engine connect/disconnect, custom TTS, STT footer and magazine auth work that was already in the working tree, with their tests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
350 lines
26 KiB
HTML
350 lines
26 KiB
HTML
<div class="section-head">
|
||
<span class="section-icon"><span class="mdi mdi-account-voice"></span></span>
|
||
<div class="section-title">
|
||
<h2>My Voices</h2>
|
||
<p>Pick a voice on the left, edit on the right.</p>
|
||
</div>
|
||
<div class="section-head-actions">
|
||
<input type="search" class="section-search" id="section-voices-search" placeholder="Search voices…" autocomplete="off"
|
||
oninput="var f=document.getElementById('library-filter-text');if(f){f.value=this.value;f.dispatchEvent(new Event('input'));}">
|
||
<button class="btn-primary section-new-voice-btn" onclick="document.getElementById('add-new-voice-btn')?.click()">+ New voice</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Workbench: list pane + inspector pane -->
|
||
<div class="voices-workbench" id="tab-library">
|
||
|
||
<!-- LEFT: compact voice list — two cards -->
|
||
<div class="voices-list-pane">
|
||
|
||
<!-- Card 2: filters + sort + voice list + toolbar -->
|
||
<div class="vl-card vl-card-list">
|
||
<!-- Top bar: search + filter toggle + view buttons. Filters/sort live in a collapsible panel. -->
|
||
<div class="vl-topbar">
|
||
<input type="search" id="library-filter-text" placeholder="Search voices…" aria-label="Search voices" autocomplete="off" class="vl-search vl-search-main">
|
||
<button id="vl-synth-toggle" class="vl-sort-dir-btn" type="button" aria-expanded="false" aria-controls="vl-synth-drawer" title="Preview text & synth source" aria-label="Preview text and synth source"><span class="mdi mdi-account-voice" aria-hidden="true"></span></button>
|
||
<button id="vl-filter-toggle" class="vl-sort-dir-btn vl-filter-toggle" type="button" aria-expanded="false" aria-controls="vl-filter-panel" title="Show filters and sorting"><span class="mdi mdi-filter-variant" aria-hidden="true"></span><span class="vl-filter-badge" id="vl-filter-badge" hidden>0</span><span class="sr-only"> Filters</span></button>
|
||
<button id="voice-group-tag-btn" class="vl-sort-dir-btn" type="button" title="Group into virtual folders by tag" aria-label="Group by tag"><span class="mdi mdi-folder-outline" aria-hidden="true"></span></button>
|
||
<button id="voice-table-view-btn" class="vl-sort-dir-btn" type="button" title="Toggle full-width table view" aria-label="Table view"><span class="mdi mdi-table" aria-hidden="true"></span></button>
|
||
<button id="voice-table-edit-btn" class="vl-sort-dir-btn" type="button" title="Toggle table edit mode" aria-label="Table edit mode" style="display:none"><span class="mdi mdi-pencil-box-outline" aria-hidden="true"></span></button>
|
||
</div>
|
||
<div class="vl-synth-drawer" id="vl-synth-drawer" hidden>
|
||
<div class="vl-synth-panel">
|
||
<div class="vl-synth-mode-row">
|
||
<span class="vl-synth-icon"><span class="mdi mdi-play"></span><span class="mdi mdi-play"></span></span>
|
||
<span class="vl-synth-label">Synth uses</span>
|
||
<div class="vl-synth-seg" id="vl-synth-mode-seg">
|
||
<button class="vl-synth-seg-btn active" data-mode="preview"
|
||
title="Synthesize the preview sentence — good for comparing voices side by side">Preview text</button>
|
||
<button class="vl-synth-seg-btn" data-mode="transcript"
|
||
title="Synthesize this voice’s saved reference transcript — good for quality check vs. original recording">Reference transcript</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="vl-preview-text-wrap" id="vl-preview-text-wrap">
|
||
<div class="vl-preview-row">
|
||
<button class="vl-preview-lang-btn" id="vl-preview-lang-btn"
|
||
title="English — click to change sample language"
|
||
onclick="openPreviewLangPicker(this)" data-lang="EN">
|
||
<span class="fi fi-gb"></span>
|
||
</button>
|
||
<textarea class="vl-preview-input" id="vl-preview-sample" rows="2"
|
||
placeholder="Sample sentence for TTS preview…"
|
||
oninput="var t=document.getElementById('benchmark-sample-text');if(t){t.value=this.value;t.dispatchEvent(new Event('input'));}"
|
||
></textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="vl-filter-panel" id="vl-filter-panel" role="group" aria-label="Filter and sort voices" hidden>
|
||
<div class="vl-filter-grid">
|
||
<label>Language <select id="library-filter-lang"><option value="">All</option></select></label>
|
||
<label>Gender <select id="library-filter-sex"><option value="">All</option></select></label>
|
||
<label>Type <select id="library-filter-type"><option value="">All types</option></select></label>
|
||
<label>Tag <select id="library-filter-tag"><option value="">All tags</option></select></label>
|
||
<label>Rating <select id="library-filter-rating" >
|
||
<option value="">All ratings</option>
|
||
<option value="5">★★★★★</option>
|
||
<option value="4">★★★★+</option>
|
||
<option value="3">★★★+</option>
|
||
<option value="2">★★+</option>
|
||
<option value="1">★+</option>
|
||
<option value="0">Unrated</option>
|
||
</select></label>
|
||
<label>Group <select id="library-filter-group"><option value="">All groups</option></select></label>
|
||
<label>Sort by <select id="voice-sort-field" title="Sort field">
|
||
<option value="id">Name</option>
|
||
<option value="flag">Language</option>
|
||
<option value="gender">Gender</option>
|
||
<option value="benchmark">Speed</option>
|
||
<option value="rating">Rating</option>
|
||
<option value="duration">Duration</option>
|
||
<option value="dbfs">Volume dB</option>
|
||
<option value="source">Source</option>
|
||
<option value="seed">Seed</option>
|
||
<option value="note">Note</option>
|
||
<option value="tag">Tags</option>
|
||
<option value="enabled">Active</option>
|
||
</select></label>
|
||
<label>Order <button id="voice-sort-dir" class="vl-sort-dir-btn vl-sort-dir-wide" type="button" title="Toggle sort direction"><span class="mdi mdi-arrow-up" aria-hidden="true"></span></button></label>
|
||
</div>
|
||
<div class="vl-filter-actions">
|
||
<label class="vl-disabled-label"><input type="checkbox" id="show-disabled-cb"> Show disabled</label>
|
||
<button id="library-clear-filters" class="btn-secondary vl-tb-btn" type="button" title="Clear all filters"><span class="mdi mdi-filter-off-outline" aria-hidden="true"></span> Clear filters</button>
|
||
</div>
|
||
<div id="voice-groups-bar" class="voice-groups-bar" hidden></div>
|
||
</div>
|
||
|
||
<div class="benchmark-confirm" id="benchmark-confirm" hidden role="group" aria-live="polite">
|
||
<strong id="benchmark-confirm-title">Benchmark active voices?</strong>
|
||
<span id="benchmark-confirm-text"></span>
|
||
<button class="btn-secondary" id="benchmark-confirm-cancel" type="button">Cancel</button>
|
||
<button class="benchmark-confirm-start" id="benchmark-confirm-start" type="button">Start benchmark</button>
|
||
</div>
|
||
|
||
|
||
<!-- Bulk-edit toolbar — appears when voices are selected -->
|
||
<div class="vl-bulk-bar" id="vl-bulk-bar" hidden>
|
||
<span class="vl-bulk-count" id="vl-bulk-count" role="status">0 selected</span>
|
||
</div>
|
||
|
||
<div class="vl-table-header" id="vl-table-header">
|
||
<div style="display:flex; justify-content:center; align-items:center;"><input type="checkbox" id="vl-select-all-header" class="vl-select-all-cb" title="Select all visible voices" aria-label="Select all visible voices"></div>
|
||
<div>Img</div>
|
||
<div>Play</div>
|
||
<div class="vl-th-sortable" data-sort="id">Name <span class="mdi mdi-sort"></span></div>
|
||
<div class="vl-th-sortable" data-sort="flag">Lang <span class="mdi mdi-sort"></span></div>
|
||
<div class="vl-th-sortable" data-sort="gender">Gender <span class="mdi mdi-sort"></span></div>
|
||
<div class="vl-th-sortable" data-sort="factor">Factor <span class="mdi mdi-sort"></span><span class="vl-th-info mdi mdi-information-outline" title="Speed multiplier: audio duration ÷ render time. Above 1.0× means the GPU is faster than real-time — higher is better."></span></div>
|
||
<div class="vl-th-sortable" data-sort="wpm">WPM <span class="mdi mdi-sort"></span><span class="vl-th-info mdi mdi-information-outline" title="Words per minute the voice speaks. 130–180 wpm is natural for audiobooks; lower = slower, more deliberate pace."></span></div>
|
||
<div class="vl-th-sortable" data-sort="seed">Seed <span class="mdi mdi-sort"></span></div>
|
||
<div class="vl-th-sortable" data-sort="dbfs">dBFS <span class="mdi mdi-sort"></span></div>
|
||
<div>Type</div>
|
||
<div class="vl-th-sortable" data-sort="source">Source <span class="mdi mdi-sort"></span></div>
|
||
<div class="vl-th-sortable" data-sort="rating">Rating <span class="mdi mdi-sort"></span></div>
|
||
<div class="vl-th-sortable" data-sort="tag">Tags <span class="mdi mdi-sort"></span></div>
|
||
<div class="vl-th-sortable" data-sort="note">Note <span class="mdi mdi-sort"></span></div>
|
||
<div class="vl-th-sortable" data-sort="enabled">Active <span class="mdi mdi-sort"></span></div>
|
||
</div>
|
||
<div class="vl-compact-header" id="vl-compact-header" role="group" aria-label="Sort voices">
|
||
<input type="checkbox" class="vl-select-all-cb" title="Select all / none of the visible voices" aria-label="Select all visible voices">
|
||
<button type="button" class="vl-th-sortable" data-sort="id">Name <span class="mdi mdi-sort" aria-hidden="true"></span></button>
|
||
<button type="button" class="vl-th-sortable" data-sort="flag">Lang <span class="mdi mdi-sort" aria-hidden="true"></span></button>
|
||
<button type="button" class="vl-th-sortable" data-sort="gender">Gender <span class="mdi mdi-sort" aria-hidden="true"></span></button>
|
||
<button type="button" class="vl-th-sortable" data-sort="benchmark">Speed <span class="mdi mdi-sort" aria-hidden="true"></span></button>
|
||
<button type="button" class="vl-th-sortable" data-sort="rating">Rating <span class="mdi mdi-sort" aria-hidden="true"></span></button>
|
||
</div>
|
||
<div id="voice-list" tabindex="0" role="region" aria-label="Voice library"></div>
|
||
<div class="vl-toolbar">
|
||
<button class="btn-secondary vl-tb-btn" id="refresh-voices-btn" title="Refresh voice list"><span class="mdi mdi-refresh" aria-hidden="true"></span><span class="vl-tb-label"> Refresh</span></button>
|
||
<button class="btn-secondary vl-tb-btn" id="sync-voice-folders-btn" title="Sync active/hidden folders"><span class="mdi mdi-sync" aria-hidden="true"></span><span class="vl-tb-label"> Sync</span></button>
|
||
<button class="btn-secondary vl-tb-btn" id="import-voices-btn" title="Import a .voice.zip bundle; an existing voice is never overwritten"><span class="mdi mdi-import" aria-hidden="true"></span><span class="vl-tb-label"> Import bundle</span></button>
|
||
<input type="file" id="import-voices-input" accept=".zip,application/zip" multiple hidden>
|
||
<div class="vl-actions">
|
||
<button type="button" class="btn-primary vl-actions-btn" id="vl-actions-btn" aria-expanded="false" aria-controls="vl-actions-menu" disabled title="Check one or more voices to enable actions"><span class="mdi mdi-lightning-bolt-outline" aria-hidden="true"></span> Actions <span class="vl-actions-n" id="vl-actions-n"></span> <span class="mdi mdi-chevron-up" aria-hidden="true"></span></button>
|
||
<div class="vl-actions-menu" id="vl-actions-menu" role="group" aria-label="Actions on the checked voices" hidden>
|
||
<div class="vl-menu-title">Edit</div>
|
||
<button class="vl-menu-item" id="vl-bulk-tag" title="Add a tag to the selected voices, keeping their existing tags"><span class="mdi mdi-tag-outline" aria-hidden="true"></span> Set tag</button>
|
||
<button class="vl-menu-item" id="vl-bulk-source" title="Set source / origin on selected voices"><span class="mdi mdi-database-outline" aria-hidden="true"></span> Set source</button>
|
||
<button class="vl-menu-item" id="vl-bulk-rating" title="Set star rating on selected"><span class="mdi mdi-star-outline" aria-hidden="true"></span> Rate</button>
|
||
<button class="vl-menu-item" id="vl-bulk-hide" title="Disable (hide) selected voices"><span class="mdi mdi-eye-off-outline" aria-hidden="true"></span> Hide</button>
|
||
<button class="vl-menu-item" id="vl-bulk-unhide" title="Enable (unhide) selected voices"><span class="mdi mdi-eye-outline" aria-hidden="true"></span> Unhide</button>
|
||
<div class="vl-menu-title">Audio</div>
|
||
<button class="vl-menu-item" id="precompute-embeddings-btn" title="Warm all active voices so the TTS engine pre-computes & caches each speaker embedding (.pt) — makes first playback instant"><span class="mdi mdi-flash-outline"></span> Precompute</button>
|
||
<button class="vl-menu-item" id="calculate-db-btn" title="Calculate dBFS"><span class="mdi mdi-sine-wave" aria-hidden="true"></span> Calc dB</button>
|
||
<button class="vl-menu-item" id="benchmark-voices-btn" title="Benchmark TTS speed"><span class="mdi mdi-speedometer" aria-hidden="true"></span> Benchmark</button>
|
||
<button class="vl-menu-item" id="seed-batch-all-btn" title="Generate & cache Seed Finder samples for every active voice (skips already-cached; resumable)"><span class="mdi mdi-dice-multiple-outline"></span> Batch seeds</button>
|
||
<button class="vl-menu-item" id="verify-voices-stt-btn" title="Synthesize a test sentence with each voice, transcribe it back with Whisper, and compare to the original text — catches repeated/garbled/nonsense output that a duration-only benchmark misses"><span class="mdi mdi-check-decagram-outline"></span> Verify (STT)</button>
|
||
<div class="vl-menu-title">Share</div>
|
||
<button class="vl-menu-item" id="copy-active-voices-btn" title="Copy the names of the checked voices, comma separated (e.g. for SillyTavern)"><span class="mdi mdi-content-copy" aria-hidden="true"></span> Copy selected</button>
|
||
<button class="vl-menu-item" id="export-voices-btn" title="Export the checked voices as .voice.zip bundles (backup / share)"><span class="mdi mdi-export" aria-hidden="true"></span> Export selected</button>
|
||
<div class="vl-menu-title">Danger</div>
|
||
<button class="vl-menu-item vl-bulk-danger" id="vl-bulk-delete" title="Delete selected voices permanently"><span class="mdi mdi-delete-outline" aria-hidden="true"></span> Delete</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="vl-footer">
|
||
<span id="voice-count" class="note"></span>
|
||
<button class="vl-add-btn" id="add-new-voice-btn" style="display:none" aria-hidden="true" tabindex="-1" title="Add a new voice to the library">+ Add voice</button>
|
||
</div>
|
||
</div><!-- /vl-card-list -->
|
||
|
||
</div><!-- /voices-list-pane -->
|
||
|
||
<!-- RIGHT: inspector / editor pane -->
|
||
<div class="voices-inspector-pane" id="voices-inspector">
|
||
<div class="inspector-placeholder">
|
||
<span><span class="mdi mdi-account-voice"></span></span>
|
||
<p>Pick a voice on the left<br>to edit it here</p>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /voices-workbench -->
|
||
|
||
<!-- Hidden scaffold — IDs required by voice-library.js but not shown in new layout -->
|
||
<div id="vl-scaffold" style="display:none" aria-hidden="true">
|
||
|
||
<div id="library-filter-panel"></div>
|
||
<div class="library-insights" id="library-insights"></div>
|
||
<div class="disabled-info" id="disabled-info">
|
||
<strong>About disabled voices:</strong> The Active toggle moves the voice package between
|
||
<code>active_voices</code> and <code>hidden_voices</code>. Qwen3-TTS should scan only <code>active_voices</code>.
|
||
</div>
|
||
|
||
<!-- Audio playback bar -->
|
||
<div id="lib-audio-bar">
|
||
<div class="lib-audio-label" id="lib-audio-label">-</div>
|
||
<audio id="lib-audio" controls></audio>
|
||
</div>
|
||
|
||
<!-- Benchmark config panel -->
|
||
<div class="library-benchmark-panel">
|
||
<textarea id="benchmark-sample-text" placeholder="Sample sentence for benchmark"></textarea>
|
||
<select id="library-tts-backend-select"><option value="">Checking backends...</option></select>
|
||
<input type="number" id="library-target-db" value="-20" min="-60" max="-1" step="0.5">
|
||
<button id="normalize-volume-btn">Normalize volume</button>
|
||
<select id="benchmark-preset-select" title="Load a benchmark sentence preset">
|
||
<option value="">Sentence presets…</option>
|
||
<option value="de">DE — Die Welt ist voller Geschichten…</option>
|
||
<option value="en">EN — The old lighthouse stood firm…</option>
|
||
<option value="de2">DE — Der schnelle braune Fuchs…</option>
|
||
<option value="en2">EN — She sells seashells…</option>
|
||
<option value="reset">↺ Reset to default</option>
|
||
</select>
|
||
<button id="benchmark-use-preview-btn">Use preview text</button>
|
||
</div>
|
||
|
||
<!-- Benchmark progress -->
|
||
<div class="benchmark-progress" id="benchmark-progress" hidden aria-live="polite">
|
||
<div class="benchmark-progress-head">
|
||
<span id="benchmark-progress-label">Benchmarking voices...</span>
|
||
<span id="benchmark-progress-count">0 / 0</span>
|
||
</div>
|
||
<div class="benchmark-progress-track" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
|
||
<div id="benchmark-progress-bar"></div>
|
||
</div>
|
||
<div class="benchmark-live-stats" id="benchmark-live-stats">
|
||
<span>Elapsed -</span><span>Avg -</span><span>ETA -</span><span>OK 0</span><span>Slow 0</span><span>Errors 0</span>
|
||
</div>
|
||
<div class="benchmark-live-last" id="benchmark-live-last"></div>
|
||
</div>
|
||
|
||
<!-- Add new voice panel -->
|
||
<div class="lib-add-panel" id="lib-add-panel">
|
||
<div class="lib-add-stack">
|
||
<div class="lib-add-section">
|
||
<h2 style="margin-bottom:10px">1 Load or record source</h2>
|
||
<div class="lib-add-input-grid">
|
||
<div class="lib-add-import-box">
|
||
<input type="file" id="lib-add-file" accept="audio/*,video/*" style="display:none">
|
||
<div class="lib-add-drop" id="lib-add-drop">
|
||
<strong>Drop an audio / video file here</strong>
|
||
<span>WAV · MP3 · OGG · FLAC · M4A · MP4 · MKV · WEBM</span>
|
||
<span>or click to browse</span>
|
||
</div>
|
||
<div>
|
||
<label class="note" for="lib-add-url">Audio or video URL</label>
|
||
<div class="url-row">
|
||
<input type="text" id="lib-add-url" placeholder="Paste a direct MP3/WAV, YouTube, or Aiartes URL">
|
||
<button class="btn-primary" id="lib-add-url-btn">Download URL</button>
|
||
</div>
|
||
<div class="btn-row">
|
||
<button class="btn-secondary" id="lib-iso-btn" hidden>Remove background music</button>
|
||
<button class="btn-secondary" id="lib-iso-toggle" hidden></button>
|
||
</div>
|
||
<div class="note" id="lib-iso-msg" role="status" aria-live="polite"></div>
|
||
</div>
|
||
</div>
|
||
<div class="lib-add-source-box lib-add-record-box">
|
||
<div class="record-head">
|
||
<span class="note">Record a fresh sample</span>
|
||
<div class="record-head-actions">
|
||
<button class="btn-secondary" id="lib-add-mic-help-btn">How to unlock mic</button>
|
||
</div>
|
||
</div>
|
||
<div class="lib-add-recorder-tools">
|
||
<div class="lib-add-mic-row">
|
||
<div class="mic-buttons">
|
||
<button class="btn-secondary" id="lib-add-monitor-btn">Check level</button>
|
||
<button class="btn-secondary" id="lib-add-monitor-stop" disabled>Stop monitor</button>
|
||
<button class="btn-red" id="lib-add-rec-start"><span class="mdi mdi-record-circle-outline"></span> Record</button>
|
||
<button class="btn-secondary" id="lib-add-rec-stop" disabled><span class="mdi mdi-stop-circle-outline"></span> Stop</button>
|
||
<span class="mic-timer" id="lib-add-rec-time">0:00</span>
|
||
</div>
|
||
<div class="mic-monitor-box">
|
||
<div class="mic-monitor-head">
|
||
<span>Input level</span>
|
||
<span class="meter-readout" id="lib-add-db-readout">-<span class="mdi mdi-infinity"></span> dB</span>
|
||
</div>
|
||
<div class="mic-meter" id="lib-add-mic-meter" aria-hidden="true"></div>
|
||
<div class="mic-gain-row">
|
||
<label for="lib-add-mic-gain">Mic gain</label>
|
||
<input id="lib-add-mic-gain" type="range" min="0" max="2" step="0.05" value="1">
|
||
<span class="mic-gain-value" id="lib-add-mic-gain-value">1.00x</span>
|
||
</div>
|
||
<div class="note" style="margin-top:5px">Best peaks: -18 to -9 dB, never red.</div>
|
||
</div>
|
||
</div>
|
||
<div class="sample-read-box">
|
||
<div class="sample-head">
|
||
<label for="lib-add-sample-lang">Read sample</label>
|
||
<select id="lib-add-sample-lang">
|
||
<option value="EN">English</option><option value="DE">Deutsch</option>
|
||
<option value="IT">Italiano</option><option value="ES">Español</option>
|
||
<option value="FR">Français</option><option value="PT">Português</option>
|
||
<option value="NL">Nederlands</option><option value="PL">Polski</option>
|
||
</select>
|
||
</div>
|
||
<textarea class="sample-sentence" id="lib-add-sample-text" spellcheck="true"></textarea>
|
||
<div class="sample-actions">
|
||
<button class="btn-secondary" id="lib-add-use-sample">Use as transcript</button>
|
||
<button class="btn-secondary" id="lib-add-reset-sample">Reset sentence</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="mic-help-panel" id="lib-add-mic-help">
|
||
<strong>If the microphone is blocked:</strong>
|
||
<ul>
|
||
<li><strong>Chrome/Brave/Edge:</strong> click the lock icon in the address bar → Microphone → Allow, then reload.</li>
|
||
<li><strong>Firefox:</strong> click the lock icon → remove Blocked → Allow, then reload.</li>
|
||
<li><strong>Safari:</strong> Settings → Websites → Microphone → allow this site.</li>
|
||
</ul>
|
||
</div>
|
||
<div class="opt-status" id="lib-add-status">Load a file, paste a URL, or record. Then trim, name, and save.</div>
|
||
</div>
|
||
</div>
|
||
<div class="lib-add-audio-row">
|
||
<audio id="lib-add-audio" controls style="display:none"></audio>
|
||
<div class="btn-row">
|
||
<button class="btn-secondary" id="lib-add-auto-trim">Auto trim</button>
|
||
<button class="btn-primary" id="lib-add-save-crop">Crop selection</button>
|
||
<button class="btn-secondary" id="lib-add-play">Play crop</button>
|
||
</div>
|
||
</div>
|
||
<canvas class="opt-wave" id="lib-add-wave" style="display:none;margin-top:10px"></canvas>
|
||
<div class="opt-controls">
|
||
<div class="opt-field"><label>Start</label><input id="lib-add-start" type="number" step="0.01" value="0"></div>
|
||
<div class="opt-field"><label>End</label><input id="lib-add-end" type="number" step="0.01" value="0"></div>
|
||
<button class="btn-primary" id="lib-add-save-crop-bottom">Crop selection</button>
|
||
<span class="crop-duration-hint" id="lib-add-crop-hint">Select 3-20 seconds for best cloning.</span>
|
||
</div>
|
||
</div>
|
||
<div class="lib-add-section">
|
||
<h2 style="margin-bottom:10px">2 Name and save voice</h2>
|
||
<div class="lib-add-name-grid">
|
||
<div class="opt-field"><label>Language</label><select id="lib-add-lang" data-langsel data-default="EN" aria-label="Voice language" title="Search by name or code; regional accents use BCP 47 subtags (EN-GB, EN-AU)"></select></div>
|
||
<div class="opt-field"><label>Gender</label><input id="lib-add-gender" value="N"></div>
|
||
<div class="opt-field"><label>Voice ID</label><input id="lib-add-voice-id" placeholder="EN_N_NewVoice"></div>
|
||
</div>
|
||
<textarea id="lib-add-transcript" placeholder="Reference transcript" style="margin-top:10px"></textarea>
|
||
<div class="btn-row" style="margin-top:10px">
|
||
<button class="btn-secondary" id="lib-add-recognize">Recognise text</button>
|
||
<button class="btn-green" id="lib-add-save">Save voice</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /vl-scaffold -->
|