/** * Retention-structure auditor. * * Long-form videos live or die at the 3-min and 6-min marks. Per the * MrBeast manual: every ~3 minutes a "mini-hook" / re-engagement is * required — a twist, a reveal, a visual spectacle, an escalation. Flat * stretches between mini-hooks bleed retention; the YouTube graph * shows the dip almost every time. * * This module: * 1. Builds a 60s window centred on each requested checkpoint. * 2. Bundles all windows + a compact transcript outline into ONE LLM call. * 3. Parses the response into a structured report with per-checkpoint * scores + an overall escalation pattern score. * * Pure parser + window-builder for unit tests; the network call lives * here too but is exported as `runRetentionAudit` so the wrapper tool * stays thin. */ import type { Transcript } from "./whisper.js"; export interface RetentionWindow { /** Centre of the window. */ atSec: number; /** Inclusive [startSec, endSec]. */ startSec: number; endSec: number; /** Concatenated transcript text falling inside the window. */ text: string; } export interface CheckpointScore { atSec: number; /** 0-1. ≥0.5 = re-engagement detected. <0.5 = flat / weak. */ score: number; /** ≤120 char description of what's happening at this checkpoint. */ summary: string; /** ≤200 char actionable suggestion when score < 0.5. Empty otherwise. */ suggestion: string; } export interface RetentionAuditResult { checkpoints: CheckpointScore[]; /** 0-1. Does the video build progressively (1) or stay flat (0)? */ escalationScore: number; /** ≤200 char overall verdict. */ overallSummary: string; /** atSec of the lowest-scoring checkpoint (-1 when checkpoints is empty). */ weakestCheckpoint: number; } /** * Build a 60s window centred on `atSec`, clamped to [0, totalSec]. * Returns the concatenated transcript text inside the window for LLM * context. Pure — exported for testing. */ export declare function buildWindow(t: Transcript, atSec: number, totalSec: number, windowSec?: number): RetentionWindow; /** * Compact transcript outline — every Nth segment trimmed to ~60 chars * with a leading [t]s tag. Keeps the LLM grounded in overall pacing * without blowing the context budget on a long transcript. */ export declare function buildOutline(t: Transcript, maxLines?: number): string; export interface RetentionAuditOptions { apiKey?: string; model?: string; /** Default [180, 360] (3min, 6min). */ checkpoints?: number[]; /** Override transcript.durationSec (e.g. when you trust ffprobe more). */ durationSec?: number; signal?: AbortSignal; } /** * Run ONE LLM audit pass and return the structured result. Throws on * network / parse error so the wrapper can convert to err(). */ export declare function runRetentionAudit(t: Transcript, opts?: RetentionAuditOptions): Promise; /** * Parse the model's JSON. Robust to missing keys; pads checkpoints to * match the requested order so the caller can correlate by index. * * Pure — exported for testing. */ export declare function parseAuditResponse(content: string, requested: number[]): RetentionAuditResult; //# sourceMappingURL=retention-structure.d.ts.map