Skip to content
Agentmart
Submit a tool

compose

Turn captured product footage into a finished demo video - a 1440p60 master with the app in a framed window on a themed backdrop, a feathered spotlight that…

Skill by stevengonsalvez

IndexedMIT★ 1
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/stevengonsalvez-compose

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Turn captured product footage into a finished demo video - a 1440p60 master with the app in a framed window on a themed backdrop, a feathered spotlight that glides between proof moments with a short label at each, blur and push transitions, chapter title cards, persona-switch and end cards, dead-hold trims and a mechanical still-check, an optional 9:16 vertical social cut whose crop follows the action with headline and burned captions, plus a sound layer timed from the capture's own events (UI sound effects, an optional ducked music bed with cuts on the beat, optional narration whose anchor words fire the spotlights, a loudness-checked mix) and WebVTT captions and chapters. Takes a demo:capture take directory (per-chapter mp4 plus events.json) and one JSON config carrying the brand, chapter titles, card copy and any label overrides; everything else is derived from the capture. Use when asked to "compose the demo", "assemble the captured chapters", "add spotlights and callouts to the footage", "put title cards on the demo", "cut the demo together", "make the walkthrough video from the takes", or to re-cut one chapter after re-shooting it, or to "add narration", "add a voiceover", "add music", "add sound effects" or "add captions" to a demo, or to "make a vertical cut", "make a 9:16 version for socials", "make a reel or short of the demo". Renders through HyperFrames. Does not record anything; pair it with demo:capture.

Use cases: design, writing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Node.js package

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/compose

What's inside

Skill name
compose
Description
Turn captured product footage into a finished demo video - a 1440p60 master with the app in a framed window on a themed backdrop, a feathered spotlight that glides between proof moments with a short label at each, blur and push transitions, chapter title cards, persona-switch and end cards, dead-hold trims and a mechanical still-check, an optional 9:16 vertical social cut whose crop follows the action with headline and burned captions, plus a sound layer timed from the capture's own events (UI sound effects, an optional ducked music bed with cuts on the beat, optional narration whose anchor words fire the spotlights, a loudness-checked mix) and WebVTT captions and chapters. Takes a demo:capture take directory (per-chapter mp4 plus events.json) and one JSON config carrying the brand, chapter titles, card copy and any label overrides; everything else is derived from the capture. Use when asked to "compose the demo", "assemble the captured chapters", "add spotlights and callouts to the footage", "put title cards on the demo", "cut the demo together", "make the walkthrough video from the takes", or to re-cut one chapter after re-shooting it, or to "add narration", "add a voiceover", "add music", "add sound effects" or "add captions" to a demo, or to "make a vertical cut", "make a 9:16 version for socials", "make a reel or short of the demo". Renders through HyperFrames. Does not record anything; pair it with demo:capture.
License
MIT
Instructions
786 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts

Agent Skills spec issues

  • description: longer than 1024 characters
  • body: 786 lines (spec recommends under 500)

Files (29)

  • SKILL.md
  • hyperframes.json · assets/template/
  • package.json · assets/template/
  • .gitignore · examples/ferry/
  • alerts.html · examples/ferry/app/
  • board.html · examples/ferry/app/
  • fares.html · examples/ferry/app/
  • style.css · examples/ferry/app/
  • beats.mjs · examples/ferry/
  • ferry.beats.config.json · examples/ferry/
  • ferry.config.json · examples/ferry/
  • ferry.narrated.config.json · examples/ferry/
  • fraunces-700.woff2 · examples/ferry/fonts/
  • plex-500.woff2 · examples/ferry/fonts/
  • serve.mjs · examples/ferry/
  • phone.png · examples/ferry/slides/
  • tablet.png · examples/ferry/slides/
  • web.png · examples/ferry/slides/
  • audio-check.mjs · scripts/
  • audio.mjs · scripts/
  • captions.mjs · scripts/
  • check-local-gsap.mjs · scripts/
  • check.mjs · scripts/
  • compose.mjs · scripts/
  • concat.sh · scripts/
  • config.mjs · scripts/
  • gsap.mjs · scripts/
  • hfrender.mjs · scripts/
  • render.sh · scripts/

SKILL.md (first lines)

# demo:compose

Assemble captured chapters into one demo video. Capture it elsewhere.

```
demo:capture takes/ ──▶ compose.mjs ──▶ projects/<segment>/  (HyperFrames)
  <ch>.mp4                  ▲              │
  <ch>-events.json      config.json     render.sh ──▶ out/seg/<segment>.mp4
                        (brand, copy)      │      (PNG frames, packed lossless)
                                        check.mjs  ──▶ hit / miss per mark  ◀── THE GATE
                                           │
                                        concat.sh ──▶ out/<name>.mp4 + montage  (seams dissolved; the ONE lossy encode)
```

Pairs with **demo:capture** (the sibling skill in this plugin), which produces the take
directory this skill consumes. Rendering is **HyperFrames**: load `hyperframes-core` before
editing the generated HTML, and `hyperframes-keyframes` / `hyperframes-animation` before
changing the motion. The generated composition already satisfies the core contract (standalone
root, one paused GSAP timeline keyed to `data-composition-id`, `@font-face` for every named
family, clip timing on the `<video>` and not on an ancestor).

## Run

```bash
S="$SKILL_DIR"   # this skill's own directory
node "$S/scripts/compose.mjs" my.config.json            # generate every segment project
bash "$S/scripts/render.sh"  my.config.json             # render each one, foreground, resumable
node "$S/scripts/check.mjs"  my.config.json             # THE GATE: hit/miss per mark, exit 1 on miss
bash "$S/scripts/concat.sh"  my.config.json             # final mp4 with sound, captions, contact sheet
```

Every command takes optional segment names to limit the work (`compose.mjs cfg.json consent`).
`render.sh` skips a segment whose `out/seg/<segment>.mp4` is newer than its `index.html`, so a
killed run resumes. A segment is rendered aside and swapped in only once it succeeds, so a failed
re-render keeps the previous one, and it must hold its planned length times the frame rate
(60fps final, 30fps draft, passed to HyperFrames as `--fps`) or render.sh fails it.
Renders run one at a time in the foreground with `workers` capture processes (default 4) under a
timeout of 120s plus 10s per second of segment at 720p30, scaled by pixel rate (80s per second at
the 1440p60 master): a harness that kills long background tasks for low memory will otherwise
take the whole batch out. The render itself is `scripts/hfrender.mjs` (render.sh and the
burned-caption cut both use it); its timeout is node's own, so it holds on stock macOS too.

A worked example is `examples/ferry/`: a made-up ferry operator's three-page app
(`serve.mjs`, `app/`), the `beats.mjs` that films it with demo:capture, and
`ferry.config.json` with its fonts. Every path in it is relative to that directory, so copy
the directory somewhere writable and run it end to end:

```bash
cp -r "$S/examples/ferry" /scratch/ferry && cd /scratch/ferry   # CAPTURE_DIR: the demo:capture skill dir
node serve.mjs &                                            # app on 127.0.0.1:7744
node "$CAPTURE_DIR/scripts/run.mjs" beats.mjs               # takes/departures.mp4, takes/fares.mp4
node "$S/scripts/compose.mjs" ferry.config.json && bash "$S/scripts/render.sh" ferry.config.json
node "$S/scripts/check.mjs" ferry.config.json && bash "$S/scripts/concat.sh" ferry.config.json
```

At the default 1440p60 master the ferry renders in about 15 minutes on an 8-core host without a
GPU (measured under load, see The look); `"quality": "draft"` in the config makes it about 3.

## Config

Only `takes` and `chapters` are required. Everything below shows the default where there is one.

```jsonc
{
  "name": "my-demo",                  // final file is out/<name>.mp4
  "takes": "/scratch/takes",          // demo:capture output dir (required)
  "out": "./compose",                 // work dir: projects/, out/, work/
  "format": "landscape",              // or "square" or "vertical"; see Playback pace and format
  "quality": "final",                 // 2560x1440 (square 1440x1440, vertical 1080x1920) at 60fps; "draft" = 1280x720 (1080x1080, 720x1280) at 30fps
  "width": 2560, "height": 1440,      // default from format and quality; set one to override the canvas
  "frame": {                          // the framed window; false = full-bleed footage
    "style": "window", "padding": 80, "radius": 24, "shadow": 1,
    "backdrop": "glow",               // "glow" (gradient plus accent light), "gradient" or "solid"
    "grain": 0.045, "tilt": 9 },      // tilt: degrees the window arrives at, eased flat
  "spotlight": { "feather": 18, "glide": 2.5, "sweep": true, "blur": 2 },
  "transitions": { "blur": 0.5, "whip": 0.4 },  // seam lengths in seconds; false = hard cuts
  "workers": 4,                       // hyperframes capture processes
  "crf": 16,                          // the one lossy encode
  "theme": {
    "bg": "#101114", "surface": "#1B1D22", "accent": "#C8CDD6",
    "highlight": "#9AA3B2", "text": "#FFFFFF", "muted": "#B5BAC4",
    "fonts": {                        // omit entirely to use the generic sans stack
      "display": { "file": "fonts/x.woff2", "family": "X", "weight": "600 700" },
      "body":    { "file": "fonts/y.woff2", "family": "Y", "weight": "500 600" }
    }
  },
  "scrim": "rgba(0,0,0,0.60)",        // what the spotlight dims everything else to
  "cards": {
    "title":  { "kicker": "…", "title": "…", "sub": "…", "dur": 3 },
    "switches": [ { "id": "switch-card", "before": "<chapter>", "kicker": "…", "title": "…", "sub": "…", "dur": 2.5 } ],
    "end":    { "kicker": "…", "title": "…", "sub": "…", "dur": 3 }
  },                                  // any card also takes "narration": "…" (see Sound)
  "chapterCardDur": 2.0,
  "defaultPersona": "",               // per-chapter `persona` overrides it
  "chapters": [
    { "name": "<chapter>",            // must match <chapter>.mp4 in takes (required)
      "title": "The live board",      // default: chapter name, title-cased
      "persona": "Foot passenger",
      "labels": ["…"],                // default: the capture's own mark labels. One per mark.
      "cuts": [[10.98, 11.2]],        // extra source-time cuts, e.g. a splash screen
      "cardDur": 2.0,
      "speed": { "travel": 1 },       // per-chapter override of the global speed
      "narration": { "intro": "…",    // spoken over the chapter card; see Sound
        "marks": ["The {@next}next sailing runs late.", null] } }  // one per mark, null = none
  ],
  "speed":  { "travel": 2, "rampMs": 250 },
  "cut": "continuous",                // or "beats": one still per mark, held for its line; see Beat-paced cut
  "beats":  { "pad": 0.6, "lead": 0, "cardHold": 2.5, "hold": 3, "fade": 0, "floor": 0, "min": 3, "max": 6, "lineMax": 7 },
  "clips": false,                     // each chapter also as its own mp4 (default true with "cut": "beats")
  "pace": 1,
  "targetDuration": 45,               // optional, seconds, whole video
  "hold":   { "min": 1.5, "max": 2.2 },
  "fadeLead": 0.25,                   // spotlight fades in this long before the mark (or once the zoom settles)
  "deadHold": 2.0,                    // freezes longer than this get trimmed
  "layout": { "safeMargin": 64, "labelHeight": 48, "labelGap": 14, "maxLabelWords": 6 },
  "check":  { "litRatio": 0.80, "dimRatio": 0.62, "contentSd": 8, "driftMax": 12, "alignMax": 7, "glideStep": 0.2, "calloutMin": 12, "cutEdge": 0.9 },
  "audio": {                          // optional; "audio": false turns the sound layer off
    "sfx":       { "level": 0, "click": true, "type": true, "zoom": true, "mark": true },  // or false
    "music":     { "file": "bed.mp3", "level": -18, "duck": 11, "fadeIn": 1.5, "fadeOut": 2.5,

From stevengonsalvez/ainb-toolkit, MIT.

More from stevengonsalvez/ainb-toolkit

Signals

Stars
1
Forks
1
Open issues
4
Last commit (this folder)
Oct 14, 2026 (15 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from stevengonsalvez

Cite this page

compose skill. Agent Mart. https://agentmart.dev/skills/stevengonsalvez-compose (last updated 2026-10-24)