tts-voice-creator-clone-and.../static/js/init.js
mARTin-B78 c7a1e35539 Security audit, modular refactor, and container-name field
Security fixes:
- Block /proc /sys /dev /run /boot in /api/browse-dirs (path traversal)
- Verify yt-dlp output stays inside TEMP_DIR before registration
- Remove Access-Control-Allow-Origin: * from /api/proxy-audio
- TTL-based temp file registry (default 2h) to prevent disk fill

Performance:
- Cache settings + routing rules in memory (mtime-checked); eliminates
  per-request disk reads on every TTS call

UI:
- Add container name (optional) field to Docker stack TTS/STT engine
  cards (Qwen3 Voice Clone, Voice Design, Custom Voice, Streaming,
  NVIDIA Magpie, Parakeet) — enables Stop/Start/Restart buttons on
  all engine cards, matching the existing Other Local TTS/STT cards

Refactor — backend:
- server.py: 5560 lines → 43-line entry point
- core/ package: constants, registry, validation, docker_client,
  config, routing, audio, voice, presets, tts_helpers
- routes/ package: admin, settings, library, stt, sources, docker,
  tts, conversation (FastAPI APIRouter modules)
- Dockerfile + docker-compose.yml updated to include core/ and routes/

Refactor — frontend:
- static/app.js: 8744 lines → 16 modules in static/js/
  utils, voice-inspector, voice-sources, integrations, routing,
  settings, voice-clone, voice-library, tts-preview, benchmark,
  stt, init, engines, ai-backends, generation, conversation
- static/loader.js updated to load modules sequentially

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 12:13:07 +02:00

50 lines
2.1 KiB
JavaScript

// ── Init ──────────────────────────────────────────────────────────────────
initBenchmarkSampleControls();
// Sync visible preview-text input with hidden benchmark-sample-text
(function syncPreviewInput() {
const visible = $('vl-preview-sample');
const hidden = $('benchmark-sample-text');
if (!visible) return;
const stored = localStorage.getItem(BENCHMARK_SAMPLE_STORAGE_KEY);
visible.value = stored || DEFAULT_BENCHMARK_SAMPLE_TEXT;
if (hidden) hidden.value = visible.value;
visible.addEventListener('input', () => {
if (hidden) hidden.value = visible.value;
localStorage.setItem(BENCHMARK_SAMPLE_STORAGE_KEY, visible.value.trim());
});
})();
// Sync flag button to current preview text language (best-match)
(function syncPreviewLangBtn() {
const ta = $('vl-preview-sample');
const btn = $('vl-preview-lang-btn');
if (!ta || !btn) return;
const cur = ta.value.trim();
const matched = Object.keys(VL_SAMPLE_TEXTS).find(l => VL_SAMPLE_TEXTS[l] === cur) || 'EN';
const cc = (_VL_LANG_FLAG[matched] || 'gb').toLowerCase();
btn.innerHTML = `<span class="fi fi-${cc}"></span>`;
btn.title = (LANGUAGE_LABELS[matched] || matched) + ' — click to change sample language';
btn.dataset.lang = matched;
})();
// Synth mode segmented control (preview text vs. reference transcript)
(function initSynthMode() {
const seg = $('vl-synth-mode-seg');
const wrap = $('vl-preview-text-wrap');
if (!seg) return;
seg.querySelectorAll('.vl-synth-seg-btn').forEach(btn => {
btn.addEventListener('click', () => {
seg.querySelectorAll('.vl-synth-seg-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
if (wrap) wrap.classList.toggle('hidden', btn.dataset.mode === 'transcript');
});
});
})();
loadSettings().then(() => {
refreshSttBackends();
renderIntegrationSnippets();
if (!localStorage.getItem(SETTINGS_SEEN_KEY)) openSettings(true);
}).catch(e => status('Settings load failed: ' + e.message));