vibemovie 0.2.0 → 0.2.1
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/dist/{chunk-HI6AAJID.js → chunk-IYP3PLDV.js} +1 -1
- package/dist/{chunk-DO2IWHL6.js → chunk-LOSCKRIB.js} +575 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +79 -1
- package/dist/index.js +13 -3
- package/dist/mcp.js +2 -2
- package/package.json +1 -1
|
@@ -1008,6 +1008,576 @@ async function renderCinematic(scenes, opts) {
|
|
|
1008
1008
|
return { path: opts.out, beats };
|
|
1009
1009
|
}
|
|
1010
1010
|
|
|
1011
|
+
// src/recipes/shots.ts
|
|
1012
|
+
var SHOT_ROLES = [
|
|
1013
|
+
"hook",
|
|
1014
|
+
"establish",
|
|
1015
|
+
"reveal",
|
|
1016
|
+
"feature",
|
|
1017
|
+
"transition",
|
|
1018
|
+
"hero",
|
|
1019
|
+
"text-card",
|
|
1020
|
+
"close",
|
|
1021
|
+
"action",
|
|
1022
|
+
"emotion"
|
|
1023
|
+
];
|
|
1024
|
+
var ENERGY_LEVELS = ["low", "med", "high"];
|
|
1025
|
+
var shotRecipes = [
|
|
1026
|
+
// ── hook ──────────────────────────────────────────────────────────────
|
|
1027
|
+
{
|
|
1028
|
+
id: "brand-ink-open",
|
|
1029
|
+
role: "hook",
|
|
1030
|
+
name: "Brand Ink Open",
|
|
1031
|
+
purpose: "Stamp the brand wordmark into paper grain before any product shot \u2014 the audience memorizes the name in one quiet held beat.",
|
|
1032
|
+
energy: "low",
|
|
1033
|
+
suggestedSeconds: 3,
|
|
1034
|
+
promptHints: "Wordmark slowly imprints into textured paper grain with a soft letterpress emboss, settles, then holds dead-still for a full breath before anything moves.",
|
|
1035
|
+
pitfall: "The held beat belongs to the wordmark settle frame, not a content card; keep opening energy low so it does not crush the later build."
|
|
1036
|
+
},
|
|
1037
|
+
{
|
|
1038
|
+
id: "magician-card-flourish",
|
|
1039
|
+
role: "hook",
|
|
1040
|
+
name: "Magician Card Flourish",
|
|
1041
|
+
purpose: 'A single hero card is conjured from a flash of light \u2014 the ritual of "making it appear" is the hook.',
|
|
1042
|
+
energy: "high",
|
|
1043
|
+
suggestedSeconds: 4,
|
|
1044
|
+
promptHints: "A short blue star-flash, then the card launches from a tiny point at frame center, spins along a curving arc toward camera, and hard-locks dead-still front-facing at near-full-frame.",
|
|
1045
|
+
pitfall: "The flash must read as light (0.3s), the spin must land exactly front-facing with no settling tail, and the card freezes on arrival \u2014 cheap color-block light effects were repeatedly rejected."
|
|
1046
|
+
},
|
|
1047
|
+
{
|
|
1048
|
+
id: "dataviz-landscape-open",
|
|
1049
|
+
role: "hook",
|
|
1050
|
+
name: "Dataviz Landscape Open",
|
|
1051
|
+
purpose: "A brand-level abstract open: the data world behind the product shot as a dark landscape of glowing streams converging into one trunk.",
|
|
1052
|
+
energy: "low",
|
|
1053
|
+
suggestedSeconds: 6,
|
|
1054
|
+
promptHints: "Slow steady low-altitude camera flight over a dark field; many thin glowing streams flow in from the deep background and merge into a single bright trunk, scattered with small readable ID labels across three depth layers.",
|
|
1055
|
+
pitfall: 'Use at most once per film, and do not pair with glow-flyline in an adjacent segment \u2014 two "dark glowing lines" reads as the same trick.'
|
|
1056
|
+
},
|
|
1057
|
+
{
|
|
1058
|
+
id: "trailer-grammar-moves",
|
|
1059
|
+
role: "hook",
|
|
1060
|
+
name: "Trailer Grammar",
|
|
1061
|
+
purpose: "The structural moments of a trailer \u2014 the open front-loads the three punchiest shots in 0.9s, then a black beat, then the real start.",
|
|
1062
|
+
energy: "high",
|
|
1063
|
+
suggestedSeconds: 5,
|
|
1064
|
+
promptHints: "Three fastest, most striking shots cut back-to-back in under a second, then hard-cut to pure black and hold one silent beat before the title opens.",
|
|
1065
|
+
pitfall: "The black beat must be pure black and empty \u2014 it is a breath; anything in it breaks the trailer hook."
|
|
1066
|
+
},
|
|
1067
|
+
{
|
|
1068
|
+
id: "input-trigger-moves",
|
|
1069
|
+
role: "hook",
|
|
1070
|
+
name: "Input Trigger",
|
|
1071
|
+
purpose: "First-person grammar \u2014 the viewer is using the product, not watching it. The cursor is the hand; the trigger fires the narrative.",
|
|
1072
|
+
energy: "med",
|
|
1073
|
+
suggestedSeconds: 5,
|
|
1074
|
+
promptHints: "An enlarged cursor with personality slides in and clicks a target; the camera pushes toward the click point then gently eases back \u2014 slow, anchored on the cursor, it comes back.",
|
|
1075
|
+
pitfall: "Cap at two input-triggers per film \u2014 each should be a section-level switch; three rapid keypresses reads as a bug."
|
|
1076
|
+
},
|
|
1077
|
+
// ── establish ─────────────────────────────────────────────────────────
|
|
1078
|
+
{
|
|
1079
|
+
id: "crane-rise-reveal",
|
|
1080
|
+
role: "establish",
|
|
1081
|
+
name: "Crane Rise Reveal",
|
|
1082
|
+
purpose: "Establish from detail to whole: start glued to one real data row, then a crane arm rises and pulls back so rows flow in until the full dashboard fills frame.",
|
|
1083
|
+
energy: "high",
|
|
1084
|
+
suggestedSeconds: 5,
|
|
1085
|
+
promptHints: "Camera locked on a tight close-up of a single data row, then rises vertically along Y and pulls back on a decelerating ease, rows streaming in from below as the full dashboard fills the frame and settles to a true still.",
|
|
1086
|
+
pitfall: "The starting detail is stared at 3.2x zoom \u2014 rasterize it hires first or text blurs; pick rise XOR dive per film (do not pair with a drone-dive)."
|
|
1087
|
+
},
|
|
1088
|
+
{
|
|
1089
|
+
id: "overhead-camera-moves",
|
|
1090
|
+
role: "establish",
|
|
1091
|
+
name: "Overhead Camera",
|
|
1092
|
+
purpose: 'The tilt angle itself tells the story: the page lies flat, the camera "looks up" to right it, content rows flowing into view like unrolling a blueprint.',
|
|
1093
|
+
energy: "med",
|
|
1094
|
+
suggestedSeconds: 5,
|
|
1095
|
+
promptHints: "Page lies flat at a steep tilt showing only a thin perspective band of its top edge; the camera tilts up toward level, rows of content flowing into view one by one until the full page reads flat.",
|
|
1096
|
+
pitfall: 'Pick this OR crane-rise-reveal for an establishing open \u2014 two "reveal opens" in one film reads as the same trick.'
|
|
1097
|
+
},
|
|
1098
|
+
{
|
|
1099
|
+
id: "icon-field-colorize",
|
|
1100
|
+
role: "establish",
|
|
1101
|
+
name: "Icon Field Colorize",
|
|
1102
|
+
purpose: 'Lay out the full capability surface as a field of grey icons, then wash it with brand-color waves \u2014 "look how much this does", lit up at once.',
|
|
1103
|
+
energy: "med",
|
|
1104
|
+
suggestedSeconds: 4,
|
|
1105
|
+
promptHints: "Over a hundred small grey icons stagger into frame and fill it as background texture, hold one beat, then brand color sweeps across as fast descending horizontal waves (blue first, then orange/green/red in lower bands).",
|
|
1106
|
+
pitfall: "The color pass must NOT be a same-frame hard flip \u2014 it is multiple color waves sweeping down over about half a second; a hard flip reads as a swapped image."
|
|
1107
|
+
},
|
|
1108
|
+
{
|
|
1109
|
+
id: "morph-from-primitive",
|
|
1110
|
+
role: "establish",
|
|
1111
|
+
name: "Morph From Primitive",
|
|
1112
|
+
purpose: "The subject grows in place rather than flying in \u2014 a stroked circle takes a breath, then its outline continuously morphs into a rounded card as content fades in.",
|
|
1113
|
+
energy: "med",
|
|
1114
|
+
suggestedSeconds: 5,
|
|
1115
|
+
promptHints: "A simple stroked circle at center breathes (scale 1 to 1.12 to 1) in anticipation, then its outline smoothly morphs into a rounded-rect card while the content fades in.",
|
|
1116
|
+
pitfall: "The breath is the anticipation beat \u2014 without it the morph reads as a pop; it is the reverse direction from UI-to-primitive."
|
|
1117
|
+
},
|
|
1118
|
+
{
|
|
1119
|
+
id: "skeleton-reveal",
|
|
1120
|
+
role: "establish",
|
|
1121
|
+
name: "Skeleton Reveal",
|
|
1122
|
+
purpose: 'Stage the product UI arrival as three fidelity jumps: hand sketch to grey skeleton bars to real content \u2014 the "becoming real" arc.',
|
|
1123
|
+
energy: "med",
|
|
1124
|
+
suggestedSeconds: 6,
|
|
1125
|
+
promptHints: "UI arrives in three jumps: a quick hand-drawn sketch, a fast swap to grey skeleton bars rolling in, then a slow push as the skeleton resolves into the real filled product UI.",
|
|
1126
|
+
pitfall: 'Each "becomes real" swap is a beat \u2014 the two fidelity transitions are the whole point; rushing them kills the arc.'
|
|
1127
|
+
},
|
|
1128
|
+
// ── reveal ────────────────────────────────────────────────────────────
|
|
1129
|
+
{
|
|
1130
|
+
id: "neon-frame-orbit-drop",
|
|
1131
|
+
role: "reveal",
|
|
1132
|
+
name: "Neon Frame Orbit Drop",
|
|
1133
|
+
purpose: "A grand one-off reveal: a neon frame traces itself then orbits from the left side to the right while all components drop in from above simultaneously and snap into place.",
|
|
1134
|
+
energy: "high",
|
|
1135
|
+
suggestedSeconds: 4,
|
|
1136
|
+
promptHints: "A neon outline frame traces itself, then the camera arcs continuously from the page left side to its right while every component and text drops from above at once, each snapping dead with its shadow vanishing on contact \u2014 a single simultaneous whole-page arrival.",
|
|
1137
|
+
pitfall: '"Simultaneous" is the grammar \u2014 all components start, land, and shed shadows on the same frames; stagger it and it stops being a unified reveal (that is the runway-rain variant instead).'
|
|
1138
|
+
},
|
|
1139
|
+
{
|
|
1140
|
+
id: "spotlight-sweep-moves",
|
|
1141
|
+
role: "reveal",
|
|
1142
|
+
name: "Spotlight Sweep",
|
|
1143
|
+
purpose: "In the dark the audience only sees what the light shows \u2014 light is illumination and editing: where it sweeps, panels appear; when it leaves, they exit.",
|
|
1144
|
+
energy: "med",
|
|
1145
|
+
suggestedSeconds: 4,
|
|
1146
|
+
promptHints: "Near-black scene; a purple-edged spotlight glow creeps along UI panel edges and logos (lit, slightly blurred \u2014 light stroking the interface, not a stroke animation). Move and expand strictly at constant linear speed; a panel lights up where the light touches and dims as it passes.",
|
|
1147
|
+
pitfall: "Constant linear speed is the\u547D\u95E8 \u2014 easing makes the light feel intentional; only linear reads as a mechanical searchlight sweep."
|
|
1148
|
+
},
|
|
1149
|
+
{
|
|
1150
|
+
id: "stroke-segment-build",
|
|
1151
|
+
role: "reveal",
|
|
1152
|
+
name: "Stroke Segment Build",
|
|
1153
|
+
purpose: 'An Alien-titles reveal: the title "develops" \u2014 discrete stroke segments light up out of order, unreadable for most of the time, then the last segments land and the word suddenly reads. Recognition is the hook.',
|
|
1154
|
+
energy: "med",
|
|
1155
|
+
suggestedSeconds: 5,
|
|
1156
|
+
promptHints: "Title broken into discrete stroke segments; segments light up out of order over the first part (mysterious fragments), then the final key segments land and the full word suddenly reads \u2014 recognition is the beat.",
|
|
1157
|
+
pitfall: "The hook strength depends on how long the unreadable period holds and how late the key segment lands \u2014 do not blow the reveal early."
|
|
1158
|
+
},
|
|
1159
|
+
// ── feature ───────────────────────────────────────────────────────────
|
|
1160
|
+
{
|
|
1161
|
+
id: "deck-deal-flyin",
|
|
1162
|
+
role: "feature",
|
|
1163
|
+
name: "Deck Deal Fly-In",
|
|
1164
|
+
purpose: 'Show "there is a LOT here, pouring in" \u2014 cards deal themselves flying into their grid slots with urgency; build information density as the first impression.',
|
|
1165
|
+
energy: "high",
|
|
1166
|
+
suggestedSeconds: 4,
|
|
1167
|
+
promptHints: "A stack teases (what is this pile?), then dozens of cards deal out and fly into the page, each slamming into its slot with urgency \u2014 the audience feels things pouring in.",
|
|
1168
|
+
pitfall: 'Abstract "flood" multi-round non-convergence was rejected; find a physical metaphor (dealing) before writing motion \u2014 group motion needs a metaphor before code.'
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
id: "row-embed",
|
|
1172
|
+
role: "feature",
|
|
1173
|
+
name: "Row Embed",
|
|
1174
|
+
purpose: 'Detail-page rows do not "appear", they "grow in" \u2014 each row drops from above and slots precisely into the layout; the accent seam at embed is the click of it snapping shut.',
|
|
1175
|
+
energy: "med",
|
|
1176
|
+
suggestedSeconds: 2,
|
|
1177
|
+
promptHints: "Structured rows drop from above one by one and slot precisely into the page layout; on each embed a thin accent-colored seam flashes at the join \u2014 the visual foley of it snapping shut.",
|
|
1178
|
+
pitfall: "Fly-in targets MUST be real layout slots that embed on landing \u2014 floating above the grid without landing reads as fake."
|
|
1179
|
+
},
|
|
1180
|
+
{
|
|
1181
|
+
id: "document-typewriter-reveal",
|
|
1182
|
+
role: "feature",
|
|
1183
|
+
name: "Document Typewriter Reveal",
|
|
1184
|
+
purpose: 'The whole real-typeset document writes itself out behind a caret, sidebar entries drop into the rail \u2014 the densest info beat; the whole persuasion is "this document is real".',
|
|
1185
|
+
energy: "med",
|
|
1186
|
+
suggestedSeconds: 4,
|
|
1187
|
+
promptHints: "A full page of real typeset document writes itself out left-to-right behind a single accent caret riding the reveal edge; sidebar history entries drop into the rail in sequence; camera holds on the page with both columns in frame.",
|
|
1188
|
+
pitfall: "Mock content must be publish-grade (native layout, full text, complete sidebar) \u2014 a slapdash screenshot-plus-slogan document forces a full reshoot; never put real customer or member names in mock data."
|
|
1189
|
+
},
|
|
1190
|
+
{
|
|
1191
|
+
id: "type-and-filter",
|
|
1192
|
+
role: "feature",
|
|
1193
|
+
name: "Type And Filter",
|
|
1194
|
+
purpose: 'Let the viewer "do it once" \u2014 see what is typed, how the page responds, where they clicked. The one lens that simulates real human operation, so it must move like a hand, not a script.',
|
|
1195
|
+
energy: "med",
|
|
1196
|
+
suggestedSeconds: 3,
|
|
1197
|
+
promptHints: "Simulated real-speed human operation: type a few characters, the list filters and re-settles, the cursor clicks into a target card that lands in its real grid slot.",
|
|
1198
|
+
pitfall: "First drafts are always too fast \u2014 type at about three frames per character; a filtered target card that floats above the grid instead of landing in a real slot reads as fake."
|
|
1199
|
+
},
|
|
1200
|
+
{
|
|
1201
|
+
id: "before-after-slider-scrub",
|
|
1202
|
+
role: "feature",
|
|
1203
|
+
name: "Before/After Slider Scrub",
|
|
1204
|
+
purpose: "The standard AI-product comparison: same frame, before (flat) overlaid with after (crisp); the divider whips to 70 percent with overshoot, holds, then crawls back to prove where the change is. Fast-sweep then slow-scan is the rhythm.",
|
|
1205
|
+
energy: "med",
|
|
1206
|
+
suggestedSeconds: 5,
|
|
1207
|
+
promptHints: "Two overlaid versions of the same frame (before: flat low-contrast; after: crisp) split by a vertical divider with a round handle; the handle whips hard from the left edge to about 70 percent with overshoot, holds one beat, then crawls back at a fifth of the speed so the difference is readable.",
|
|
1208
|
+
pitfall: "Both versions must share identical layout and camera \u2014 different layouts read as two pages and the comparison fails; use real screenshots for both."
|
|
1209
|
+
},
|
|
1210
|
+
{
|
|
1211
|
+
id: "integration-hub-map",
|
|
1212
|
+
role: "feature",
|
|
1213
|
+
name: "Integration Hub Map",
|
|
1214
|
+
purpose: '"One product connects everything" \u2014 the page flips over to become a hub, icons appear, then light tubes connect to them in two beats and breathe the flow.',
|
|
1215
|
+
energy: "high",
|
|
1216
|
+
suggestedSeconds: 5,
|
|
1217
|
+
promptHints: "Old page flips a full 180 degrees to become a new hub page (one fast continuous flip with a brief edge flash at the 90-degree profile, no stop); icons appear all at once, then glowing light tubes connect out to them across two beats and pulse softly to keep flowing.",
|
|
1218
|
+
pitfall: 'The flip must be complete and continuous with no 90-degree-profile pause \u2014 a stop there was rejected; "constant speed" here means no pauses, not literal linear.'
|
|
1219
|
+
},
|
|
1220
|
+
{
|
|
1221
|
+
id: "command-palette-summon",
|
|
1222
|
+
role: "feature",
|
|
1223
|
+
name: "Command Palette Summon",
|
|
1224
|
+
purpose: "The signature ritual: a soft chime, the whole UI dims aside, the command palette drops from upper-center, candidates stagger in; type two letters and the list narrows live.",
|
|
1225
|
+
energy: "med",
|
|
1226
|
+
suggestedSeconds: 5,
|
|
1227
|
+
promptHints: "A soft chime, the whole UI world dims to make way, a command palette drops from upper-center, candidate rows stagger in; two characters typed at human speed and the list narrows live \u2014 the squeeze comes from row-height collapse, not fade.",
|
|
1228
|
+
pitfall: "Type at real human speed (at least 12 frames between the two keys); the narrowing squeeze must come from row-height collapse, not opacity fade."
|
|
1229
|
+
},
|
|
1230
|
+
{
|
|
1231
|
+
id: "list-stack-press",
|
|
1232
|
+
role: "feature",
|
|
1233
|
+
name: "List Stack Press",
|
|
1234
|
+
purpose: '"Stacking has weight" \u2014 each new card lands and presses the whole pile down before it springs back; the counter ticks in lockstep to nail the quantity.',
|
|
1235
|
+
energy: "med",
|
|
1236
|
+
suggestedSeconds: 3,
|
|
1237
|
+
promptHints: "Feed or inbox cards stack one by one; each new card lands and presses the whole settled pile down, which springs back up; a counter ticks up in lockstep with each landing.",
|
|
1238
|
+
pitfall: "Stack and list info lenses must be shot head-on \u2014 even in a fully stylized film this lens was rolled back to front-view individually; validate camera per lens, do not apply globally."
|
|
1239
|
+
},
|
|
1240
|
+
// ── transition ────────────────────────────────────────────────────────
|
|
1241
|
+
{
|
|
1242
|
+
id: "wipe-transitions",
|
|
1243
|
+
role: "transition",
|
|
1244
|
+
name: "Wipe Transitions",
|
|
1245
|
+
purpose: 'The geometric-wipe family \u2014 both pages stay still while one geometric boundary sweeps across to hand off. Clock-wipe = "dashboard refreshed a screen of data"; blinds-slice = "flip the page".',
|
|
1246
|
+
energy: "med",
|
|
1247
|
+
suggestedSeconds: 5,
|
|
1248
|
+
promptHints: "Old and new pages both still; a geometric boundary sweeps across to reveal the new \u2014 either a clock-hand radar sweep from center (data-refresh feel) or vertical blinds flipping in a staggered wave (page-turn feel). The wipe edge carries bright highlight lines so it does not read as a slideshow transition.",
|
|
1249
|
+
pitfall: "The wipe boundary MUST carry highlight or glow lines \u2014 a line-less wipe reads as a PowerPoint transition; light lines need a dark edge-stroke on light areas and a bright white core on dark."
|
|
1250
|
+
},
|
|
1251
|
+
{
|
|
1252
|
+
id: "card-flip-reveal",
|
|
1253
|
+
role: "transition",
|
|
1254
|
+
name: "Card Flip Reveal",
|
|
1255
|
+
purpose: 'A semantic flip \u2014 a card front (feature UI) and back (the number it produced) are a cause-and-effect pair; the flip answers "so what?". Three staggered cards read as "results roll in".',
|
|
1256
|
+
energy: "high",
|
|
1257
|
+
suggestedSeconds: 5,
|
|
1258
|
+
promptHints: 'A row of cards each flips over; the front is the feature UI, the back is the result number it produced \u2014 the flip answers "so what?". Three cards flip in a stagger, reading as consecutive results.',
|
|
1259
|
+
pitfall: "Same technique root as a grid wave-flip but different semantics \u2014 that is batch entrance, this is cause-to-result; do not conflate."
|
|
1260
|
+
},
|
|
1261
|
+
{
|
|
1262
|
+
id: "bubble-swarm-takeover",
|
|
1263
|
+
role: "transition",
|
|
1264
|
+
name: "Bubble Swarm Takeover",
|
|
1265
|
+
purpose: '"Curtain" thinking \u2014 a swarm of brand objects drifts into foreground, swells to fill the frame hiding a hard cut, then drifts apart to reveal the new scene. Longer transitions mean more brand exposure, not slow.',
|
|
1266
|
+
energy: "high",
|
|
1267
|
+
suggestedSeconds: 4,
|
|
1268
|
+
promptHints: "A swarm of brand objects (bubbles, petals, icons) drifts in and swells to completely fill or occlude the frame (hard cut hidden at peak occlusion), then drifts apart to reveal a new scene.",
|
|
1269
|
+
pitfall: 'The peak MUST truly occlude the full frame or the cut shows; the hidden-cut variant is the one-to-three-frame "invisible scissors" \u2014 pick by how long you want the brand on screen.'
|
|
1270
|
+
},
|
|
1271
|
+
{
|
|
1272
|
+
id: "line-carry-transition",
|
|
1273
|
+
role: "transition",
|
|
1274
|
+
name: "Line Carry Transition",
|
|
1275
|
+
purpose: "The scene never changes \u2014 a single line carries you across. A progress bar fills, its tip extends off the card edge; the camera follows it panning into the new world, the line dog-legs to frame the next card.",
|
|
1276
|
+
energy: "med",
|
|
1277
|
+
suggestedSeconds: 5,
|
|
1278
|
+
promptHints: "A progress bar fills and its tip extends into a long line off the card edge; the camera follows the line panning sideways into a new scene, the line dog-legs to draw the next card frame, the frame closes and content fades in \u2014 the eye never leaves the line.",
|
|
1279
|
+
pitfall: "Graphic continuity IS the transition \u2014 do not cross-fade; the line belongs to the whole cut, not to one element."
|
|
1280
|
+
},
|
|
1281
|
+
{
|
|
1282
|
+
id: "color-block-step-wipe",
|
|
1283
|
+
role: "transition",
|
|
1284
|
+
name: "Color-Block Step Wipe",
|
|
1285
|
+
purpose: "Zero interpolation, zero easing \u2014 color blocks grow like retro pixel-game tiles, every step a hard cut, stillness between steps. The stutter itself is the rhythm.",
|
|
1286
|
+
energy: "high",
|
|
1287
|
+
suggestedSeconds: 3,
|
|
1288
|
+
promptHints: "Brand color blocks grow in hard discrete steps with no easing and no interpolation \u2014 each step is a hard cut, fully still between steps (retro pixel-game tile growth). Three to five steps total; a content card can ride each step.",
|
|
1289
|
+
pitfall: "Distinct from the smooth clock and blinds wipes \u2014 this is the stuttered no-tween pixel feel; do not smooth it out."
|
|
1290
|
+
},
|
|
1291
|
+
{
|
|
1292
|
+
id: "brand-frame-snap",
|
|
1293
|
+
role: "transition",
|
|
1294
|
+
name: "Brand Frame Snap",
|
|
1295
|
+
purpose: "Wrap real screen recordings in a thick brand-color picture frame \u2014 the frame appears first, then its color becomes the chapter code. On a chapter switch the whole frame hard-flips color in one frame.",
|
|
1296
|
+
energy: "med",
|
|
1297
|
+
suggestedSeconds: 4,
|
|
1298
|
+
promptHints: "A thick brand-color picture frame draws around a screen recording (frame first, content second \u2014 ritual); on a chapter switch the entire frame hard-flips to a new brand color in a single frame (no gradient), the window content and corner badges swapping in the same frame.",
|
|
1299
|
+
pitfall: "The flip MUST be same-frame across frame, window content, and badge text \u2014 even two frames apart and the gear-shift scatters into three small animations; keep the color code consistent film-wide."
|
|
1300
|
+
},
|
|
1301
|
+
// ── hero ──────────────────────────────────────────────────────────────
|
|
1302
|
+
{
|
|
1303
|
+
id: "spotlight-hero-card",
|
|
1304
|
+
role: "hero",
|
|
1305
|
+
name: "Spotlight Hero Card",
|
|
1306
|
+
purpose: "The single-protagonist open: a wandering spotlight locks onto one card, the camera pushes in on an angle, the card rises, hovers, is scanned by a contour beam, then reseats.",
|
|
1307
|
+
energy: "med",
|
|
1308
|
+
suggestedSeconds: 5,
|
|
1309
|
+
promptHints: "A roaming spotlight narrows and locks onto one card in a grid; camera pushes from a flat full-page to a tilted close-up (left-side angle), the card rises with overshoot, hovers with a gentle bob, a glowing rounded-rect contour beam traces it twice (fast-bright then slow-dim), then it reseats.",
|
|
1310
|
+
pitfall: "Open with a SINGLE card and one complete action arc \u2014 a multi-card dance cannot carry a first impression; slow the rise-to-reseat toward three seconds, first drafts are always too fast."
|
|
1311
|
+
},
|
|
1312
|
+
{
|
|
1313
|
+
id: "crash-zoom-punch",
|
|
1314
|
+
role: "hero",
|
|
1315
|
+
name: "Crash Zoom Punch",
|
|
1316
|
+
purpose: 'One beat slams from a wide to a target close-up \u2014 "look at THIS". Land with an overshoot bounce (spring) or a hard impact shake (weight), by emphasis.',
|
|
1317
|
+
energy: "high",
|
|
1318
|
+
suggestedSeconds: 3,
|
|
1319
|
+
promptHints: "In about six frames, crash-zoom from a wide framing to an extreme close-up on the target card filling 60 to 75 percent of frame; either overshoot and rebound 3 to 6 percent (spring) or land hard with a high-frequency impact shake that decays in six frames.",
|
|
1320
|
+
pitfall: "Do not mix the two landings (rebound plus shake reads as a glitch); cap at two crash-zooms per film, and the landing target must be high-res or text blurs."
|
|
1321
|
+
},
|
|
1322
|
+
{
|
|
1323
|
+
id: "runway-ground-skim",
|
|
1324
|
+
role: "hero",
|
|
1325
|
+
name: "Runway Ground Skim",
|
|
1326
|
+
purpose: "Treat the UI as a runway: low-angle, cards hang at staggered heights then rain down in an overlapping fast volley, landing dead with zero bounce, then the whole page stands up to vertical.",
|
|
1327
|
+
energy: "high",
|
|
1328
|
+
suggestedSeconds: 4,
|
|
1329
|
+
promptHints: "Strong low-angle perspective, page lying flat like a runway; UI cards suspended at staggered heights then drop in an overlapping rain (small stagger, gravity acceleration), each landing dead-still with no bounce; once all are down the whole page rotates up to vertical and the camera pulls to center.",
|
|
1330
|
+
pitfall: "The drop feel is crisp: zero bounce (the squish was rejected), a short drop frame count (longer was rejected as slow), and overlapping parallelism (waiting for one to land before starting the next was rejected)."
|
|
1331
|
+
},
|
|
1332
|
+
{
|
|
1333
|
+
id: "segmented-thumb-hero",
|
|
1334
|
+
role: "hero",
|
|
1335
|
+
name: "Segmented Thumb Hero",
|
|
1336
|
+
purpose: 'A mode switch told entirely by the segmented control thumb sliding eight frames \u2014 "we moved from A to B" with no page context; the control is the stage.',
|
|
1337
|
+
energy: "med",
|
|
1338
|
+
suggestedSeconds: 4,
|
|
1339
|
+
promptHints: "Extreme close-up of a segmented control; cursor slides in, presses with a ripple, the thumb slider glides eight frames to the other segment, and a new icon pops in \u2014 four beats: arrival, decision, response, reward.",
|
|
1340
|
+
pitfall: "All four beats are required \u2014 drop the cursor and the UI looks self-animated; drop the icon pop and the switch feels unrewarded."
|
|
1341
|
+
},
|
|
1342
|
+
{
|
|
1343
|
+
id: "space-camera-moves",
|
|
1344
|
+
role: "hero",
|
|
1345
|
+
name: "Space Camera",
|
|
1346
|
+
purpose: "Treat the flat page as a real 3D object the camera flies around \u2014 exploded-view (parts blow out along Z then reassemble) or drone-dive (god-view plunges to a hero close-up).",
|
|
1347
|
+
energy: "high",
|
|
1348
|
+
suggestedSeconds: 5,
|
|
1349
|
+
promptHints: "Either the whole page tilts in 3D and its components blow out along the Z-axis, hover, then reassemble in reverse with an impact shake; or a near-vertical overhead hover, then a hard dive that air-cushions to a stop on a hero-card close-up, motion-blurred through the dive.",
|
|
1350
|
+
pitfall: "Both variants need real layered or high-res screenshots \u2014 one flat page cannot explode, and the dive lands on a close-up that blurs without hires rasterization; cap at two of these big moves per film."
|
|
1351
|
+
},
|
|
1352
|
+
// ── text-card ─────────────────────────────────────────────────────────
|
|
1353
|
+
{
|
|
1354
|
+
id: "paper-title-card",
|
|
1355
|
+
role: "text-card",
|
|
1356
|
+
name: "Paper Title Card",
|
|
1357
|
+
purpose: 'Give the audience one sentence of breath between two product beats \u2014 say "what is next and why it matters". Letterpress emboss keeps the card in the same world as the paper-and-ink visuals.',
|
|
1358
|
+
energy: "low",
|
|
1359
|
+
suggestedSeconds: 2,
|
|
1360
|
+
promptHints: "A single short phrase embossed into textured paper with a letterpress press, holds for one breath between two scenes \u2014 concrete copy naming the feature and its payoff, never abstract metaphor.",
|
|
1361
|
+
pitfall: "Copy must be concrete (feature name plus specific payoff) \u2014 abstract metaphor words get rewritten; place a guiding card before an important feature, it is a chapter signpost not decoration."
|
|
1362
|
+
},
|
|
1363
|
+
{
|
|
1364
|
+
id: "cel-flash-stomp",
|
|
1365
|
+
role: "text-card",
|
|
1366
|
+
name: "Cel Flash Stomp",
|
|
1367
|
+
purpose: "Stomp-typography alone is just weight; background color-flash alone is just flash. Welded: the word slam-frame is the flash ignition \u2014 subject still, world quaking in peripheral vision. The opposite of screenshake.",
|
|
1368
|
+
energy: "high",
|
|
1369
|
+
suggestedSeconds: 5,
|
|
1370
|
+
promptHints: "Each word slams down dead-still onto frame; on each slam-frame the solid background color hard-flashes to a new hue and back. Subject rock-still, only the world flashes \u2014 peripheral-vision impact. Three words, three beats.",
|
|
1371
|
+
pitfall: "Sound-dependent \u2014 each word-slam needs a kick and the flash must align to the beat; without the kick it is just a janky strobe."
|
|
1372
|
+
},
|
|
1373
|
+
{
|
|
1374
|
+
id: "gradient-word-sweep",
|
|
1375
|
+
role: "text-card",
|
|
1376
|
+
name: "Gradient Word Sweep",
|
|
1377
|
+
purpose: '"Energize" one keyword in an otherwise-neutral line \u2014 a gradient color sweep zips across the chars like an injection; the wavefront is brightest, then it settles to a steady glow with linking sparks.',
|
|
1378
|
+
energy: "high",
|
|
1379
|
+
suggestedSeconds: 3,
|
|
1380
|
+
promptHints: "One keyword in an otherwise-neutral line gets electrified: a bright gradient color sweep zips across the characters left-to-right in 15 to 20 frames (the wavefront brightest, trailing off), then settles to a steady glow with thin linking sparks between chars breathing.",
|
|
1381
|
+
pitfall: "Fill-process must NOT follow a light dot; sparks appear only after fill; glow stays restrained. A slow sweep reads as a progress bar \u2014 keep it 15 to 20 frames."
|
|
1382
|
+
},
|
|
1383
|
+
{
|
|
1384
|
+
id: "letterspace-materialize",
|
|
1385
|
+
role: "text-card",
|
|
1386
|
+
name: "Letterspace Materialize",
|
|
1387
|
+
purpose: 'The wordmark does not fade or type \u2014 it "crystallizes": all letters strokes begin growing simultaneously and converge to the word in one synchronized breath (wide-tracked caps).',
|
|
1388
|
+
energy: "low",
|
|
1389
|
+
suggestedSeconds: 4,
|
|
1390
|
+
promptHints: "All letters of a wide-tracked uppercase wordmark begin drawing their strokes at once and converge to the complete word in a single synchronized breath \u2014 like an invisible hand writing all letters simultaneously, every letter starting and finishing on the same frames.",
|
|
1391
|
+
pitfall: "Strokes must be continuous (no mask-halves \u2014 a half-then-rest reads as fake) AND synchronized (staggered letters read as typewriter semantics, not whole-word ritual)."
|
|
1392
|
+
},
|
|
1393
|
+
{
|
|
1394
|
+
id: "split-flap-title",
|
|
1395
|
+
role: "text-card",
|
|
1396
|
+
name: "Split-Flap Title",
|
|
1397
|
+
purpose: 'The wordmark as a station-board "broadcast" with mechanical announcing cadence \u2014 for countdowns, ship-dates, metric reveals, or retro-mechanical texture.',
|
|
1398
|
+
energy: "med",
|
|
1399
|
+
suggestedSeconds: 5,
|
|
1400
|
+
promptHints: "A title rendered as a split-flap station departure board: a stretch of scrambled flapping, then characters cascade-flip left-to-right to settle on the real title, holding dead-still. Mechanical announcing cadence.",
|
|
1401
|
+
pitfall: "Sound-dependent \u2014 the mechanical flap-click on each settle is half the effect; without it the cascade is lifeless."
|
|
1402
|
+
},
|
|
1403
|
+
{
|
|
1404
|
+
id: "type-rhythm-sync",
|
|
1405
|
+
role: "text-card",
|
|
1406
|
+
name: "Type Rhythm Sync",
|
|
1407
|
+
purpose: "Bind the title hard to the audio track \u2014 beat-bound (drum hits) or speech-bound (narrator word-by-word). The title or slogan synced tight to the music bed.",
|
|
1408
|
+
energy: "high",
|
|
1409
|
+
suggestedSeconds: 5,
|
|
1410
|
+
promptHints: "Title or slogan bound tight to the audio: variant A \u2014 each syllable or weight-pulse hits on a drum beat in a short decay window (dance feel); variant B \u2014 each word lights up following the narrator cadence (follow-along feel).",
|
|
1411
|
+
pitfall: "Strong sound dependency \u2014 the pulse must really land on the beat; unsynced pulses over a silent track read as broken."
|
|
1412
|
+
},
|
|
1413
|
+
// ── close ─────────────────────────────────────────────────────────────
|
|
1414
|
+
{
|
|
1415
|
+
id: "outro-group-photo-launch",
|
|
1416
|
+
role: "close",
|
|
1417
|
+
name: "Outro Group Photo Launch",
|
|
1418
|
+
purpose: "Recall one representative element from each feature shown for a group photo, then the wordmark enters as the climax \u2014 launch-event scale, energy pushed to the film peak.",
|
|
1419
|
+
energy: "high",
|
|
1420
|
+
suggestedSeconds: 5,
|
|
1421
|
+
promptHints: "Representative elements from every feature shown fly in from the four edges to gather around the center for a group photo, then the brand wordmark drops in as the climax \u2014 launch-event scale, crane plus stage light plus particles, the film highest energy.",
|
|
1422
|
+
pitfall: "First drafts are almost always too conservative \u2014 start at product-launch-keynote scale with crane, stage-light, particles; structure before effects (the four-way gather is the skeleton, atmosphere comes after)."
|
|
1423
|
+
},
|
|
1424
|
+
{
|
|
1425
|
+
id: "ui-strip-away-outro",
|
|
1426
|
+
role: "close",
|
|
1427
|
+
name: "UI Strip-Away Outro",
|
|
1428
|
+
purpose: 'The only "subtraction" outro \u2014 one click detonates all the UI to exit, leaving black with just the semantic focus (the clicked button). "Launch equals complexity returns to zero".',
|
|
1429
|
+
energy: "med",
|
|
1430
|
+
suggestedSeconds: 4,
|
|
1431
|
+
promptHints: "A single click detonates the entire UI to evaporate \u2014 evaporating in order from the outer edges to the center, one layer every few frames, each layer flying outward off-frame; the black field leaves only the one clicked button.",
|
|
1432
|
+
pitfall: "Evaporation must be ordered (outer-to-center, staggered, each layer with directional motion outward) \u2014 random or same-frame-all-vanish reads as a power-outage glitch."
|
|
1433
|
+
},
|
|
1434
|
+
{
|
|
1435
|
+
id: "ui-to-brand-morph",
|
|
1436
|
+
role: "close",
|
|
1437
|
+
name: "UI To Brand Morph",
|
|
1438
|
+
purpose: 'The brand finale fourth path \u2014 a product UI element morphs itself into the brand logo ("the UI you use every day IS this brand").',
|
|
1439
|
+
energy: "high",
|
|
1440
|
+
suggestedSeconds: 4,
|
|
1441
|
+
promptHints: 'A product UI element morphs itself into the brand mark \u2014 an icon flips once and resolves into the logo, one continuous deformation telling "the daily-use UI is the brand" in a single beat.',
|
|
1442
|
+
pitfall: "It is a transformation (the reverse direction from morph-from-primitive, and distinct from a gather-without-transform group photo) \u2014 keep it one clean morph, do not pile effects."
|
|
1443
|
+
},
|
|
1444
|
+
{
|
|
1445
|
+
id: "edit-hook-moves",
|
|
1446
|
+
role: "close",
|
|
1447
|
+
name: "Edit Hook (Button Ending)",
|
|
1448
|
+
purpose: "Rhetoric on the timeline itself \u2014 the ending that takes it back: fade to black, logo holds (audience thinks it is over), a sudden easter-egg hard-cut, cut back to logo. A trailer button-ending.",
|
|
1449
|
+
energy: "med",
|
|
1450
|
+
suggestedSeconds: 5,
|
|
1451
|
+
promptHints: 'Fade to black, the logo fades in and holds (audience assumes it is over), then a sudden short hard-cut to a UI close-up easter-egg, then hard-cut back to the logo to truly close \u2014 playing with the audience "it is finished" expectation.',
|
|
1452
|
+
pitfall: "At most one per film and only at the very end \u2014 a button-ending mid-film reads as a glitch."
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
id: "text-column-converge",
|
|
1456
|
+
role: "close",
|
|
1457
|
+
name: "Text Column Converge",
|
|
1458
|
+
purpose: "Two words sit left and right like a table-of-contents standoff; only on the last word do they converge into the product name \u2014 one convergence retcons the whole rotation as suspense setup. Recap or version-reveal energy.",
|
|
1459
|
+
energy: "med",
|
|
1460
|
+
suggestedSeconds: 6,
|
|
1461
|
+
promptHints: "Words alternate in left and right columns (perfectly still, equal margins), rotating through a feature list; only on the final word do the two halves converge once into the product name \u2014 one single convergence, no gradual shrink.",
|
|
1462
|
+
pitfall: "The convergence must happen exactly once and only at the end; any gradual shrink spoils the reveal and dilutes it to a progress bar."
|
|
1463
|
+
},
|
|
1464
|
+
// ── action ────────────────────────────────────────────────────────────
|
|
1465
|
+
{
|
|
1466
|
+
id: "beat-cut-moves",
|
|
1467
|
+
role: "action",
|
|
1468
|
+
name: "Beat Cut",
|
|
1469
|
+
purpose: "In highlight or sprint segments, make the CUT itself the drumbeat \u2014 trailer-style accelerating approach (rapid cuts into a held freeze) or awards-ceremony consecutive-flash ritual.",
|
|
1470
|
+
energy: "high",
|
|
1471
|
+
suggestedSeconds: 4,
|
|
1472
|
+
promptHints: "The cut itself is the beat: variant A \u2014 trailer-style accelerating approach, several ever-faster cuts building to a dead-still hold; variant B \u2014 awards-ceremony, live footage punctuated by hard flashes then a long held freeze.",
|
|
1473
|
+
pitfall: "Density-type high energy \u2014 sub-second beats, several channels jumping together; without an audio bed of kicks it reads as chaotic, not rhythmic."
|
|
1474
|
+
},
|
|
1475
|
+
{
|
|
1476
|
+
id: "speed-ramp-freeze",
|
|
1477
|
+
role: "action",
|
|
1478
|
+
name: "Speed Ramp Freeze",
|
|
1479
|
+
purpose: "Uniform flow reads as a slideshow. Two time-remap moves on one motion: speed-ramp (fast to gaze to fast, blur on the fast parts only) and freeze-annotate (flow to freeze, marker-pen circle the target to unfreeze).",
|
|
1480
|
+
energy: "high",
|
|
1481
|
+
suggestedSeconds: 5,
|
|
1482
|
+
promptHints: "On one continuous motion: variant speed-ramp \u2014 fast, then a slow gaze window, then fast again, with motion blur only on the fast segments (fast-blurred and slow-sharp contrast is half the effect); variant freeze \u2014 flow hard-freezes, a marker-pen circle strokes around the target, then it unfreezes and accelerates to catch up.",
|
|
1483
|
+
pitfall: 'The slow or freeze window needs enough frames or the gaze does not land; the fast-to-slow slope contrast needs about tenfold or "slowed down" is not readable.'
|
|
1484
|
+
},
|
|
1485
|
+
{
|
|
1486
|
+
id: "montage-rhythm-moves",
|
|
1487
|
+
role: "action",
|
|
1488
|
+
name: "Montage Rhythm",
|
|
1489
|
+
purpose: "Paragraph-level rhythm design \u2014 charge-burst (blackout hold then explode), flow-sketch (three ultra-close mechanical clicks then whip to the result), or chain-open (a momentum-handoff opening chain).",
|
|
1490
|
+
energy: "high",
|
|
1491
|
+
suggestedSeconds: 5,
|
|
1492
|
+
promptHints: "Paragraph-level rhythm shapes: A \u2014 pure black silent hold for one beat then explode open (EDM blackout); B \u2014 three ultra-close mechanical detail shots then whip-pan to the lit result; C \u2014 a chain of momentum handoffs opening the film.",
|
|
1493
|
+
pitfall: "Variant A is at most one per film and MUST be sound-designed (the blackout frame cuts audio to dead silence, the explode frame is the audio boom) \u2014 unsynced it reads as broken."
|
|
1494
|
+
},
|
|
1495
|
+
{
|
|
1496
|
+
id: "slam-entrance-moves",
|
|
1497
|
+
role: "action",
|
|
1498
|
+
name: "Slam Entrance",
|
|
1499
|
+
purpose: 'The top of the entrance-vocabulary force scale \u2014 "slam". Directional (fisheye whip-in), weight (drop with ring-plus-dust-plus-shake), or conduction (the shockwave shoves neighbors aside).',
|
|
1500
|
+
energy: "high",
|
|
1501
|
+
suggestedSeconds: 4,
|
|
1502
|
+
promptHints: "Card slams in with weight: A \u2014 fisheye-exaggerated perspective whip-in along the lens snapping flat; B \u2014 card drops at oversized scale, a ring burst plus dust plus impact shake all igniting on the same frame; C \u2014 the shockwave visibly shoves neighbor cards aside and they rebound.",
|
|
1503
|
+
pitfall: "All three carry screenshake \u2014 do not stack shake-family cards in the same shot; one screenshake event per beat."
|
|
1504
|
+
},
|
|
1505
|
+
{
|
|
1506
|
+
id: "scroll-brake-moves",
|
|
1507
|
+
role: "action",
|
|
1508
|
+
name: "Scroll Brake",
|
|
1509
|
+
purpose: 'A whole year of updates scrolls past as a fast blur-band, then an exponential-deceleration hard-brake stops dead on today release, which lifts off highlighted while the rest dims. Density says "always shipping"; the stop says "today is the big one".',
|
|
1510
|
+
energy: "high",
|
|
1511
|
+
suggestedSeconds: 5,
|
|
1512
|
+
promptHints: "A long vertical list scrolls past fast (blurring into a color band), then an exponential-deceleration hard-brake stops dead on one entry \u2014 that entry lifts off the surface and highlights while the rest dims; variant B snaps four L-brackets onto the stopped entry on the exact brake frame.",
|
|
1513
|
+
pitfall: "The high-speed band does not need real readable text (it is a blur) \u2014 placeholder grey blocks are fine; reserve real text for the braked entry."
|
|
1514
|
+
},
|
|
1515
|
+
// ── emotion ───────────────────────────────────────────────────────────
|
|
1516
|
+
{
|
|
1517
|
+
id: "light-play-moves",
|
|
1518
|
+
role: "emotion",
|
|
1519
|
+
name: "Light Play",
|
|
1520
|
+
purpose: "Treat light as a fourth brush (sweep, wipe, bloom): a dark-scene title reveal by a light sweep, crown the hero card with light, or impact-flare the slam frame. Light does what motion cannot.",
|
|
1521
|
+
energy: "med",
|
|
1522
|
+
suggestedSeconds: 5,
|
|
1523
|
+
promptHints: 'Light as a fourth brushstroke: a soft light sweep reveals a title out of darkness; or a quiet bloom crowns the hero card with light (low energy, the "lit" moment is the peak); or a hard impact-flare blooms on a slam frame.',
|
|
1524
|
+
pitfall: "The crown variant is deliberately low-energy \u2014 the bloom is the only peak; over-animate it and it stops being a crown and becomes a trick."
|
|
1525
|
+
},
|
|
1526
|
+
{
|
|
1527
|
+
id: "tension-camera-moves",
|
|
1528
|
+
role: "emotion",
|
|
1529
|
+
name: "Tension Camera",
|
|
1530
|
+
purpose: 'Small moves, all the force in emotional semantics \u2014 freeze-and-orbit, tilt-righted, imperceptible slow push, or pull-back-dim. Each is a direct word for "what should the audience feel here".',
|
|
1531
|
+
energy: "med",
|
|
1532
|
+
suggestedSeconds: 5,
|
|
1533
|
+
promptHints: "Small moves, heavy emotion: A \u2014 freeze mid-motion and orbit the camera around to examine; B \u2014 a tilted uneasy angle rolls back to level on the beat; C \u2014 an imperceptibly slow push building pressure, hard-cut to release at the peak; D \u2014 pull back while surroundings extinguish layer by layer, leaving one suspended point.",
|
|
1534
|
+
pitfall: 'Variant C "first two seconds must be unnoticeable" is the design intent, not a flaw \u2014 judge it on full playback, not a frame pull.'
|
|
1535
|
+
},
|
|
1536
|
+
{
|
|
1537
|
+
id: "collab-cursor-moves",
|
|
1538
|
+
role: "emotion",
|
|
1539
|
+
name: "Collab Cursor",
|
|
1540
|
+
purpose: 'Elevate the named collab cursor to an actor \u2014 two named cursors choreograph a handoff story in pure dark space with zero UI, or several drift as ambient particles for "the team is here" warmth.',
|
|
1541
|
+
energy: "med",
|
|
1542
|
+
suggestedSeconds: 5,
|
|
1543
|
+
promptHints: "Named collab cursors (with identity chips) as actors: A \u2014 two named cursors move in dark empty space, their positions telling a handoff story with no UI at all; B \u2014 several cursors drift in and float as ambient particles for team presence, one stopping to type a cameo.",
|
|
1544
|
+
pitfall: "Chip color equals identity code, must be consistent film-wide (blue equals Designer stays blue); a mid-film color change reads as a different person."
|
|
1545
|
+
},
|
|
1546
|
+
{
|
|
1547
|
+
id: "voice-waveform-live",
|
|
1548
|
+
role: "emotion",
|
|
1549
|
+
name: "Voice Waveform Live",
|
|
1550
|
+
purpose: 'The only functional voiceprint \u2014 the "listening to you" live receipt. Speaking towers tall, pauses shrink to a dot-row, history scrolls left. The audience reads "it is really listening" from the rise and fall alone.',
|
|
1551
|
+
energy: "med",
|
|
1552
|
+
suggestedSeconds: 5,
|
|
1553
|
+
promptHints: 'A live functional voiceprint: while "speaking" the waveform towers tall and dynamic, on "pauses" it shrinks to a dot-row, history scrolling left \u2014 the audience reads "it is genuinely listening" from the rise and fall alone, no other content needed.',
|
|
1554
|
+
pitfall: "If the film has a real narrator or voice track, the waveform envelope MUST follow that voice \u2014 the speak and pause segments align to the audio speak and pause; a one-second offset reads as fake."
|
|
1555
|
+
}
|
|
1556
|
+
];
|
|
1557
|
+
|
|
1558
|
+
// src/recipes/index.ts
|
|
1559
|
+
function pickRecipes(role, n) {
|
|
1560
|
+
if (!Number.isInteger(n) || n <= 0) return [];
|
|
1561
|
+
const out = [];
|
|
1562
|
+
for (const r of shotRecipes) {
|
|
1563
|
+
if (out.length >= n) break;
|
|
1564
|
+
if (r.role === role) out.push(r);
|
|
1565
|
+
}
|
|
1566
|
+
return out;
|
|
1567
|
+
}
|
|
1568
|
+
function recipesForArc(roles) {
|
|
1569
|
+
const out = [];
|
|
1570
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1571
|
+
for (const role of roles) {
|
|
1572
|
+
const match = shotRecipes.find((r) => r.role === role);
|
|
1573
|
+
if (match !== void 0 && !seen.has(match.id)) {
|
|
1574
|
+
seen.add(match.id);
|
|
1575
|
+
out.push(match);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
return out;
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1011
1581
|
// src/index.ts
|
|
1012
1582
|
function createHyperframesRunner() {
|
|
1013
1583
|
return {
|
|
@@ -1090,5 +1660,10 @@ export {
|
|
|
1090
1660
|
deriveBeats,
|
|
1091
1661
|
cinematicAvailable,
|
|
1092
1662
|
renderCinematic,
|
|
1663
|
+
SHOT_ROLES,
|
|
1664
|
+
ENERGY_LEVELS,
|
|
1665
|
+
shotRecipes,
|
|
1666
|
+
pickRecipes,
|
|
1667
|
+
recipesForArc,
|
|
1093
1668
|
renderMovie
|
|
1094
1669
|
};
|
package/dist/cli.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import '@pooriaarab/vibe-core';
|
|
|
7
7
|
* Lives in its own module so the CLI entry's is-main guard is never
|
|
8
8
|
* code-split into a shared chunk.
|
|
9
9
|
*/
|
|
10
|
-
declare const VERSION = "0.1
|
|
10
|
+
declare const VERSION = "0.2.1";
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* vibemovie CLI — render a session recap from JSON events, or serve MCP.
|
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
VERSION
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-IYP3PLDV.js";
|
|
5
5
|
import {
|
|
6
6
|
ENGINES,
|
|
7
7
|
RATIOS,
|
|
8
8
|
TEMPLATES,
|
|
9
9
|
renderMovie
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-LOSCKRIB.js";
|
|
11
11
|
|
|
12
12
|
// src/cli.ts
|
|
13
13
|
import { readFile } from "fs/promises";
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,84 @@ interface RenderOptions {
|
|
|
28
28
|
*/
|
|
29
29
|
declare function renderHyperframes(scenes: readonly Scene[], opts?: RenderOptions): string;
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* shots.ts — the shot-recipe library, distilled from video-shotcraft.
|
|
33
|
+
*
|
|
34
|
+
* Each recipe is a camera/shot move translated into a **prompt-based** stack
|
|
35
|
+
* (wavespeed image/video models + ffmpeg), not Remotion/React animation code.
|
|
36
|
+
* `promptHints` is a short motion/framing phrase a keyframe or image-to-video
|
|
37
|
+
* prompt can splice in next to a shared LOCK/STYLE anchor (see `cinematic.ts`).
|
|
38
|
+
*
|
|
39
|
+
* Source: github.com/Vincentwei1021/video-shotcraft — ~104 shot recipe cards
|
|
40
|
+
* organized in 10 functional categories (camera, data, effects, interaction,
|
|
41
|
+
* opening, outro, rhythm, transition, typography, ui-entrance). The ~52 cards
|
|
42
|
+
* below are the strongest, most distinct moves re-tagged by *narrative role*
|
|
43
|
+
* so the cinematic engine can draw a shot list for any energy arc
|
|
44
|
+
* (hook → establish → feature → … → close). Recipe `id`s keep the original
|
|
45
|
+
* kebab-case card names for provenance.
|
|
46
|
+
*
|
|
47
|
+
* Recipe-card metadata (purpose, energy, suggested duration, the motion core,
|
|
48
|
+
* and the single load-bearing pitfall) is summarized from the cards' Chinese
|
|
49
|
+
* frontmatter + body; timings are rounded to whole seconds at 30fps.
|
|
50
|
+
*/
|
|
51
|
+
/** Where a recipe sits in a film's narrative arc. */
|
|
52
|
+
type Role = 'hook' | 'establish' | 'reveal' | 'feature' | 'transition' | 'hero' | 'text-card' | 'close' | 'action' | 'emotion';
|
|
53
|
+
/** Kinetic intensity — the energy-curve axis from video-shotcraft. */
|
|
54
|
+
type Energy = 'low' | 'med' | 'high';
|
|
55
|
+
declare const SHOT_ROLES: readonly Role[];
|
|
56
|
+
declare const ENERGY_LEVELS: readonly Energy[];
|
|
57
|
+
interface ShotRecipe {
|
|
58
|
+
/** kebab-case id; matches the originating video-shotcraft card name. */
|
|
59
|
+
id: string;
|
|
60
|
+
/** Narrative role in the arc. */
|
|
61
|
+
role: Role;
|
|
62
|
+
/** Human-readable name (original card name). */
|
|
63
|
+
name: string;
|
|
64
|
+
/** One sentence: what this move is *for*. */
|
|
65
|
+
purpose: string;
|
|
66
|
+
/** Low/med/high energy — where it sits on the arc curve. */
|
|
67
|
+
energy: Energy;
|
|
68
|
+
/** Representative whole-second duration at 30fps (action + holds). */
|
|
69
|
+
suggestedSeconds: number;
|
|
70
|
+
/** Short motion/framing phrase for a keyframe or image-to-video prompt. */
|
|
71
|
+
promptHints: string;
|
|
72
|
+
/** The single load-bearing pitfall to avoid. */
|
|
73
|
+
pitfall: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The curated library. Ordered roughly by arc role (hook → establish → reveal
|
|
77
|
+
* → feature → transition → hero → text-card → close → action → emotion) so a
|
|
78
|
+
* naive slice reads as a sane film.
|
|
79
|
+
*/
|
|
80
|
+
declare const shotRecipes: readonly ShotRecipe[];
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* recipes/index.ts — public surface of the shot-recipe library.
|
|
84
|
+
*
|
|
85
|
+
* Re-exports the data and two deterministic selectors:
|
|
86
|
+
*
|
|
87
|
+
* - `pickRecipes(role, n)` — up to `n` recipes of one role (array order).
|
|
88
|
+
* - `recipesForArc(roles)` — one representative recipe per role in arc order
|
|
89
|
+
* (first match per role, deduped by id).
|
|
90
|
+
*
|
|
91
|
+
* Both are deterministic (no `Math.random`) to match the repo's "same input →
|
|
92
|
+
* same output" rendering principle. A caller that wants variety should shuffle
|
|
93
|
+
* upstream with a fixed seed, not inside the selectors.
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Up to `n` recipes whose `role` matches, in library (array) order. Returns
|
|
98
|
+
* fewer than `n` (possibly none) when the role is thinly populated — it never
|
|
99
|
+
* throws. Deterministic.
|
|
100
|
+
*/
|
|
101
|
+
declare function pickRecipes(role: Role, n: number): ShotRecipe[];
|
|
102
|
+
/**
|
|
103
|
+
* One representative recipe per role in `roles`, in the order the roles appear
|
|
104
|
+
* (first match per role, deduped by id so a repeated role does not double-up).
|
|
105
|
+
* Skips roles with no recipes rather than throwing. Deterministic.
|
|
106
|
+
*/
|
|
107
|
+
declare function recipesForArc(roles: readonly Role[]): ShotRecipe[];
|
|
108
|
+
|
|
31
109
|
/**
|
|
32
110
|
* @pooriaarab/vibemovie — your agent coding session as a short recap video.
|
|
33
111
|
*
|
|
@@ -91,4 +169,4 @@ interface RenderMovieResult {
|
|
|
91
169
|
*/
|
|
92
170
|
declare function renderMovie(events: readonly (VibeEvent | RawEvent)[], opts?: RenderMovieOptions): Promise<RenderMovieResult>;
|
|
93
171
|
|
|
94
|
-
export { BuildOptions, Engine, type NotifySink, Ratio, RawEvent, type RenderMovieOptions, type RenderMovieResult, type RenderOptions, Scene, renderHyperframes, renderMovie };
|
|
172
|
+
export { BuildOptions, ENERGY_LEVELS, type Energy, Engine, type NotifySink, Ratio, RawEvent, type RenderMovieOptions, type RenderMovieResult, type RenderOptions, type Role, SHOT_ROLES, Scene, type ShotRecipe, pickRecipes, recipesForArc, renderHyperframes, renderMovie, shotRecipes };
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ENERGY_LEVELS,
|
|
2
3
|
ENGINES,
|
|
4
|
+
SHOT_ROLES,
|
|
3
5
|
buildScenes,
|
|
4
6
|
cinematicAvailable,
|
|
5
7
|
deriveBeats,
|
|
6
8
|
deriveReferencePrompts,
|
|
9
|
+
pickRecipes,
|
|
10
|
+
recipesForArc,
|
|
7
11
|
renderCinematic,
|
|
8
12
|
renderHyperframes,
|
|
9
|
-
renderMovie
|
|
10
|
-
|
|
13
|
+
renderMovie,
|
|
14
|
+
shotRecipes
|
|
15
|
+
} from "./chunk-LOSCKRIB.js";
|
|
11
16
|
export {
|
|
17
|
+
ENERGY_LEVELS,
|
|
12
18
|
ENGINES,
|
|
19
|
+
SHOT_ROLES,
|
|
13
20
|
buildScenes,
|
|
14
21
|
cinematicAvailable,
|
|
15
22
|
deriveBeats,
|
|
16
23
|
deriveReferencePrompts,
|
|
24
|
+
pickRecipes,
|
|
25
|
+
recipesForArc,
|
|
17
26
|
renderCinematic,
|
|
18
27
|
renderHyperframes,
|
|
19
|
-
renderMovie
|
|
28
|
+
renderMovie,
|
|
29
|
+
shotRecipes
|
|
20
30
|
};
|
package/dist/mcp.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VERSION
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-IYP3PLDV.js";
|
|
4
4
|
import {
|
|
5
5
|
ENGINES,
|
|
6
6
|
RATIOS,
|
|
7
7
|
TEMPLATES,
|
|
8
8
|
renderMovie
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LOSCKRIB.js";
|
|
10
10
|
|
|
11
11
|
// src/mcp.ts
|
|
12
12
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibemovie",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Your agent coding session as a short recap video — Hyperframes (HTML/CSS/JS) with zero gen-video keys, or your own video model. For Claude Code, Codex, Gemini, and other agentic CLIs. Local-first.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|