changelog-video
changelog-video — an installable skill for AI agents.
By heygen-com · 59,900 installs
npx skills add heygen-com/hyperframes --skill changelog-video
Source repository · Upstream listing
Changelog → Branded Video
Input: a changelog .md (themes + items, like the weekly HyperFrames digest).
Output: a lint clean, seam gate green HyperFrames project in
projects/active/weekly changelog <range / . Render only when asked.
Load first, non negotiable: motion doctrine (+ cut the curve ,
oversized cursor if a cursor appears, seam craft ) and captions overlay .
This skill supplies the changelog specific pipeline; the doctrine supplies the
motion law.
The prime directive: visualize, don't list
Every theme is illustrated by an animated mock of the actual UI or a
faithful analog acting out the change in experience — never text bullets.
Route every theme/item through references/visualization registry.md BEFORE
writing the script; the registry decides ui recreate / ui analog / terminal /
checklist. Text checklist is the LAST resort, reserved for genuinely
non visual items (reliability fix lists).
Pipeline
0 · Bootstrap the project from THIS skill's assets — non negotiable
Do this before writing any composition HTML. Skipping it always produces a video that looks like a similar project you built before, NOT this skill's brand — that's the single most common way this skill goes off brand. The skill's assets, fonts, and scaffold are the skill; the SKILL.md prompt is a router.
Then read references/build spec.md end to end (not skimmed) — it defines the brand tokens (TT Norms Pro + ABC Solar Display + TT Norms Mono, cream f5f6f4 , rationed green 5ef17c , glass cards with green tinted borders, kicker/sec chip pill shape, 32px caption rail at top: 990 ) that every scene inherits from the scaffold.
Only THEN begin steps 1 6 below. Steps 1 4 (parse, route, script, VO) plan what goes into the scaffold; step 5 fills placeholders ( <RANGE , <TOTAL , <CUT N , <DUR N , scene bodies) inside the already copied project/index.html — you do NOT rewrite the scaffold's chrome, fonts, palette, or layout shell.
If you catch yourself reaching for cp on a prior video's index.html , or writing your own @font face declarations, or designing a WebGL shader background instead of using the encoded bg pattern MP4 above: STOP. Delete the current index.html and restart at the cp of the master skeleton scaffold. Rebuilding scene content on the right scaffold is cheaper than retrofitting brand into the wrong scaffold.
1 · Parse + editorial cut
Extract: week range, headline stats (releases, commits), themes, items.
Budget: 45 60s total. Title ≤2s, outro ≤3.5s, 4 themes ≈ 9 12s each.
Per theme keep ONE hero visualization + at most 3 spoken items. Everything
else exists only as the outro's "full digest" pointer. Cutting is the job:
a changelog with 30 items still yields ≤14 spoken beats.
Order themes by story: marquee feature → product surface → performance →
reliability (the digest usually already reads this way).
2 · Visualization routing
For each theme, pick the surface from references/visualization registry.md
and write one line: theme → surface → the 2 4 sequenced actions the mock
performs, each tied to a script phrase . If no registry surface fits and no
faithful analog exists, it's a checklist scene — don't invent fake UI for
something we can't represent honestly.
3 · Two layer script (spoken vs display)
Write the script as token lines per references/script voice.md :
conversational register, every technical term carrying a spoken phonetic
form from references/lexicon.json while display keeps standard spelling.
Captions show display ; the VO reads spoken . Any term not in the lexicon:
STOP and ask the user how it's pronounced, then add it to the lexicon.
Save as script tokens.json in the project.
4 · VO — Annie (HeyGen, pinned)
Requires heygen CLI ≥0.3.0 authenticated ( heygen auth login oauth ).
Then align spoken timestamps back to display tokens:
captions.json is the caption rail input (display spelling, spoken timing).
The aligner prints MISMATCH warnings — resolve every one before building
(usually a lexicon spelling the TTS renders as multiple words). The audio
is the clock : all beat times come from vo words.json ; a VO regen re opens
every seam.
Word timings are a hard gate. Before moving on to step 5, verify
vo words.json is non empty and has a words: [...] array with start / end
per word. If it's empty (0 bytes) or missing the array — a known failure mode
when the TTS provider returns audio but no timestamp payload — DO NOT proceed
without them. Fallback: forced align the produced audio against the display
script using local whisper:
Whisper mishears TTS renderings ("gee sap" → "gsap", "heyjen" → "hey Jen",
etc.) — captions still use the DISPLAY spelling from script tokens.json ;
whisper only supplies the timestamps. align captions.mjs handles the join.
This fallback is the difference between a captioned build and a silently
uncaptioned one.
5 · Build
Follow references/build spec.md exactly: brand tokens + fonts (bundled in
<SKILL DIR /assets/ ), the animated background encode, scene scaffold,
chrome, caption rail, one rationed green moment per scene. Then the doctrine
order: ledger.json (all ordinary seams cut the curve LEFT) → seam stamp →
internal beats on VO words → seam gate verify.
Captions are non optional. The master skeleton ships a caption rail IIFE
that reads a LINES array — leaving that array empty is a shipped bug, not a
style choice. Populate it from captions.json before proceeding to step 6:
If align captions.mjs was skipped or LINES is [] , the frame check in
step 6 will fail — do not paper over it by removing cap line from the
scaffold.
6 · Gates (all green before presenting)
1. bun run cwd packages/cli hyperframes check caption zone "x0=0;y0=.90;x1=1;y1=1;severity=error;seek=.02,.06,.10,.14,.18,.22,.26,.30,.34,.38,.42,.46,.50,.54,.58,.62,.66,.70,.74,.78,.82,.86,.90,.94,.98" (or the installed
hyperframes CLI from the repo local skills/hyperframes cli/ skill) —
0 errors (contrast: dim text ≥ .66 alpha; scene content stays above the
caption rail). Do NOT reach for
npx hyperframes@latest ; the tracked repo local CLI is the source of
truth for the composition contract this skill produces against.
2. seam gate.mjs verify — 0 fail.
3. Restart the preview server (it caches the bundle), spot check 3 4 beats
via player.seek on the raw comp page.
4. Do NOT render unless the user asks. After a requested render, verify
frames from the MP4 ( ffmpeg ss <t … frames:v 1 ): captions present,
background video not black, no tiny/frozen frames.
5. Caption presence gate — hard fail. Sample 3 4 frames spread across
the VO's spoken window (e.g. t=3 , t=15 , t=30 , t=42 for a 48s VO)
and confirm the caption rail at top: 990 renders visible text on each.
If any frame in a spoken interval is missing captions, the build ships
uncaptioned — treat it as a red gate and re check step 5's LINES
population. This is exactly what went wrong on the Jul 13 20 v4 build.
Project layout
Anti patterns
Don't Instead
Bullet point slides for UI changes Mock the surface acting out the change
Fake UI for un representable items Honest checklist scene
Plain "JSON"/"CLI" in the TTS text Lexicon spoken forms; display stays standard
Phonetic spellings in captions Captions always render the display layer
Guessing an unknown term's pronunciation Ask, then grow the lexicon
Speaking every changelog item ≤3 per theme; the digest link carries the rest
Green accents everywhere One green moment per scene ( 5ef17c)
Starting from a prior video's index.html Step 0 — copy examples/master skeleton.html from this skill into project/index.html , always
Hand crafted @font face / WebGL shader / custom BGM Step 0 — copy this skill's assets/ verbatim; the skill's assets ARE the brand
Delivered without CloudFront invalidation Run aws cloudfront create invalidation on distribution E2BSLVSZ7FG3U0 for the exact path after any S3 replace — CDN caches the old file otherwise
Shipping with the LINES array empty in the scaffold Step 4 must produce a populated captions.json ; step 5 must paste it into the IIFE; step 6 gate 5 must confirm captions on rendered frames. An empty LINES = uncaptioned ship = re do the run
No vo words.json → skip captions and ship anyway Fall back to whisper forced alignment on the produced audio; captions are non optional