""" Build paced hero reel from the browser-ordered clip list. - Shot 1 (family entry): trimmed to 3s — cuts before mud pan - Shots 2-7: full 6s (establish the story) - Shots 8-12: trimmed to 3.5s (building pace) - Shots 13-15: trimmed to 2.5s (rapid) - Shot 16 (final reveal): full 6s (hold on clean result) """ import os, subprocess, shutil BASE_DIR = os.path.dirname(os.path.dirname(__file__)) VID_DIR = os.path.join(BASE_DIR, "assets", "videos", "hero", "clips") REEL_OUT = os.path.join(BASE_DIR, "assets", "videos", "hero", "hero-reel.mp4") TMP_DIR = os.path.join(VID_DIR, "paced-tmp") os.makedirs(TMP_DIR, exist_ok=True) # Clip order: wine spill > extraction > stain > technician, stairs later CLIPS = [ "v3-shot-02", # 1 - wine spill on sofa "shot-05-extraction-couch",# 2 - extraction couch "shot-03-technician", # 3 - technician "v3-shot-03", # 4 - dirty stained carpet close-up "v3-shot-06", # 5 - living room clean carpet pan "v3-shot-07", # 6 - restaurant carpet glide "v3-shot-05", # 7 - office lobby carpet pan "v2-shot-05-clean-stairs", # 8 - clean bright staircase "v2-shot-07-restaurant", # 9 - restaurant carpet "v2-shot-06-office", # 10 - bright office carpet "shot-01-wide-room", # 11 - wide room establishing "shot-05-clean-reveal", # 12 - clean reveal "shot-04-extraction-carpet",# 13 - final reveal ] # Duration for each clip DURATIONS = [ 4.5, # 1 wine spill — cut at 4.5s 5.0, # 2 5.0, # 3 4.0, # 4 --- building pace --- 4.0, # 5 4.0, # 6 3.5, # 7 3.5, # 8 2.5, # 9 --- rapid --- 2.5, # 10 2.5, # 11 2.5, # 12 6.0, # 13 final reveal — hold ] paced_clips = [] for i, (name, dur) in enumerate(zip(CLIPS, DURATIONS)): src = os.path.join(VID_DIR, f"{name}.mp4") out = os.path.join(TMP_DIR, f"{i:02d}-{name}.mp4") if not os.path.exists(src): print(f" MISSING: {src}") continue print(f"[{i+1:02d}] {name} → {dur}s") result = subprocess.run( ["ffmpeg", "-y", "-i", src, "-t", str(dur), "-c:v", "libx264", "-crf", "22", "-preset", "fast", out], capture_output=True, text=True ) if result.returncode != 0: print(f" ffmpeg error: {result.stderr[-200:]}") else: paced_clips.append(out) print(f"\n{len(paced_clips)}/{len(CLIPS)} clips trimmed") concat_file = os.path.join(TMP_DIR, "concat.txt") with open(concat_file, "w") as f: for p in paced_clips: f.write(f"file '{p}'\n") result = subprocess.run( ["ffmpeg", "-y", "-f", "concat", "-safe", "0", "-i", concat_file, "-c:v", "libx264", "-crf", "22", "-preset", "fast", "-movflags", "+faststart", REEL_OUT], capture_output=True, text=True ) if result.returncode == 0: print(f"Reel saved: {REEL_OUT} ({os.path.getsize(REEL_OUT)//1024}KB)") # Clean up tmp shutil.rmtree(TMP_DIR) print("Done.") else: print(f"ffmpeg error: {result.stderr[-400:]}")