""" pacing.py --------------------------------------- Retention & Pacing Optimization Engine (V8) Purpose: - Adjust video pacing for maximum retention - Compress slow segments - Emphasize high-value moments - Create TikTok / Reels optimized flow Works in CPU-only environments (FFmpeg-based). """ import subprocess import os # ===================================================== # CONFIG # ===================================================== OUTPUT_FILE = "pacing_optimized.mp4" SLOW_THRESHOLD = 1.25 # speed multiplier for slow segments FAST_THRESHOLD = 1.75 # speed multiplier for filler segments # ===================================================== # BASIC SEGMENT ESTIMATION (NO ML DEPENDENCY) # ===================================================== def estimate_segment_value(text): """ Heuristic scoring system: determines importance of spoken segment. """ text = text.lower() high_value_keywords = [ "you", "secret", "important", "stop", "crazy", "insane", "listen", "this", "money", "success", "life", "truth" ] filler_keywords = [ "um", "uh", "like", "you know", "so", "actually", "basically" ] score = 1.0 # boost high value words for w in high_value_keywords: if w in text: score += 0.6 # penalize filler speech for w in filler_keywords: if w in text: score -= 0.4 return max(0.5, min(score, 2.0)) # ===================================================== # SPEED MAP GENERATOR # ===================================================== def build_speed_map(words): """ Converts transcript into pacing instructions """ segments = [] buffer = [] for w in words: buffer.append(w) # group into micro segments if len(buffer) >= 6: segments.append(buffer) buffer = [] if buffer: segments.append(buffer) speed_map = [] for seg in segments: text = " ".join([w["word"] for w in seg]) score = estimate_segment_value(text) start = seg[0]["start"] end = seg[-1]["end"] # decide speed if score > 1.4: speed = 1.0 # keep normal (important content) elif score > 1.0: speed = 1.15 # slight compression else: speed = FAST_THRESHOLD # aggressive speed-up speed_map.append({ "start": start, "end": end, "speed": speed }) return speed_map # ===================================================== # FFMEG FILTER BUILDER # ===================================================== def build_filter(speed_map): """ Creates FFmpeg atempo + setpts filter chain """ filters = [] for i, seg in enumerate(speed_map): start = seg["start"] end = seg["end"] speed = seg["speed"] # video speed filters.append( f"[0:v]trim=start={start}:end={end},setpts=PTS/{speed}[v{i}]" ) # audio speed filters.append( f"[0:a]atrim=start={start}:end={end},asetpts=PTS-STARTPTS," f"atempo={speed}[a{i}]" ) v_streams = "".join([f"[v{i}]" for i in range(len(speed_map))]) a_streams = "".join([f"[a{i}]" for i in range(len(speed_map))]) filters.append( f"{v_streams}{a_streams}concat=n={len(speed_map)}:v=1:a=1[outv][outa]" ) return ";".join(filters) # ===================================================== # MAIN ENGINE # ===================================================== def optimize_pacing(video_path, words=None): """ Main entry point for V8 pacing system """ print("[PACING] Starting optimization...") if not words: print("[PACING] No transcript provided — returning original video") return video_path # Step 1: build speed map speed_map = build_speed_map(words) print(f"[PACING] Segments: {len(speed_map)}") # Step 2: build ffmpeg filter filter_complex = build_filter(speed_map) output_path = OUTPUT_FILE # Step 3: render optimized video cmd = [ "ffmpeg", "-y", "-i", video_path, "-filter_complex", filter_complex, "-map", "[outv]", "-map", "[outa]", "-c:v", "libx264", "-preset", "ultrafast", "-c:a", "aac", output_path ] subprocess.run(cmd, check=True) print("[PACING] Done:", output_path) return output_path # ===================================================== # LIGHTWEIGHT MODE (FAST FALLBACK) # ===================================================== def fast_pacing(video_path): """ Simple fallback: global speed-up only """ output = "fast_pacing.mp4" cmd = [ "ffmpeg", "-y", "-i", video_path, "-filter_complex", "[0:v]setpts=0.92*PTS[v];[0:a]atempo=1.08[a]", "-map", "[v]", "-map", "[a]", "-c:v", "libx264", "-preset", "ultrafast", "-c:a", "aac", output ] subprocess.run(cmd, check=True) return output # ===================================================== # PUBLIC API # ===================================================== def pacing_engine(video_path, words=None, mode="smart"): """ Entry point used by main.py """ if mode == "fast": return fast_pacing(video_path) return optimize_pacing(video_path, words)