Major: smart selection pipeline (analyze.py) + audio fade + multi-lang auto-detect

- New analyze.py: full transcript + energy + structural analysis
- Smart clip range: includes pre-chorus, can exceed 30s up to max_duration (default 45s)
- Audio fade in/out: auto-detected from vocal boundaries
- Instrumental detection: auto-disables subs if vocals < 10% of duration
- Multi-language: auto-detect via Whisper or explicit (DE/SL/HR/BS/SR/EN/IT/ES/FR)
- Frontend: cleaner UX, added bs language, smart selection description
- reframe.py: --fade-in --fade-out args
- clip.py: propagates fade params
- app/main.py: replaces find_chorus.py call with analyze.py
This commit is contained in:
2026-04-29 06:21:35 +00:00
parent 81edd24ca3
commit 8512076b91
5 changed files with 572 additions and 36 deletions
+19 -5
View File
@@ -216,12 +216,16 @@
<div>
<label>Jezik podnapisov</label>
<select id="lang">
<option value="">Auto detect</option>
<option value="">Auto detect (Whisper)</option>
<option value="sl">Slovenščina</option>
<option value="de">Deutsch</option>
<option value="en">English</option>
<option value="hr">Hrvatski</option>
<option value="bs">Bosanski</option>
<option value="sr">Српски</option>
<option value="it">Italiano</option>
<option value="es">Español</option>
<option value="fr">Français</option>
</select>
</div>
<div>
@@ -238,8 +242,13 @@
<label class="toggle" style="margin-top: 16px;">
<input type="checkbox" id="auto-chorus" checked>
Avto-detekcija refrena (priporočeno za glasbo)
Pametna izbira odseka (Whisper + energy → najde refren)
</label>
<div style="font-size: 12px; color: var(--text-dim); margin-top: 4px; margin-left: 26px;">
Sistem analizira celoten video, najde refren ter pre-chorus build-up.
Lahko traja malo dlje (do 1.5×) če to bolje prikazuje pesem.
Audio fade in/out je avtomatsko dodan.
</div>
<div id="manual-times" class="row hidden">
<div>
@@ -353,13 +362,18 @@
// ─── Settings collector ─────────────────────────
function collectSettings() {
const auto = $("#auto-chorus").checked;
const duration = parseFloat($("#duration").value) || 30;
return {
mode: $("#mode").value,
lang: $("#lang").value || null,
whisper_model: $("#model").value,
auto_chorus: $("#auto-chorus").checked,
start: !$("#auto-chorus").checked && $("#start").value ? parseTimestamp($("#start").value) : null,
duration: parseFloat($("#duration").value) || 30,
auto_chorus: auto,
start: !auto && $("#start").value ? parseTimestamp($("#start").value) : null,
duration: duration,
// Smart selection: max do 1.5x ciljno trajanje, min 0.7x
max_duration: auto ? Math.round(duration * 1.5) : duration,
min_duration: auto ? Math.round(duration * 0.7) : duration,
subtitle_style: $("#subtitle-style").value,
quality: $("#quality").value,
no_subs: $("#no-subs").checked,