Trust LLM: remove forced extension, content-driven prompt

User feedback: 'Tikaj more llm razmislat in ineti filing kaj dat notri'.
With Soniox transcript now accurate, LLM has all info to decide content-wise.

TWO CHANGES:

1. smart_clip_range() — REMOVED forced extension logic:
   Before: if duration < min_duration (20s):
       - extend to next chorus (40% match) ← WRONG! merged with B-chorus
       - extend symmetrically into VERSE ← WRONG! brought in kitica
       - cap at max_duration
   After: trust LLM completely. Only safety: clamp to video bounds.

2. Prompt rewrite — content-driven instead of number-driven:
   Before: 'Skupna dolžina: 12-25 sekund (običajno)' + conflicting '~30s'
           ' Drugi/tretji nastop refrena — uporabi PRVI'
   After: '~30 sekund (NAJBOLJŠA opcija = dva zaporedna refrena)'
          'Vključi naravne intro klice (Ajmo Janezi! Hey! Pa-pa!)'
          'BRAJDE primer: 41.8-69.8s = 28s (dva refrena z Ajmo Janezi intro)'
          'NE meša 2 RAZLIČNA refrena (A + B = napaka)'
          'NE razširi v VERZE/KITICE'

For BRAJDE this means:
- Old: Claude picked 57.1-69.8s (12.7s, 2nd chorus, no Ajmo)
       Code forced extension to 57.06-82.5s (mixed with B-chorus + verse)
- New: Claude picks 41.8-69.8s (28s, 2 choruses with 'Ajmo Janezi!' intro)
       Code returns exactly that — no forced extension.
This commit is contained in:
Sebastjan Artič 2026-04-30 04:39:26 +00:00
parent dc1cb1ad27
commit 22bb3cfe02

View File

@ -1218,18 +1218,19 @@ def find_chorus(transcript, energies, video_duration):
def smart_clip_range(chorus, transcript, video_duration,
target_duration=30, max_duration=45, min_duration=20,
include_prebuild=False):
"""Inteligentno določi clip range.
Logika:
1. Začni z refrenom kot core
2. Če je krajši od min_duration razširi z drugim refrenom (ne kitico!)
3. Cap na max_duration
include_prebuild=False (default): NE doda kitice/verza pred refrenom.
include_prebuild=True: doda kratek pre-chorus (max 8s, gap < 3s).
"""Vrne clip range TOČNO kot je odločil LLM.
Sistem NE razširja in NE skrajšuje LLM-ove odločitve. LLM ima ves
transkript + lyrics z web_search in lahko razmišlja vsebinsko o:
- kateri refren
- koliko ponovitev (1, 2, 3?)
- ali vključiti intro klic ('Ajmo Janezi!')
- kje naravno konča
Edina varnost: če Claude vrne nič, fallback na sredino videa.
"""
if not chorus or not chorus.get("best"):
# Fallback: vzemi sredino videa
# Fallback: sredina videa
mid = video_duration / 2
start = max(0, mid - target_duration / 2)
return {
@ -1239,63 +1240,16 @@ def smart_clip_range(chorus, transcript, video_duration,
}
best = chorus["best"]
sections = detect_vocal_sections(transcript["segments"])
actual_start = best["start"]
actual_end = best["end"]
# Najdi VSE sekcije ki so podobne refrenu (verjetne ponovitve)
chorus_words = set(re.findall(r"\b\w+\b", best["text_preview"].lower()))
chorus_sections = []
for sec in sections:
sec_words = set(re.findall(r"\b\w+\b", sec["text"].lower()))
if chorus_words and len(sec_words & chorus_words) >= len(chorus_words) * 0.4:
chorus_sections.append(sec)
# 1. Če je core refren prekratek, razširi z naslednjim REFRENOM (ne kitico!)
if actual_end - actual_start < min_duration:
for sec in chorus_sections:
if sec["start"] > actual_end and sec["start"] - actual_end < 8:
if sec["end"] - actual_start <= max_duration:
actual_end = sec["end"]
if actual_end - actual_start >= min_duration:
break
# 2. Pre-chorus build-up (samo če uporabnik to izrecno hoče)
if include_prebuild:
pre_section = None
for sec in sections:
# Pre-section mora biti BLIZU (gap < 3s) in NE preveč dolga (< 8s)
sec_duration = sec["end"] - sec["start"]
if (sec["end"] <= actual_start
and actual_start - sec["end"] < 3
and sec_duration < 8):
pre_section = sec
if pre_section:
candidate_start = pre_section["start"]
if actual_end - candidate_start <= max_duration:
actual_start = candidate_start
# 3. Če je še prekratek, razširi simetrično znotraj refrenov (ne kitic)
if actual_end - actual_start < min_duration:
deficit = min_duration - (actual_end - actual_start)
# Razširi konec če lahko
for sec in chorus_sections:
if sec["start"] > actual_end and sec["start"] - actual_end < 5:
actual_end = min(sec["end"], actual_end + deficit)
break
# Če še ni dovolj, manjše simetrično
if actual_end - actual_start < min_duration:
extra = (min_duration - (actual_end - actual_start)) / 2
actual_start = max(0, actual_start - extra)
actual_end = min(video_duration, actual_end + extra)
# 4. Trim na max
if actual_end - actual_start > max_duration:
actual_end = actual_start + max_duration
# Samo varnostni cap: NIKOLI ne čez video duration
actual_start = max(0, actual_start)
actual_end = min(video_duration, actual_end)
# Če je nekako reverse (start > end), popravi
if actual_start >= actual_end:
actual_end = min(video_duration, actual_start + target_duration)
return {
"start": round(actual_start, 2),
@ -1441,43 +1395,61 @@ PROSIM:
- Ohrani timestamp-e nespremenjene
3. Prepoznaj REFREN: del besedila ki se PONAVLJA (ponavadi 2-4 vrstice, ki se v pesmi večkrat ponovijo). To je **univerzalno za vse jezike** refren je strukturni element pesmi, ne le slovenske/nemške/angleške.
{"" if include_prebuild else '''4. **🎯 KRITIČNO PRAVILO: SAMO REFREN, NIČ DRUGEGA**
{"" if include_prebuild else '''4. **🎯 IZBIRA REFRENA — VSEBINSKO RAZMIŠLJANJE**
Uporabnik je izbral način "**SAMO REFREN**". To pomeni:
TI ODLOČAŠ na osnovi vsebine, ritma, energije pesmi.
Sistem ne bo razširil ne skrajšal tvoje izbire kar vrneš, to se uporabi.
## ⚠️ ABSOLUTNO PRAVILO: clip se ZAČNE TOČNO 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 ko prva beseda refrena začne** (npr. če prva beseda refrena "Žena" začne pri 78.0s, izberi start = 78.0s NE 77.7s)
- **Brez buffer-ja** clip začne natančno na vokalu
## CILJ: ~30 sekund (tipično za TikTok/Instagram Reel)
## Identifikacija refrena (univerzalno čez jezike):
- Najdi del, ki se v pesmi **ponavlja vsaj 2-krat** (običajno 3-4x)
- Refren ima ponavadi **najvišjo melodičnost**, "catchy" del
- Verzi pripovedujejo zgodbo (različno besedilo), refren je vedno enako besedilo
- Pri pop pesmih: refren običajno začne z naslovom pesmi ali znano frazo
- Lady Gaga "Abracadabra" refren = "Abracadabra, amor, ooh-na-na..."
- "Despacito" refren = "Despacito, quiero respirar..."
- "Shape of You" refren = "I'm in love with the shape of you..."
- Pri narodno-zabavnih (SL/HR/SR): refren je tisti del, ki se ponovi po vsakem verzu
- Pri Schlager (DE): refren je melodični "hook" del
Dolžina je SVOBODNA glede na strukturo pesmi:
- 12-15s = en kratki refren (če je pesem zelo kratka)
- **20-35s = dva zaporedna refrena (NAJBOLJŠA opcija!)** največkrat idealno
- 30-40s = refren + drug refren če sta vsebinsko povezana
## Konec: vključno s celotnim naravnim izpevom
- **Vse outro fraze** ki so del refrena (slo: "aj ja ja", "ej ej ej"; en: "yeah", "oh oh"; es: "ay ay ay"; ro: "hei hei"; ja: "la la la")
- Pevec drži zadnji ton 1-3s to je **del refrena**, ne reži ga
- Refren naj se **naravno izteče**
## STRATEGIJA — kako razmišljati:
## Skupna dolžina: 12-25 sekund (običajno)
- Če refren traja 18s izberi 18s
- Če refren traja 25s izberi 25s
- **NIKOLI ne dodajaj sekund pred refrenom** za "obogatitev"
## 🚫 NAJPOGOSTEJŠE NAPAKE (NE DELAJ TEH):
- Vključitev pre-chorusa "ker je vsebinsko povezan" NE, samo refren!
- Začetek 5s pred refrenom za "kontext" NE, točno na refrenu!
- Kombinacija pre-chorus + refren NE, zgolj refren!
- Drugi/tretji nastop refrena uporabi PRVI
- Sekanje sredi besede / izpeta tona
1. **Najdi PRVI nastop refrena** v pesmi
2. **Poglej KAJ SLEDI**:
- Če **takoj sledi DRUGI nastop ISTEGA refrena** (gap < 3s) **vključi oba** = ~30s. TO JE NAJBOLJ POGOST PRIMER.
- Če sledi **drug refren** (B-refren z drugim besedilom) samo prvi A-refren
- Če sledi instrumental break samo prvi refren
- Če sledi takoj verz samo prvi refren
3. **Vključi naravne intro klice/fraze**:
- "Ajmo Janezi!" pred BRAJDE refrenom = del refrena, vključi
- "Hey!" / "Yeah!" / "Oh!" intro klici = del refrena, vključi
- "Pa-pa!" / "La-la!" v začetku refrena = del refrena, vključi
4. **Naravni konec refrena**:
- Pevec drži zadnji ton 1-3s = del refrena
- Outro filler ("aj aj aj", "yeah yeah") = del refrena
- Ne reži sredi besede ali izpetega tona
## PRIMERI — kako se razmišlja:
**BRAJDE (FIRBCI x LIMA LEN):**
- Refren 1: "Ajmo Janezi! Pejd' greva..." 41.8-49.4s + "Da v senci hladni..." 50.2-56.1s
- GAP < 3s
- Refren 2: "Pejd' greva..." 57.1-63.1s + "Da v senci..." 63.8-69.8s
- **Izbira: 41.8-69.8s = 28s** (dva zaporedna refrena z "Ajmo Janezi" intro klicem)
**Lady Gaga "Abracadabra":**
- Refren: "Abracadabra, amor..." 4 vrstice
- Ponavadi se 2x ponovi
- Izbira: oba refrena = ~30s
**Žena Me Tepe:**
- Refren: "Žena me tepe, mi prazni žepe..."
- Ponavadi je dolg (15s) in se ponovi
- Izbira: lahko 1 polni refren ali 2 zaporedna
## 🚫 ČESAR NE DELAJ:
- NE razširi v VERZE/KITICE (verz pripoveduje zgodbo, ima drugo besedilo)
- NE meša 2 RAZLIČNA refrena (A-refren + B-refren = napaka)
- NE začni sredi refrena (vedno na PRVI besedi)
- NE konča sredi besede ali izpetega tona
- NE razmišljaj samo o številu sekund razmišljaj VSEBINSKO
'''}{'''4. **IZBERI ODSEK REFREN + PRE-CHORUS:**
Uporabnik je izbral način "**REFREN + PRE-CHORUS**".