Inspector: - Skinny 2-row header: 72px avatar + name/ID row / subtitle row / note row - Searchable flag picker (dblclick flag icon) — filtered by voice language, falls back to ALL_FLAGS - Searchable language picker (dblclick lang code) — shows full language names - Tag reuse: entered tags persist to localStorage as datalist suggestions - Compact active toggle (32×18px), slim save button (12px/4px padding) - Show/hide eye toggle and "✓ Key saved" badge on API key fields AI Backends (s-llms.html + style.css): - Full CSS design: pill tabs with active accent, animated section transitions - Service cards: icon bubbles, tier badges (Free/Demo/Paid), stat chips, endpoint rows, model tags - Highlighted recommended card with accent border - Dark code blocks for local service snippets with copy feedback - Show/hide password toggle and auto-appearing "✓ Key saved" badge per card Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
111 lines
5.8 KiB
HTML
111 lines
5.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>TTS Voice Creator</title>
|
|
<!-- WaveSurfer must load synchronously before app.js initialises audio -->
|
|
<script src="https://unpkg.com/wavesurfer.js@7/dist/wavesurfer.min.js"></script>
|
|
<script src="https://unpkg.com/wavesurfer.js@7/dist/plugins/regions.min.js"></script>
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flag-icons@7.3.2/css/flag-icons.min.css">
|
|
<link rel="stylesheet" href="/static/style.css">
|
|
</head>
|
|
<body>
|
|
|
|
<!-- Hidden tabs nav — required for JS backend availability detection -->
|
|
<nav class="tabs" style="display:none" aria-hidden="true">
|
|
<div class="tab active" data-tab="library" data-backend-required="voice_clone" tabindex="-1"><span class="tab-title">Voice Clone</span></div>
|
|
<div class="tab" data-tab="design" data-backend-required="voice_design" tabindex="-1"><span class="tab-title">Voice Design</span></div>
|
|
<div class="tab" data-tab="custom" data-backend-required="customvoice" tabindex="-1"><span class="tab-title">Voice Custom</span></div>
|
|
<div class="tab" data-tab="generation" data-backend-required="any_tts" tabindex="-1"><span class="tab-title">TTS Generation</span></div>
|
|
<div class="tab" data-tab="stt-tts" data-backend-required="any_tts" tabindex="-1"><span class="tab-title">STT-TTS</span></div>
|
|
<div class="tab" data-tab="routing" tabindex="-1"><span class="tab-title">Routing</span></div>
|
|
<div class="tab" data-tab="integrations" tabindex="-1"><span class="tab-title">How to</span></div>
|
|
<div class="tab" data-tab="getvoices" tabindex="-1"><span class="tab-title">Get Voices</span></div>
|
|
<div class="tab" data-tab="settings" tabindex="-1"><span class="tab-title">Settings</span></div>
|
|
</nav>
|
|
|
|
<!-- App shell -->
|
|
<div id="app-shell">
|
|
|
|
<!-- Sidebar -->
|
|
<aside id="sidebar">
|
|
<div class="sidebar-brand">
|
|
<h1>🎤 Voice Creator</h1>
|
|
<p>Clone · Design · Deploy</p>
|
|
</div>
|
|
|
|
<nav class="sidebar-nav">
|
|
<div class="nav-group-label">Voices</div>
|
|
<div class="nav-item nav-tree-head active" data-nav-section="s-voices" id="nav-voices-head" onclick="navTo('s-voices')">
|
|
<span class="nav-icon">🔊</span>
|
|
<span class="nav-label">My Voices</span>
|
|
<span class="nav-badge" id="nav-voices-count"></span>
|
|
<span class="nav-chevron" id="nav-voices-chevron">⌄</span>
|
|
</div>
|
|
<div class="nav-tree open" id="nav-voices-tree">
|
|
<div class="nav-tree-item is-active" data-voice-cat="all" onclick="navVoicesCat('all')">All voices <span class="ntc" id="ntc-all"></span></div>
|
|
<div class="nav-tree-item" data-voice-cat="cloned" onclick="navVoicesCat('cloned')">Cloned <span class="ntc" id="ntc-cloned"></span></div>
|
|
<div class="nav-tree-item" data-voice-cat="designed" onclick="navVoicesCat('designed')">Designed <span class="ntc" id="ntc-designed"></span></div>
|
|
<div class="nav-tree-item" data-voice-cat="favorites" onclick="navVoicesCat('favorites')">Favorites <span class="ntc" id="ntc-favorites"></span></div>
|
|
<div class="nav-tree-item" data-voice-cat="hidden" onclick="navVoicesCat('hidden')">Hidden <span class="ntc" id="ntc-hidden"></span></div>
|
|
<div class="nav-tree-item" data-voice-cat="tools" onclick="navVoicesCat('tools')">Library tools</div>
|
|
</div>
|
|
<div class="nav-item" data-nav-section="s-clone" onclick="navTo('s-clone')">
|
|
<span class="nav-icon">🎤</span> Clone a Voice
|
|
</div>
|
|
<div class="nav-item" data-nav-section="s-design" onclick="navTo('s-design')">
|
|
<span class="nav-icon">✨</span> Design a Voice
|
|
</div>
|
|
<div class="nav-item" data-nav-section="s-studio" onclick="navTo('s-studio')">
|
|
<span class="nav-icon">🌐</span> Get Voices Online
|
|
</div>
|
|
<div class="nav-item" data-nav-section="s-tryout" onclick="navTo('s-tryout')">
|
|
<span class="nav-icon">▶</span> Try It Out
|
|
</div>
|
|
|
|
<div class="nav-group-label" style="margin-top:6px">Setup</div>
|
|
<div class="nav-item" data-nav-section="s-llms" onclick="navTo('s-llms')">
|
|
<span class="nav-icon">🧠</span> LLMs
|
|
</div>
|
|
<div class="nav-item" data-nav-section="s-routing" onclick="navTo('s-routing')">
|
|
<span class="nav-icon">⇌</span> App Routing
|
|
</div>
|
|
<div class="nav-item" data-nav-section="s-connect" onclick="navTo('s-connect')">
|
|
<span class="nav-icon">🔗</span> Connect Apps
|
|
</div>
|
|
<div class="nav-item" data-nav-section="s-settings" onclick="navTo('s-settings')">
|
|
<span class="nav-icon">⚙</span> Settings
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="sidebar-footer">
|
|
<button id="theme-btn" title="Switch theme" style="display:none">☀</button>
|
|
<button id="settings-btn" onclick="navTo('s-settings')" title="Open settings">⚙ Settings</button>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Main scrollable content — sections filled by loader.js -->
|
|
<main id="main-content">
|
|
<section class="page-section" id="s-voices"></section>
|
|
<section class="page-section" id="s-clone"></section>
|
|
<section class="page-section" id="s-design"></section>
|
|
<section class="page-section" id="s-studio"></section>
|
|
<section class="page-section" id="s-tryout"></section>
|
|
<section class="page-section" id="s-routing"></section>
|
|
<section class="page-section" id="s-connect"></section>
|
|
<section class="page-section" id="s-settings"></section>
|
|
<section class="page-section" id="s-llms"></section>
|
|
</main>
|
|
|
|
</div><!-- /app-shell -->
|
|
|
|
<div id="toast"></div>
|
|
<div id="status-bar">Loading…</div>
|
|
|
|
<!-- loader.js: fetches sections → loads app.js → loads nav.js -->
|
|
<script src="/static/loader.js"></script>
|
|
|
|
</body>
|
|
</html>
|