@ossclip/core 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ossclip/core",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "ossclip's framework-free pipeline: schema, transcription, analysis, cutlist, captions, framing, and the LLM producer",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/assemble.ts CHANGED
@@ -13,25 +13,21 @@ const DROP_BELOW_SEC = 0.8;
13
13
  const SHORT_TAKE_SEC = 45;
14
14
  const SHORT_TAKE_MIN_SCENE_SEC = 3;
15
15
  /**
16
- * A graphic punches in, makes its point, and hands the frame back to the
17
- * speaker — it does not have to span the moment that motivated it. Keeps the
18
- * §4.5 pattern-interrupt rhythm instead of 10s static cards (FINDINGS §3).
19
- * Exported: the beat scheduler budgets coverage with this same number (§7).
16
+ * A graphic holds through the WHOLE moment that motivated it (R23 §114).
17
+ * The old 5s punch-out implemented §4.5's pattern interrupt (§3's fix for
18
+ * 10s static cards), but post-launch footage showed its real effect: scenes
19
+ * started on their context and LEFT while the speaker was still on it — the
20
+ * card gone, the captions still discussing it. The interrupt rhythm now
21
+ * comes from the coverage budget and moment alternation (the beat scheduler
22
+ * prices a graphic at its full span), not from cutting cards off early.
23
+ * This ceiling is the safety net for a rambling moment, not the normal
24
+ * exit; it was the lower-third hold since R20 §95 and is now every
25
+ * layout's. Exported: the beat scheduler budgets coverage with it (§7).
20
26
  */
21
- export const MAX_SCENE_SEC = 5;
22
- /**
23
- * A lower third never TAKES the frame — the speaker stays full-bleed the
24
- * whole time — so the pattern-interrupt argument behind MAX_SCENE_SEC does
25
- * not apply and the punch-out at 5s was cutting cards off mid-sentence
26
- * (R20 §95, seen on the first real landscape run). It holds through its
27
- * whole moment instead, under this generous ceiling so a rambling moment
28
- * still cannot pin one static card up for a minute.
29
- */
30
- export const MAX_OVERLAY_SCENE_SEC = 15;
31
-
32
- /** The on-screen cap for a cue, by how much frame its layout takes. */
33
- const maxSceneSecFor = (layout: SceneCue["layout"]): number =>
34
- layout === "lower-third" ? MAX_OVERLAY_SCENE_SEC : MAX_SCENE_SEC;
27
+ export const MAX_SCENE_SEC = 15;
28
+ /** R20 §95's lower-third ceiling — now the universal one; kept as an alias
29
+ * so published consumers of the old name keep compiling. */
30
+ export const MAX_OVERLAY_SCENE_SEC = MAX_SCENE_SEC;
35
31
  /** Breathing room enforced between consecutive scenes. */
36
32
  const SCENE_GAP_SEC = 0.05;
37
33
 
@@ -102,7 +98,7 @@ export function assembleScenes(
102
98
  if (cue.endSec - cue.startSec < minScene) {
103
99
  cue.endSec = cue.startSec + minScene;
104
100
  }
105
- cue.endSec = Math.min(cue.endSec, cue.startSec + maxSceneSecFor(cue.layout), map.outputDuration);
101
+ cue.endSec = Math.min(cue.endSec, cue.startSec + MAX_SCENE_SEC, map.outputDuration);
106
102
  if (cue.endSec - cue.startSec < DROP_BELOW_SEC) {
107
103
  dropped.push({ id: cue.id, reason: "too short after clamping" });
108
104
  continue;
@@ -72,12 +72,12 @@ export const PRODUCER_SYSTEM = `You are the producer for a short-form vertical v
72
72
 
73
73
  Virality grammar — follow these as hard policies:
74
74
  - The first moment is the hook: the strongest claim or number anywhere in the take, on screen within 2 seconds.
75
- - A pattern interrupt every 3-6 seconds: alternate graphic moments with plain talking-head moments ("none").
75
+ - Pattern interrupts: alternate graphic moments with plain talking-head moments ("none") — never a wall of back-to-back graphics.
76
76
  - On-screen copy is SHORT: numbers over adjectives, verbs over descriptions, never full sentences.
77
77
  - Use contrast/negation beats (StrikethroughReveal, RuleCard with struck alternatives) when the speaker rejects an idea.
78
78
  - End with a payoff or takeaway moment.
79
- - Moments must be contiguous-ish spans of the transcript, 5-10 seconds of speech each, in transcript order, non-overlapping.
80
- - COVERAGE: graphics should be on screen for roughly 40-50% of the runtime. Each graphic holds at most ~5 seconds, then hands the frame back — so MOST moments can carry one. Spread them evenly: never leave a stretch longer than ~10 seconds with no graphic.
79
+ - A moment spans the FULL stretch of speech about its beat — typically 5-15 seconds — in transcript order, non-overlapping. The graphic stays on screen for the ENTIRE moment, so the word range must cover everything the graphic refers to: a stat card leaves when the speaker moves on, not before.
80
+ - COVERAGE: graphics should be on screen for roughly 40-50% of the runtime. A graphic spends its whole moment against that budget, so be selective — give graphics to the moments where one genuinely earns the frame, and spread them evenly: never leave a stretch longer than ~10 seconds with no graphic.
81
81
  - VARIETY: never the same component twice in a row, and prefer a component you have NOT used yet in this video — reuse a treatment only when the beat genuinely calls for it. A repeat reads as a template.
82
82
  - Keep the face LARGE: prefer StatCard/RuleCard/ScreenshotFrame (they sit under a big face) over TitleCard (face becomes a small bubble); use FlowDiagram/TerminalMock sparingly — they remove the face entirely and only earn that when the graphic IS the point.
83
83
  - The transcript is ASR output and may contain mishearings: an unfamiliar proper noun is more likely a mistranscription of a common phrase than a real entity — write on-screen copy with the common-sense reading, never a suspected mishearing.