tts-voice-creator-clone-and.../static/sections/s-clone.html
mARTin-B78 a0d94b140e Fix clone UX: sample text, live monitor, quality, STT picker, OGG accept
1. Sample text: expose initCloneSampleText as a window function and call
   it from nav.js runSideEffects when the clone section is activated,
   ensuring the textarea is always populated even if the IIFE ran before
   the element existed.

2. Better sample texts: all 8 languages rewritten to ~38 words / ~15 s,
   first-person, phonetically rich, proper Unicode diacritics.

3. Live mic monitor: a level-meter (18-bar) + scrolling oscilloscope
   canvas (ring-buffer, 300 px, colour-coded) added to the microphone
   card.  "Check level" / "Stop monitor" buttons start/stop it
   independently; clicking Record starts it automatically.
   Uses raw mic constraints (no echo-cancel / AGC) for cleaner voice clone
   audio.  Mic gain slider and dB readout included.

4. Recording quality: MediaRecorder now requests audioBitsPerSecond:256000
   in both voice-clone.js and stt.js.

5. STT engine picker: Recognition engine <select> + Refresh button added
   above the Auto-transcribe button in Step 3.  refreshSttBackends() now
   syncs both stt-tts-stt-backend and clone-stt-backend.  The transcribe
   call passes the chosen backend to /api/transcribe.

6. File input: explicit extension list added to accept= for OGG/OPUS.

7. CSS: .mic-live-wave style added (dark/light theme variants).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 17:58:28 +02:00

155 lines
8.7 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.

<div class="section-head">
<span class="section-icon"><span class="mdi mdi-microphone-variant"></span></span>
<div class="section-title">
<h2>Clone a Voice</h2>
<p>Upload or record 3-20 seconds of audio, trim it, then save it as a reusable voice clone.</p>
</div>
</div>
<!-- Step 1: Load audio -->
<div class="tab-content" id="tab-source">
<div class="card">
<h2>Step 1 &mdash; Load audio</h2>
<p class="card-subtitle">Drop a file, paste a URL, or record directly from your microphone.</p>
<div id="drop-zone">
<strong>Drop an audio / video file here</strong>
<span>WAV &middot; MP3 &middot; OGG &middot; FLAC &middot; M4A &middot; MP4 &middot; MKV &middot; WEBM</span>
<span style="margin-top:10px;font-size:12px;color:var(--subtext)">or click to browse</span>
<input type="file" id="file-input" accept=".wav,.mp3,.ogg,.opus,.flac,.m4a,.mp4,.mkv,.webm,.mov,.avi,audio/*,video/*">
</div>
</div>
<div class="card">
<h2>YouTube / URL</h2>
<p class="card-subtitle">Download audio from a direct link or YouTube video.</p>
<div class="url-row">
<input type="text" id="yt-url" placeholder="https://www.youtube.com/watch?v=...">
<button class="btn-primary" id="yt-btn">Download</button>
</div>
<div id="yt-progress"></div>
</div>
<div class="card">
<h2>Microphone</h2>
<p class="card-subtitle">Record a fresh sample with live input level monitoring.</p>
<div class="sample-read-box" style="margin-bottom:12px">
<div class="sample-head">
<label for="clone-sample-lang">Read aloud</label>
<select id="clone-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="clone-sample-text" spellcheck="true"></textarea>
</div>
<div class="btn-row">
<button class="btn-secondary" id="clone-monitor-btn"><span class="mdi mdi-waveform"></span> Check level</button>
<button class="btn-secondary" id="clone-monitor-stop" disabled>Stop monitor</button>
<button class="btn-red" id="rec-start-btn"><span class="mdi mdi-record-circle-outline"></span> Record</button>
<button class="btn-secondary" id="rec-stop-btn" disabled><span class="mdi mdi-stop-circle-outline"></span> Stop</button>
<div id="rec-indicator"><div id="rec-dot"></div><span id="rec-time">0:00</span></div>
</div>
<div class="mic-monitor-box" id="clone-monitor-box" style="margin-top:10px">
<div class="mic-monitor-head">
<span>Input level</span>
<span class="meter-readout" id="clone-db-readout">-∞ dB</span>
</div>
<div class="mic-meter" id="clone-mic-meter" aria-hidden="true"></div>
<canvas id="clone-live-wave" class="mic-live-wave" width="300" height="48" aria-hidden="true"></canvas>
<div class="mic-gain-row">
<label for="clone-mic-gain">Mic gain</label>
<input id="clone-mic-gain" type="range" min="0" max="2" step="0.05" value="1">
<span class="mic-gain-value" id="clone-mic-gain-value">1.00x</span>
</div>
<div class="note" style="margin-top:4px">Best peaks: 18 to 9 dB. Never red.</div>
</div>
</div>
<div class="card" id="waveform-card" style="display:none">
<h2>Step 2 &mdash; Trim selection</h2>
<p class="card-subtitle">Select the best 320 s of clean speech from the waveform.</p>
<div id="waveform-wrap"><div id="waveform"></div></div>
<div class="time-row">
<label>Start (s) <input type="number" id="trim-start" value="0" min="0" step="0.1"></label>
<label>End (s) &nbsp;<input type="number" id="trim-end" value="0" min="0" step="0.1"></label>
<span id="trim-duration" class="dur-ok">0.0 s</span>
</div>
<div class="btn-row">
<button class="btn-primary" id="trim-btn">Confirm trim &rarr; Name &amp; Save</button>
<button class="btn-secondary" id="auto-trim-btn">Auto trim</button>
<button class="btn-secondary" id="play-btn"><span class="mdi mdi-play"></span> Play</button>
<button class="btn-secondary" id="play-selection-btn"><span class="mdi mdi-play"></span> Play selection</button>
</div>
</div>
</div><!-- /tab-source -->
<!-- Step 3: Name and save -->
<div class="tab-content" id="tab-save">
<div class="card">
<h2>Step 3 &mdash; Name the voice</h2>
<p class="card-subtitle">Assign a unique ID, language, and gender — e.g. <code>EN_F_Anna</code>.</p>
<div class="voice-id-row">
<input type="text" id="voice-id-input" placeholder="e.g. EN_F_Anna or MyCustomVoice" spellcheck="false">
</div>
<div id="voice-id-hint" class="note" style="min-height:1.2em"></div>
<details class="helper">
<summary>Build from parts &nbsp;(LANG &middot; GENDER &middot; Name helper)</summary>
<div class="helper-body">
<div class="field">
<label>Language</label>
<select id="lang-select">
<option>EN</option><option>DE</option><option>ZH</option><option>FR</option>
<option>ES</option><option>JA</option><option>KO</option><option>IT</option>
<option>PT</option><option>RU</option><option>AR</option><option>PL</option>
<option>NL</option><option>SV</option><option>TR</option><option>HI</option>
</select>
</div>
<div class="field">
<label>Gender</label>
<select id="gender-select">
<option value="F">F &mdash; Female</option>
<option value="M">M &mdash; Male</option>
<option value="N">N &mdash; Neutral</option>
</select>
</div>
<div class="field" style="flex:1;min-width:120px">
<label>Name (no spaces)</label>
<input type="text" id="name-input" placeholder="Anna">
</div>
<button class="btn-secondary" id="helper-apply-btn" style="align-self:flex-end">Apply &rarr;</button>
</div>
</details>
</div>
<div class="card">
<h2>Transcript (reference text)</h2>
<p class="card-subtitle">The spoken text that matches this audio — type it or auto-transcribe.</p>
<div class="btn-row" style="gap:6px;align-items:center;flex-wrap:wrap;margin-bottom:8px">
<label style="font-size:13px;color:var(--subtext);white-space:nowrap">Recognition engine:</label>
<select id="clone-stt-backend" style="flex:1;min-width:160px"><option value="configured">Configured Whisper/STT</option></select>
<button class="btn-secondary" id="clone-refresh-stt-btn" type="button">Refresh</button>
</div>
<div class="btn-row">
<button class="btn-secondary" id="transcribe-btn"><span class="mdi mdi-message-text-outline"></span> Auto-transcribe</button>
<span id="transcribe-status" style="font-size:13px;color:var(--subtext)"></span>
</div>
<textarea id="transcript-area" placeholder="Type or auto-transcribe the spoken text&hellip;"></textarea>
</div>
<div class="card">
<h2>Audio preview</h2>
<p class="card-subtitle">Play back the trimmed audio before saving to the library.</p>
<audio id="trim-audio" controls style="display:none"></audio>
<p id="no-audio-hint" class="note">No audio loaded yet. Load a file above (Step 1) or use Voice Design below.</p>
</div>
<div class="card">
<h2>Step 4 &mdash; Save to library</h2>
<p class="card-subtitle">Write the cloned voice to your active voices folder.</p>
<div class="btn-row">
<button class="btn-green" id="save-btn"><span class="mdi mdi-memory"></span> Save to Voice Library</button>
</div>
<div id="save-result" class="note" style="display:none"></div>
</div>
</div><!-- /tab-save -->