@koda-sl/baker-cli 0.74.0 → 0.80.0
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/README.md +34 -8
- package/canvas/end-card-composition/index.html +66 -0
- package/canvas/end-card-composition/meta.json +19 -0
- package/canvas/feature-reveal-composition/index.html +83 -0
- package/canvas/feature-reveal-composition/meta.json +18 -0
- package/canvas/lower-third-composition/index.html +75 -0
- package/canvas/lower-third-composition/meta.json +18 -0
- package/canvas/stat-counter-composition/index.html +73 -0
- package/canvas/stat-counter-composition/meta.json +20 -0
- package/canvas/title-card-composition/index.html +90 -0
- package/canvas/title-card-composition/meta.json +20 -0
- package/canvas/video-call-composition/index.html +136 -0
- package/canvas/video-call-composition/meta.json +26 -0
- package/canvas/video-overlay-composition/index.html +39 -2
- package/dist/{chunk-JIDZ37KG.js → chunk-NBNUNCY7.js} +552 -313
- package/dist/chunk-NBNUNCY7.js.map +1 -0
- package/dist/cli.js +640 -114
- package/dist/cli.js.map +1 -1
- package/dist/engine/index.d.ts +6 -0
- package/dist/engine/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-JIDZ37KG.js.map +0 -1
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=1080, height=1920" />
|
|
6
|
+
<script src="./gsap.min.js"></script>
|
|
7
|
+
<style>
|
|
8
|
+
/* The "talking head on a video call" pattern — see the creative-canvas-ads
|
|
9
|
+
skill's references/hyperframes/talking-head-and-overlays.md. Presenter
|
|
10
|
+
(the `background` video) starts full-bleed, then shrinks to a corner PIP
|
|
11
|
+
pill while #content takes the stage. Replace #content with a real
|
|
12
|
+
screenshot <img> you drop in this dir, or nest a catalog block. Drop
|
|
13
|
+
brand-bold.otf / brand-regular.otf for on-brand type. */
|
|
14
|
+
@font-face {
|
|
15
|
+
font-family: 'BrandFont';
|
|
16
|
+
src: url('./brand-bold.otf') format('opentype'), url('./brand-bold.ttf') format('truetype');
|
|
17
|
+
font-weight: 700 900;
|
|
18
|
+
font-display: swap;
|
|
19
|
+
}
|
|
20
|
+
@font-face {
|
|
21
|
+
font-family: 'BrandFont';
|
|
22
|
+
src: url('./brand-regular.otf') format('opentype'), url('./brand-regular.ttf') format('truetype');
|
|
23
|
+
font-weight: 100 600;
|
|
24
|
+
font-display: swap;
|
|
25
|
+
}
|
|
26
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
27
|
+
html, body { width: 1080px; height: 1920px; overflow: hidden; background: #000; }
|
|
28
|
+
#root { position: absolute; inset: 0; font-family: 'BrandFont', 'Helvetica Neue', Arial, sans-serif; }
|
|
29
|
+
|
|
30
|
+
/* Content stage — sits BEHIND the presenter (DOM order: #content first, then
|
|
31
|
+
#video-wrap → the pill paints on top). Swap this panel for a screenshot. */
|
|
32
|
+
#content {
|
|
33
|
+
position: absolute; inset: 0; background: {{bg_color}}; color: {{text_color}};
|
|
34
|
+
display: flex; flex-direction: column; justify-content: center;
|
|
35
|
+
padding: 160px 96px; opacity: 0;
|
|
36
|
+
}
|
|
37
|
+
#content .kicker { width: 120px; height: 8px; background: {{accent_color}}; border-radius: 4px; transform: scaleX(0); transform-origin: left center; margin-bottom: 40px; }
|
|
38
|
+
#content .headline { font-size: 104px; font-weight: 900; line-height: 1.08; letter-spacing: -1px; text-wrap: balance; }
|
|
39
|
+
|
|
40
|
+
/* Presenter video — full-bleed at first, then TRANSFORM-scaled into a corner
|
|
41
|
+
pill. Transforms only: never animate left/top/width/height — they trigger
|
|
42
|
+
layout, and the renderer's parallel per-frame seeks can desync layout-driven
|
|
43
|
+
geometry (see references/hyperframes/composition-engine.md). The pill chrome
|
|
44
|
+
(radius/ring) is applied at PIP time and pre-multiplied for the scale. */
|
|
45
|
+
#video-wrap { position: absolute; top: 0; left: 0; width: 1080px; height: 1920px; overflow: hidden; transform-origin: 0 0; }
|
|
46
|
+
#bg { width: 100%; height: 100%; object-fit: cover; }
|
|
47
|
+
|
|
48
|
+
/* Floating glass claim card. */
|
|
49
|
+
#claim {
|
|
50
|
+
position: absolute; left: 64px; bottom: 360px; max-width: 720px;
|
|
51
|
+
padding: 36px 44px; border-radius: 24px;
|
|
52
|
+
background: rgba(255,255,255,0.10); backdrop-filter: blur(18px) saturate(140%);
|
|
53
|
+
-webkit-backdrop-filter: blur(18px) saturate(140%);
|
|
54
|
+
border: 1px solid rgba(255,255,255,0.22);
|
|
55
|
+
color: {{text_color}}; font-size: 46px; font-weight: 700; line-height: 1.2;
|
|
56
|
+
opacity: 0; transform: translateY(24px);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* Caption band. */
|
|
60
|
+
#caption {
|
|
61
|
+
position: absolute; left: 50%; bottom: 150px; transform: translateX(-50%);
|
|
62
|
+
width: 88%; text-align: center; color: {{text_color}};
|
|
63
|
+
font-size: 56px; font-weight: 800; line-height: 1.15;
|
|
64
|
+
text-shadow: 0 2px 8px rgba(0,0,0,0.6), 0 0 2px rgba(0,0,0,0.9);
|
|
65
|
+
opacity: 0;
|
|
66
|
+
}
|
|
67
|
+
#caption .u { display: inline-block; height: 6px; width: 120px; background: {{accent_color}}; border-radius: 3px; vertical-align: middle; margin-left: 16px; transform: scaleX(0); transform-origin: left center; }
|
|
68
|
+
</style>
|
|
69
|
+
</head>
|
|
70
|
+
<body>
|
|
71
|
+
<div id="root" data-composition-id="video-call" data-start="0" data-duration="{{duration}}" data-width="1080" data-height="1920">
|
|
72
|
+
<div id="content">
|
|
73
|
+
<div class="kicker" id="kicker"></div>
|
|
74
|
+
<div class="headline" id="headline">{{headline}}</div>
|
|
75
|
+
</div>
|
|
76
|
+
<div id="video-wrap">
|
|
77
|
+
<video id="bg" src="background.mp4" muted></video>
|
|
78
|
+
</div>
|
|
79
|
+
<div id="claim">{{claim}}</div>
|
|
80
|
+
<div id="caption"><span id="caption-text">{{caption}}</span><span class="u" id="caption-u"></span></div>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<script>
|
|
84
|
+
(() => {
|
|
85
|
+
var DURATION = parseFloat('{{duration}}') || 8;
|
|
86
|
+
var PIP_AT = parseFloat('{{pip_at_s}}'); if (!(PIP_AT >= 0)) PIP_AT = 2;
|
|
87
|
+
var hasHeadline = ((document.getElementById('headline').textContent) || '').trim().length > 0;
|
|
88
|
+
var hasClaim = ((document.getElementById('claim').textContent) || '').trim().length > 0;
|
|
89
|
+
var hasCaption = ((document.getElementById('caption-text').textContent) || '').trim().length > 0;
|
|
90
|
+
if (!hasClaim) document.getElementById('claim').style.display = 'none';
|
|
91
|
+
if (!hasCaption) document.getElementById('caption').style.display = 'none';
|
|
92
|
+
// Kicker sits at scaleX(0) but still holds its layout box + 40px bottom margin,
|
|
93
|
+
// so hide it outright when there's no headline (the default) — no dead space.
|
|
94
|
+
if (!hasHeadline) document.getElementById('kicker').style.display = 'none';
|
|
95
|
+
|
|
96
|
+
// Top-right PIP pill, 9:16 to MATCH the full frame so a single UNIFORM scale
|
|
97
|
+
// shrinks the presenter without distorting the video (non-uniform scaleX/scaleY
|
|
98
|
+
// would squish it). Edit x/y for another corner. Transforms only.
|
|
99
|
+
var PILL = { x: 672, y: 56, w: 360, h: 640 };
|
|
100
|
+
var s = PILL.w / 1080; // === PILL.h / 1920 (uniform)
|
|
101
|
+
var k = 1 / s; // pre-multiplier so the chrome lands crisp at the target size after scaling
|
|
102
|
+
|
|
103
|
+
var tl = gsap.timeline({ paused: true });
|
|
104
|
+
|
|
105
|
+
// Presenter shrinks into the pill; content stage fades up underneath. The pill
|
|
106
|
+
// chrome (radius + white ring) is set at PIP time and pre-multiplied by k so,
|
|
107
|
+
// once the element is scaled by s, it reads as ~28px radius + a crisp ring.
|
|
108
|
+
tl.set('#video-wrap', {
|
|
109
|
+
borderRadius: 28 * k,
|
|
110
|
+
boxShadow: '0 ' + 24 * k + 'px ' + 60 * k + 'px ' + (-20 * k) + 'px rgba(0,0,0,0.45), 0 0 0 ' + 6 * k + 'px rgba(255,255,255,0.7), 0 0 0 ' + 8 * k + 'px rgba(11,16,32,0.18)',
|
|
111
|
+
}, PIP_AT);
|
|
112
|
+
tl.fromTo('#video-wrap',
|
|
113
|
+
{ x: 0, y: 0, scale: 1 },
|
|
114
|
+
{ x: PILL.x, y: PILL.y, scale: s, duration: 0.6, ease: 'power2.inOut' },
|
|
115
|
+
PIP_AT);
|
|
116
|
+
tl.fromTo('#content', { opacity: 0 }, { opacity: 1, duration: 0.4, ease: 'power2.out' }, PIP_AT + 0.1);
|
|
117
|
+
if (hasHeadline) tl.fromTo('#kicker', { scaleX: 0 }, { scaleX: 1, duration: 0.4, ease: 'power3.out' }, PIP_AT + 0.25);
|
|
118
|
+
|
|
119
|
+
// Glass claim card rises in.
|
|
120
|
+
if (hasClaim) tl.fromTo('#claim', { opacity: 0, y: 24 }, { opacity: 1, y: 0, duration: 0.45, ease: 'power2.out' }, PIP_AT + 0.45);
|
|
121
|
+
|
|
122
|
+
// Caption fades in with an accent underline wipe.
|
|
123
|
+
if (hasCaption) {
|
|
124
|
+
tl.fromTo('#caption', { opacity: 0 }, { opacity: 1, duration: 0.35, ease: 'power1.out' }, PIP_AT + 0.6);
|
|
125
|
+
tl.fromTo('#caption-u', { scaleX: 0 }, { scaleX: 1, duration: 0.4, ease: 'power3.out' }, PIP_AT + 0.7);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Hold to the full duration.
|
|
129
|
+
tl.to({}, { duration: 0.01 }, Math.max(0.02, DURATION - 0.01));
|
|
130
|
+
|
|
131
|
+
window.__timelines = window.__timelines || {};
|
|
132
|
+
window.__timelines["video-call"] = tl;
|
|
133
|
+
})();
|
|
134
|
+
</script>
|
|
135
|
+
</body>
|
|
136
|
+
</html>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "video-call",
|
|
3
|
+
"title": "Talking head on a video call — presenter shrinks to a PIP pill over content",
|
|
4
|
+
"description": "The 'AI person showing you something on a call' pattern. The presenter video starts full-bleed, then at pip_at_s shrinks into a rounded corner PIP pill while a content card (a claim, or your screen-share/app-UI image) takes the stage; a glass claim card and a caption band animate in. The presenter clip is the `background` input. Replace the #content panel with a real screenshot <img> you drop in this dir, or nest a catalog block (npx hyperframes add …) — see the creative-canvas-ads skill's references/hyperframes/talking-head-and-overlays.md. Drop brand-bold.otf / brand-regular.otf for on-brand type. Fixed 1080x1920; copy + edit width/height for other ratios.",
|
|
5
|
+
"width": 1080,
|
|
6
|
+
"height": 1920,
|
|
7
|
+
"fps": 30,
|
|
8
|
+
"default_duration": 8,
|
|
9
|
+
"inputs": {
|
|
10
|
+
"background": {
|
|
11
|
+
"kind": "video",
|
|
12
|
+
"required": true,
|
|
13
|
+
"staged_as": "background.mp4",
|
|
14
|
+
"description": "The presenter / talking-head clip (e.g. a Seedance native-voiced scene)."
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"params": {
|
|
18
|
+
"headline": { "kind": "string", "default": "", "description": "Big line on the content stage (what the presenter is showing)." },
|
|
19
|
+
"claim": { "kind": "string", "default": "", "description": "Short proof/claim on the floating glass card (optional)." },
|
|
20
|
+
"caption": { "kind": "string", "default": "", "description": "A caption line in the lower band (optional)." },
|
|
21
|
+
"pip_at_s": { "kind": "number", "default": 2, "min": 0, "max": 30, "description": "When the presenter shrinks to the corner pill." },
|
|
22
|
+
"bg_color": { "kind": "color", "default": "#0b1020", "description": "Content-stage background (behind the presenter)." },
|
|
23
|
+
"text_color": { "kind": "color", "default": "#ffffff" },
|
|
24
|
+
"accent_color": { "kind": "color", "default": "#5b8cff", "description": "Headline accent + caption underline + pill ring tint." }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -8,17 +8,33 @@
|
|
|
8
8
|
/* ═══════════════════════════════════════════════════════════════════════
|
|
9
9
|
OVERLAY LAYER — PAINT THIS YOURSELF.
|
|
10
10
|
|
|
11
|
+
This is a REAL Hyperframes composition (hyperframe_render runs the genuine
|
|
12
|
+
`npx hyperframes` renderer), so it can do FAR more than the seeded text.
|
|
13
|
+
|
|
11
14
|
The scaffold seeds #overlay-root (below) with the reference ad's overlays
|
|
12
15
|
as plain HTML elements — real text, a position class, and data-start/
|
|
13
16
|
data-dur timing. This file is YOURS: restyle every rule here, add classes,
|
|
14
17
|
build a lower-third bar or a scrolling ticker, drop a logo image into this
|
|
15
|
-
dir and reference it with <img>. The
|
|
18
|
+
dir and reference it with <img>. The simple contract for a seeded element:
|
|
16
19
|
|
|
17
20
|
• keep each overlay element inside #overlay-root
|
|
18
21
|
• keep its data-start / data-dur (seconds) — the runtime shows/hides by them
|
|
19
22
|
• (optional) data-anim="fade|slide_up|slide_down|pop" for a canned entrance
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
…and the richer capabilities (see the two commented slots in #overlay-root,
|
|
25
|
+
and the full docs under the creative-canvas-ads skill's references/hyperframes/):
|
|
26
|
+
|
|
27
|
+
• PULL A READY-MADE BLOCK — `npx hyperframes add <id>` (run in THIS dir;
|
|
28
|
+
lands in compositions/) then nest it with a <div data-composition-src>
|
|
29
|
+
clip. ~97 blocks: lower-thirds, social-proof cards, stat counters, charts,
|
|
30
|
+
code, logo stings. `npx hyperframes catalog --type block` lists them.
|
|
31
|
+
• CAPTIONS — drive a karaoke/themed/kinetic caption track off the
|
|
32
|
+
transcript (sound-off feed). `npx hyperframes add caption-highlight`.
|
|
33
|
+
• MOTION — animate with GSAP using the named motion-rule vocabulary, not
|
|
34
|
+
just the four canned entrances.
|
|
35
|
+
|
|
36
|
+
The seeded runtime decides only WHEN a plain element shows; everything
|
|
37
|
+
else — look, motion, nested blocks — is your CSS/markup/GSAP.
|
|
22
38
|
For on-brand type, drop brand-bold.otf / brand-regular.otf into this dir.
|
|
23
39
|
═══════════════════════════════════════════════════════════════════════ */
|
|
24
40
|
@font-face {
|
|
@@ -68,6 +84,27 @@
|
|
|
68
84
|
<video id="bg" src="background.mp4" muted></video>
|
|
69
85
|
<div id="overlay-root">
|
|
70
86
|
<!--OVERLAYS-->
|
|
87
|
+
|
|
88
|
+
<!-- ── NESTED BLOCK SLOT (optional) ───────────────────────────────────
|
|
89
|
+
For an ANIMATED graphic (lower-third, social-proof/review card, stat
|
|
90
|
+
counter, chart, logo sting), pull a ready-made block instead of a
|
|
91
|
+
static <img>. From this dir:
|
|
92
|
+
npx hyperframes catalog --type block # find one by tag/name
|
|
93
|
+
npx hyperframes add yt-lower-third # writes compositions/yt-lower-third.html
|
|
94
|
+
then uncomment + retime the nested clip (add data-start/data-track-index;
|
|
95
|
+
data-composition-id is optional but if set must match the block's id):
|
|
96
|
+
<div data-composition-src="compositions/yt-lower-third.html"
|
|
97
|
+
data-start="3" data-duration="4.5" data-track-index="2"
|
|
98
|
+
data-width="1920" data-height="1080"></div>
|
|
99
|
+
──────────────────────────────────────────────────────────────────── -->
|
|
100
|
+
|
|
101
|
+
<!-- ── CAPTION TRACK SLOT (optional, recommended for sound-off feeds) ──
|
|
102
|
+
The feed plays muted — burn in captions from the word-level transcript
|
|
103
|
+
the deconstruct produced. Floor: `npx hyperframes add caption-highlight`
|
|
104
|
+
(TikTok karaoke); escalate by register (caption-kinetic-slam, etc.).
|
|
105
|
+
Wiring + the {id,text,start,end} sync contract:
|
|
106
|
+
references/hyperframes/captions-and-audio.md.
|
|
107
|
+
──────────────────────────────────────────────────────────────────── -->
|
|
71
108
|
</div>
|
|
72
109
|
</div>
|
|
73
110
|
|