tts-voice-creator-clone-and.../static/sections/s-clone.html
mARTin-B78 40e42590cc Release v1.6.0: a11y (WCAG AA), i18n (DE), PWA, perf, tests, Cast UX
Cast: card/list views, sort & filter, online voice picker, "Hear a line"
sample button, AI character notes, import auto-save.

Platform: WCAG 2.1 AA accessibility pass; German UI translation + language
picker; installable PWA with offline shell; GZip + content-visibility
virtualization + lazy images + Rehearser PCM memory cap (mobile stability);
Playwright suite (desktop + iPhone); opt-in minified bundle build.

Fixes: screenplay parser false characters; Fish-Speech inline-tag tones;
narrator/voice pickers list full library; clone GUI rework; fish.audio
import dedup; voice-ID rename; bulk-delete modal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 14:23:35 +02:00

180 lines
11 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>Capture 320 seconds of clean speech, trim it, name it, then save it as a reusable voice clone.</p>
</div>
</div>
<!-- Audio source — integrated tabs (record / upload / link) -->
<div class="tab-content" id="tab-source">
<div class="clone-tabbox">
<div class="clone-src-picker" id="clone-src-picker" role="tablist">
<button class="clone-src-tab active" data-src="mic" role="tab"><span class="mdi mdi-microphone"></span> Microphone</button>
<button class="clone-src-tab" data-src="file" role="tab"><span class="mdi mdi-file-music-outline"></span> Upload file</button>
<button class="clone-src-tab" data-src="url" role="tab"><span class="mdi mdi-link-variant"></span> URL / YouTube</button>
</div>
<div class="clone-srcpanel">
<!-- Microphone -->
<div class="clone-src-card" id="clone-src-mic" data-src="mic">
<p class="clone-src-intro"><span class="mdi mdi-microphone"></span> Record a fresh sample with live input-level monitoring.</p>
<div class="field" style="max-width:320px">
<label for="clone-your-name">Voice name</label>
<input type="text" id="clone-your-name" placeholder="e.g. Anna" spellcheck="false" autocomplete="off">
<p class="note">Sets the voice name and is dropped into the sentence below.</p>
</div>
<div class="sample-read-box" style="margin-top:12px">
<div class="sample-head">
<label for="clone-sample-lang">Read this 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" aria-label="Sample sentence to read aloud" spellcheck="true">Hello! My name is Sam, and this is my voice. I can speak softly or with great strength. The crisp winter air, warm firelight, and the gentle sound of rain — these are the things I love. Can you hear how clearly I speak?</textarea>
<p class="note" style="margin-top:6px"><span class="mdi mdi-pencil-outline"></span> Edit the sentence freely before recording.</p>
</div>
<div class="btn-row" style="margin-top:12px">
<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>
<!-- Upload file -->
<div class="clone-src-card" id="clone-src-file" data-src="file" hidden>
<p class="clone-src-intro"><span class="mdi mdi-file-music-outline"></span> Drop an audio or video file, or click to browse.</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>
<!-- URL / YouTube -->
<div class="clone-src-card" id="clone-src-url" data-src="url" hidden>
<p class="clone-src-intro"><span class="mdi mdi-link-variant"></span> Paste a direct audio link or a YouTube URL to grab the audio.</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><!-- /clone-srcpanel -->
</div><!-- /clone-tabbox -->
<!-- Trim (appears once audio is loaded) -->
<div class="card" id="waveform-card" style="display:none">
<h2><span class="mdi mdi-content-cut"></span> Trim your sample</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 -->
<!-- Name, transcribe, preview & save -->
<div class="tab-content" id="tab-save">
<div class="card">
<h2><span class="mdi mdi-account-voice"></span> Name your voice</h2>
<p class="card-subtitle">Choose language &amp; gender and type a name — the ID builds automatically (e.g. <code>EN_F_Anna</code>). You can also type a custom ID.</p>
<div class="clone-id-row">
<div class="field">
<label for="lang-select">Language</label>
<select id="lang-select" aria-label="Voice language">
<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 for="gender-select">Gender</label>
<select id="gender-select" aria-label="Voice gender">
<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:140px">
<label>Name (no spaces)</label>
<input type="text" id="name-input" placeholder="Anna">
</div>
<button class="btn-secondary" id="helper-apply-btn" hidden>Apply &rarr;</button>
</div>
<div class="field" style="margin-top:14px">
<label for="voice-id-input">Final voice ID</label>
<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>
</div>
</div>
<div class="card">
<h2><span class="mdi mdi-message-text-outline"></span> Reference transcript</h2>
<p class="card-subtitle">The exact words spoken in the audio — type them 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" aria-label="Speech-to-text recognition engine" 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><span class="mdi mdi-play-circle-outline"></span> Preview</h2>
<p class="card-subtitle">Listen to the trimmed audio before saving.</p>
<audio id="trim-audio" controls style="display:none"></audio>
<p id="no-audio-hint" class="note">No audio yet — record or load a sample above, or use Voice Design.</p>
</div>
<div class="card">
<h2><span class="mdi mdi-content-save-outline"></span> Save to library</h2>
<p class="card-subtitle">Write the cloned voice to your active voices folder.</p>
<div class="btn-row" style="align-items:center;gap:12px">
<button class="btn-green" id="save-btn"><span class="mdi mdi-memory"></span> Save to Voice Library</button>
<label class="chunk-toggle-label" style="font-size:12px;gap:5px" title="Save automatically once audio, ID and transcript are all ready (re-saves when you change details)">
<input type="checkbox" id="clone-autosave-toggle" checked>
<span>Auto-save when ready</span>
</label>
</div>
<div id="save-result" class="note" style="display:none"></div>
</div>
</div><!-- /tab-save -->