#!/usr/bin/env python3 """ clip.py — Vse v enem: vzemi 16:9 video, izreži klip, reframe na 9:16, dodaj podnapise. Primer: # Cel video → 9:16 z face tracking + slovenskimi podnapisi python3 clip.py input.mp4 reel.mp4 --lang sl # 30s klip od 1:20 dalje, blur ozadje, brez podnapisov python3 clip.py input.mp4 reel.mp4 --start 80 --duration 30 --mode blur --no-subs # Več klipov hkrati prek timestamp seznama python3 clip.py input.mp4 out_dir/ --clips "0:30-1:00,2:15-2:45,5:00-5:30" --lang sl """ import argparse import shutil import subprocess import sys import os import tempfile from pathlib import Path def parse_ts(s): """'1:23' → 83.0, '1:23.5' → 83.5, '90' → 90.0""" s = s.strip() if ":" in s: parts = s.split(":") if len(parts) == 2: return int(parts[0]) * 60 + float(parts[1]) if len(parts) == 3: return int(parts[0]) * 3600 + int(parts[1]) * 60 + float(parts[2]) return float(s) def parse_clips(spec): """'0:30-1:00,2:15-2:45' → [(30.0, 60.0), (135.0, 165.0)]""" out = [] for c in spec.split(","): a, b = c.split("-") out.append((parse_ts(a), parse_ts(b))) return out SCRIPT_DIR = Path(__file__).parent def run_clip(src, dst, start, duration, mode, lang, model, style, no_subs, quality, fade_in=0.0, fade_out=0.0, srt_path=None): """Naredi en klip src → dst.""" print(f"🎯 run_clip args: src={src}, dst={dst}, start={start!r}, duration={duration!r}, " f"mode={mode}, fade_in={fade_in}, fade_out={fade_out}, " f"srt={'yes' if srt_path else 'no'}", file=sys.stderr) tmp = tempfile.mkdtemp(prefix="reel_") try: reframed = Path(tmp) / "reframed.mp4" # 1. Reframe (in trim hkrati) cmd = [ "python3", str(SCRIPT_DIR / "reframe.py"), str(src), str(reframed), "--mode", mode, "--quality", quality, ] if start is not None: cmd += ["--start", str(start)] if duration is not None: cmd += ["--duration", str(duration)] if fade_in > 0: cmd += ["--fade-in", str(fade_in)] if fade_out > 0: cmd += ["--fade-out", str(fade_out)] print(f"🔧 REFRAME CMD: {' '.join(cmd)}", file=sys.stderr) print(f"\n▶ Klip: {dst.name}") r = subprocess.run(cmd) if r.returncode != 0: print(f"❌ Reframe napaka pri {dst.name}", file=sys.stderr) return False # 2. Subtitles (opcijsko) if no_subs: shutil.move(str(reframed), str(dst)) else: cmd = [ "python3", str(SCRIPT_DIR / "subtitle.py"), str(reframed), str(dst), "--model", model, "--style", style, ] if lang: cmd += ["--lang", lang] if srt_path: cmd += ["--srt", str(srt_path)] r = subprocess.run(cmd) if r.returncode != 0: print(f"❌ Subtitle napaka — shranim brez", file=sys.stderr) shutil.move(str(reframed), str(dst)) return True finally: shutil.rmtree(tmp, ignore_errors=True) def main(): ap = argparse.ArgumentParser() ap.add_argument("input") ap.add_argument("output", help="Datoteka (en klip) ali mapa (več klipov)") ap.add_argument("--start", type=str, default=None, help="Začetek (s ali mm:ss)") ap.add_argument("--duration", type=float, default=None, help="Trajanje v s") ap.add_argument("--fade-in", type=float, default=0.0, help="Audio fade in (s)") ap.add_argument("--fade-out", type=float, default=0.0, help="Audio fade out (s)") ap.add_argument("--clips", type=str, default=None, help="Več klipov: '0:30-1:00,2:15-2:45'") ap.add_argument("--mode", default="track", choices=["track", "center", "blur"]) ap.add_argument("--lang", default=None, help="sl, de, en, ... (privzeto auto)") ap.add_argument("--model", default="large-v3", choices=["tiny", "base", "small", "medium", "large-v3"]) ap.add_argument("--style", default="reels", choices=["reels", "yellow", "minimal"]) ap.add_argument("--no-subs", action="store_true") ap.add_argument("--quality", default="medium", choices=["fast", "medium", "high"]) ap.add_argument("--srt", default=None, help="Že-pripravljen SRT (preskoči Whisper)") args = ap.parse_args() src = Path(args.input) if not src.exists(): print(f"❌ {src} ne obstaja", file=sys.stderr) sys.exit(1) if args.clips: clips = parse_clips(args.clips) out_dir = Path(args.output) out_dir.mkdir(parents=True, exist_ok=True) ok = 0 for i, (s, e) in enumerate(clips, 1): dst = out_dir / f"reel_{i:02d}.mp4" if run_clip(src, dst, s, e - s, args.mode, args.lang, args.model, args.style, args.no_subs, args.quality): ok += 1 print(f"\n✅ Dokončano: {ok}/{len(clips)} klipov v {out_dir}") else: start = parse_ts(args.start) if args.start else None run_clip(src, Path(args.output), start, args.duration, args.mode, args.lang, args.model, args.style, args.no_subs, args.quality, fade_in=args.fade_in, fade_out=args.fade_out, srt_path=args.srt) if __name__ == "__main__": main()