diff --git a/scripts/analyze.py b/scripts/analyze.py index 496d936..3b8b320 100644 --- a/scripts/analyze.py +++ b/scripts/analyze.py @@ -742,9 +742,12 @@ def detect_audio_fade(clip_range, transcript, video_duration=None): if video_duration is not None: extended_end = min(extended_end, video_duration) - fade_in = 0.4 if starts_in_vocal else 0.2 + # Fade-in: če clip začne MED vokalom, fade-in mora biti zelo kratek + # da ne odreže prve besede. Pri vokalnem začetku samo 0.05s "smooth click prevention", + # ne pravi audible fade. Pri instrumentalnem intro lahko 0.2-0.3s. + fade_in = 0.05 if starts_in_vocal else 0.2 # Krajši fade out (0.5s) ker zdaj clip konča po koncu vokala - fade_out = 0.5 if ends_in_vocal else 0.3 + fade_out = 0.3 if ends_in_vocal else 0.4 return { "fade_in": fade_in, @@ -838,7 +841,8 @@ PROSIM: ## ⚠️ ABSOLUTNO PRAVILO: clip se ZAČNE na PRVI BESEDI prvega refrena - **NE** vključuj kateri koli verz, pre-chorus, build-up, ali intro - **NE** začni "tik pred" refrenom - - **Začetek = točno tam, kjer prva vrstica refrena prvič začne** + - **Začetek = ~0.3s PRED prvo besedo refrena** (npr. če prva beseda refrena "Žena" začne pri 78.0s, izberi start = 77.7s) + - **Razlog**: 0.3s buffer da ne odrežeš prve besede zaradi audio fade-in efekta ## Identifikacija refrena (univerzalno čez jezike): - Najdi del, ki se v pesmi **ponavlja vsaj 2-krat** (običajno 3-4x) @@ -1350,6 +1354,57 @@ def main(): duration # ne čez celoten audio ) + # ── EXTEND clip START nazaj če Claude začne sredi besede/segmenta ── + # Refren se pogosto začne na isti besedi kot v transkriptu, ampak Scribe + # lahko zazna mejo med segmenti **PO** prvi besedi refrena (npr. + # "Žena me tepe" — beseda "Žena" v prejšnjem segmentu pri 78.0s, + # nov segment začne pri 78.3s s "tepe"). To pomeni Claude reže + # PRED besedo "Žena" → odrezana. + # + # Strategija: če clip start pade SREDI segmenta (ne tik na začetku), + # razširi nazaj na začetek tega segmenta + 0.2s buffer. + current_start = clip_range["start"] + for seg in corrected_segs: + seg_start = float(seg.get("start", 0)) + seg_end = float(seg.get("end", 0)) + # Segment ki se prekriva s clip start (start je MED njim) + if seg_start < current_start < seg_end: + # Razširi nazaj — vendar samo če je segment kratek (<3s) in + # se "naslanja" na clip (zadnja beseda lahko vodi v refren) + if (seg_end - seg_start) < 3.0: + new_start = max(0, seg_start - 0.2) # 0.2s buffer pred prvo besedo + if new_start < current_start: + print(f" 🎵 Razširim clip začetek {current_start:.1f}s → {new_start:.1f}s " + f"(prva beseda refrena je v prejšnjem segmentu)", file=sys.stderr) + current_start = new_start + break + # Segment ki se konča TOČNO ali tik pred clip start (lahko zadnja + # beseda refrena = "Žena" se konča na 78.2 ko clip začne 78.3) + elif current_start - 0.5 <= seg_end <= current_start + 0.1: + # Preveri ali zadnja beseda v segmentu morda **začne refren** + seg_text = seg.get("text", "").strip() + # Če segment kaže novo frazo (z veliko začetnico po pavzi) ali + # vsebuje znake interpunkcije, morda zadnja beseda res začne refren + if seg_text and (seg_end - seg_start) < 4.0: + # Razširi nazaj na začetek POSLEDJE besede tega segmenta + words = seg.get("words", []) + if words: + last_word = words[-1] + new_start = max(0, float(last_word.get("start", seg_start)) - 0.15) + else: + # Brez word-level: vzemi 0.5s nazaj + new_start = max(0, current_start - 0.5) + if new_start < current_start: + print(f" 🎵 Razširim clip začetek {current_start:.1f}s → {new_start:.1f}s " + f"(zadnja beseda prejšnjega segmenta morda začne refren)", file=sys.stderr) + current_start = new_start + break + + if current_start < clip_range["start"]: + clip_range["start"] = round(current_start, 2) + clip_range["duration"] = round(clip_range["end"] - current_start, 2) + clip_range["reason"] += f" (start extended back)" + # Najdi vse segmente ki se začnejo PO trenutnem clip end for seg in corrected_segs: seg_start = float(seg.get("start", 0))