Multi-upload batch queue + Telegram notifications
Changes:
1. Frontend multi-upload:
- File input now has 'multiple' attribute, drag-drop accepts multiple
- File queue list with per-file artist/title preview + remove button
- 'Pošlji vse' uploads sequentially (one at a time to avoid network saturation)
- Each file gets same batch_id for Telegram batch summary
- After upload, queue clears, jobs appear in right sidebar
2. Backend queue worker:
- New _queue_worker() background thread processes 'queued' jobs sequentially
- Only 1 job at a time to keep openclaw stable (avoid CPU/RAM thrash)
- FIFO order by created_at
- Auto-starts on app startup after job resume
3. Job submission flow change:
- /api/process and /api/youtube no longer call background.add_task directly
- Just mark status='queued', queue worker picks up
- This means upload completes fast, processing happens in background
- User can close browser, jobs continue
4. Telegram notifications (FOLX Alerts bot):
- Per-job: 'Reel pripravljen: Lady Gaga - Abracadabra (29s, 30 MB)'
- Per-job failed: 'Reel ni uspel: <name> + error message'
- Batch summary: 'Batch končan: 10/10 reels pripravljeni' (only if >1 in batch)
- Uses existing TELEGRAM_TOKEN + TELEGRAM_CHAT_ID env vars
- app/telegram.py module with notify_job_done(), notify_job_failed(),
notify_batch_complete()
5. batch_id field:
- Added to Job model + StartJobIn pydantic
- Saved during upload + process
- Used to count batch progress and trigger summary notification
User experience:
- Drag 20 videos at once
- Click 'Pošlji'
- Close browser, go grab coffee
- Telegram sends 'Reel pripravljen' for each
- After all done: 'Batch končan: 20/20 reels pripravljeni' summary
- Open app to download all
This commit is contained in:
+42
-14
@@ -1429,31 +1429,59 @@ def main():
|
||||
clip_range["reason"] += f" (start extended back)"
|
||||
|
||||
# Najdi vse segmente ki se začnejo PO trenutnem clip end
|
||||
# STROŽJA pravila: ne podaljšuj v naslednji refren / verz / instrumental.
|
||||
# Razširjamo SAMO če zadnji segment se prekriva s clip (klesti iz njega) ALI
|
||||
# če je naslednji segment KRATEK (< 2s) IN vsebuje samo outro fillerje
|
||||
# (la la, oh, yeah, ej, ja, ah, na, hey itd.).
|
||||
|
||||
# Definiraj outro filler regex (multi-jezikovno)
|
||||
import re as _re
|
||||
OUTRO_FILLER_RE = _re.compile(
|
||||
r'^[\s\-,.!?]*'
|
||||
r'((?:la|na|oh|ah|eh|ej|aj|ja|hey|yeah|yo|ho|wo|hu|mm|nn|uu|oo|aa|ee|ii)'
|
||||
r'[\s\-,.!?]*)+'
|
||||
r'[\s\-,.!?]*$',
|
||||
_re.IGNORECASE
|
||||
)
|
||||
# Hard cap: ne razširjaj več kot 3s nad původne clip end
|
||||
original_clip_end = clip_range["end"]
|
||||
soft_extension_limit = min(original_clip_end + 3.0, extension_limit)
|
||||
|
||||
for seg in corrected_segs:
|
||||
seg_start = float(seg.get("start", 0))
|
||||
seg_end = float(seg.get("end", 0))
|
||||
# Segment začnemo po trenutnem clip end
|
||||
seg_text = seg.get("text", "").strip()
|
||||
|
||||
# Segment se prekriva s clip end (zadnji segment refrena, ki ni zaključen)
|
||||
if seg_start <= current_end:
|
||||
# Segment se prekriva s clip — če konča pred extension_limit, podaljšaj
|
||||
if seg_end > current_end and seg_end <= extension_limit:
|
||||
# Podaljšaj clip do konca tega segmenta + 0.3s diha
|
||||
new_end = min(seg_end + 0.3, extension_limit)
|
||||
if seg_end > current_end and seg_end <= soft_extension_limit:
|
||||
new_end = min(seg_end + 0.3, soft_extension_limit)
|
||||
if new_end > current_end:
|
||||
print(f" 🎵 Podaljšam clip {current_end:.1f}s → {new_end:.1f}s "
|
||||
f"(zadnji segment refrena se zaključi)", file=sys.stderr)
|
||||
current_end = new_end
|
||||
else:
|
||||
# Segment je popolnoma za clip end — preverim ali je v dosegu in ali nima dolge pavze pred njim
|
||||
# Segment začne PO clip end — preveri ali je outro filler
|
||||
pause = seg_start - current_end
|
||||
if pause < 1.0 and seg_end <= extension_limit:
|
||||
# Še vedno povezano s clipom (kratko pavzo, naprej outro/echo)
|
||||
new_end = min(seg_end + 0.3, extension_limit)
|
||||
if new_end > current_end:
|
||||
print(f" 🎵 Podaljšam clip {current_end:.1f}s → {new_end:.1f}s "
|
||||
f"(outro segment z {pause:.1f}s pavzo)", file=sys.stderr)
|
||||
current_end = new_end
|
||||
|
||||
# Predaleč → ustavi se
|
||||
if pause >= 0.7:
|
||||
break
|
||||
# Predolg segment = nov verz/refren, ne dodaj
|
||||
if (seg_end - seg_start) > 2.5:
|
||||
break
|
||||
# Preveri vsebino — če ni samo outro fillerji, NE dodaj
|
||||
if not OUTRO_FILLER_RE.match(seg_text):
|
||||
# Ni filler → verjetno nov refren/verz/post-chorus
|
||||
break
|
||||
|
||||
# OK, je outro filler — dodaj
|
||||
new_end = min(seg_end + 0.2, soft_extension_limit)
|
||||
if new_end > current_end:
|
||||
print(f" 🎵 Podaljšam clip {current_end:.1f}s → {new_end:.1f}s "
|
||||
f"(outro filler '{seg_text[:40]}')", file=sys.stderr)
|
||||
current_end = new_end
|
||||
else:
|
||||
# Daljša pavza — ustavi se tu
|
||||
break
|
||||
|
||||
if current_end > clip_range["end"]:
|
||||
|
||||
Reference in New Issue
Block a user