Skip to content
Back to skills

Cueframe Product Video

ASecurity

Use when turning a screen recording (with cursor/click events) into a polished, auto-zooming product video or demo reel via CueFrame — e.g. "make a product demo from this Browserbase capture", "auto-zoom this screen recording to where the user clicked", "turn this walkthrough into a social demo". This is a USE-CASE recipe over the CueFrame primitives in the `cueframe-cli` skill.

  • 2 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added October 23, 2026
ai-agentsgo

Works with

  • cursor
  • terminal
  • cli
  • mcp

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned November 11, 2026

npx -y skills add cueframe-ai/cueframe-mcp --skill cueframe-product-video --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Cueframe Product Video?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Cueframe Product Video
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/cueframe-ai-cueframe-product-video/badge)](https://www.skillsdirectory.com/skills/cueframe-ai-cueframe-product-video)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: cueframe-product-video
description: Use when turning a screen recording (with cursor/click events) into a polished, auto-zooming product video or demo reel via CueFrame — e.g. "make a product demo from this Browserbase capture", "auto-zoom this screen recording to where the user clicked", "turn this walkthrough into a social demo". This is a USE-CASE recipe over the CueFrame primitives in the `cueframe-cli` skill.
---

# CueFrame — Product Video recipe

Use the [project and capability policy](../composing-video/references/project-policy.md) for scope, current state and metered work.

A **use-case recipe**, not new framework surface. CueFrame's engine only knows
primitives (`upload` → `composition put` → `render`, the `reframe` viewport, the
overlay/effect primitives). This skill is the *judgment* on top: how to turn a
captured walkthrough into a product video that looks good. This tells you *what*
to author, not how to transport it.

**Drive the primitives over MCP if you can call tools** (`new_composition` /
`apply_composition` / `validate_composition` / `create_render` — see the
`cueframe-connect` skill for the one-line setup). The `npx -y cueframe@0.12 …` commands
written out below are the same operations for a terminal or CI job with no MCP
host; see the `cueframe-cli` skill.

## The pipeline

```
capture (video + cursor/click points)  →  auto-zoom (points → reframe)
   →  compose (video track + per-clip reframe)  →  polish (overlay primitives)
   →  render
```

## 1. Capture → timed focus points

Get a screen recording **plus** the cursor/click events with viewport
coordinates and timestamps (e.g. from a browser-automation capture). Normalize
every point to `{ t: seconds, x: 0..1, y: 0..1 }` against the **real captured
viewport** — these are the *focus points* the zoom follows. Measure the rendered
video's true duration (ffprobe) and map point times onto it.

## 2. Points → reframe (auto-zoom)

The framework owns the tuning. Canonical implementation:
`autoZoom(points, style)` in `@cueframe/composition` (timed focus points →
gapless `reframe` segments; never re-derive this with an LLM — it drifts). Pick a
**style**, never raw numbers:

| style | zoom (`<1` punches in) | feel |
|---|---|---|
| `subtle`   | 0.80 | gentle, corporate |
| `standard` | 0.67 | default |
| `punchy`   | 0.55 | snappy, social |

The tiling rule (what `autoZoom` does — use this until it's exposed as
`cueframe compose from-points`): sort points by `t`; group points within
`mergeGap`s; pad each group `prePad` before / `postPad` after; drop groups
shorter than `minZoom`; merge overlapping windows; emit `frame-center` zoom 1
in the gaps and a `point` punch-in (`focus:{mode:"point",x,y}`, `zoom` = the
style's) over each window. Result → `source.reframe.segments` on the clip.

## 3. Compose

One video track, the screen recording as a media clip carrying the reframe.
`npx -y cueframe@0.12 composition put <projectId> -b @composition.json --if-match <etag>`, with the
ETag from `composition get` (`--create` for the project's first composition; see `cueframe-cli`).
Choose `-a 16:9` for landscape product video, `9:16` for social.

## 4. Polish — layer overlay primitives (this is what makes it look "produced")

A bare auto-zoom reads as a raw screen-grab. Add overlay/effect clips referencing
registered primitives (`registry/params-required.json` lists each one's params;
`$brand:` tokens bind brand colors/fonts at render). Tasteful default set for a
product demo:

| Goal | primitiveId | kind |
|---|---|---|
| animated cursor tracing the click path | `cursor-flow` / `simulated-cursor` | overlay |
| title / context | `lower-third` or `heroText` | overlay |
| highlight a clicked element | `marker-highlight` / `pulsing-indicator` | overlay |
| device/browser frame | `device-mockup-zoom` / `browser-flow` | overlay |
| captions (if narrated) | the top-level `captions` field | — |
| finish/look | `color-grade` + `vignette` | effect |
| several cells sharing space that should reflow (feature grid, rail + fluid content) | author one card or native component laid out with CSS flex/grid (see `cueframe-component-authoring`) | overlay (authored) |

Static PiP / split-screen is `region` + `fit` on the clips (EX3 / EX4). Cells that must
**reflow together** or hold mixed content are one authored card or native component laid out
with CSS flex/grid.

A primitive is the `source` of a clip; the clip wraps it with `id`/`startTime`/`duration`:
- Overlay clip (on a `kind:"overlay"` track): `{ "id":"t1", "startTime":1, "duration":3, "source":{ "kind":"overlay", "primitiveId":"lower-third", "params":{…}, "zPlane":"front" } }`.
- Effect clip (on a `kind:"effect"` track): `{ "id":"e1", "startTime":0, "duration":9, "source":{ "kind":"effect", "primitiveId":"color-grade", "params":{…} } }`.
Simultaneous overlays go on **separate tracks** — clips on one track can't overlap in time.
**Don't over-decorate** — 2–4 primitives. Cursor + title + grade is usually enough.

## 5. Render

First use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md):
check framing with `preview_frame` and click/zoom timing with an affected-window `preview_clip`.
For a small revision, verify that change and relevant regressions without exporting the whole film.
When delivering the finished video:

`npx -y cueframe@0.12 render <projectId> -o out.mp4 --json`. Verify the output (ffprobe +
sample frames) before declaring done.

## Worked examples — composition JSON

These are **orientation, not the contract.** The live wire schema is
`npx -y cueframe@0.12 schema composition`, and the way to know a draft is correct is
`npx -y cueframe@0.12 composition validate -b @composition.json` — it runs the same
validator the server enforces, with no save and no render. Discover + validate
before you render; never spend a render to find a schema mistake.

Each block below is a complete `@composition.json` (the bare object `composition put`
accepts: top-level `v`, `format`, `tracks`, optional `captions`). All five validate
against the real wire schema + save invariants (swap the `<…MediaId>` placeholders for
real `npx -y cueframe@0.12 upload` ids). Conventions that keep them valid:

- Tracks hold **`contents`** (not `clips`); each clip wraps a `source`.
- A clip's `source.kind` must match the track `kind`: `media` → `video`/`image`/`audio`
  tracks, `overlay` → `overlay` tracks, `effect` → `effect` tracks.
- Clip/segment times are **seconds** (`startTime`, `duration`, `startSec`, `endSec`,
  `trim`); caption word times are **milliseconds** (`startMs`/`endMs`).
- `region`/`fit` are **clip-level** (siblings of `source`); `reframe` lives on the media `source`.
- Clips on one track can't overlap — put simultaneous layers on **separate tracks**.
- `zoom < 1` punches in (range `[0.1, 1]`, default `1`). Durations are illustrative — match your source.

### EX1 · Auto-zoom screen demo (16:9)
One screen recording with `reframe` punch-ins (the `autoZoom` output: `frame-center` in the gaps, `point` over each click) + a cinematic grade.

```json
{
  "v": 1,
  "format": { "aspectRatio": "16:9", "fps": 30 },
  "tracks": [
    {
      "id": "v-screen", "kind": "video", "contents": [
        {
          "id": "rec", "startTime": 0, "duration": 12,
          "source": {
            "kind": "media", "mediaId": "<mediaId>",
            "reframe": { "segments": [
              { "startSec": 0,  "endSec": 2,  "focus": { "mode": "frame-center" }, "zoom": 1 },
              { "startSec": 2,  "endSec": 5,  "focus": { "mode": "point", "x": 0.28, "y": 0.42 }, "zoom": 0.6,  "ease": { "in": 0.4, "out": 0.4 } },
              { "startSec": 5,  "endSec": 7,  "focus": { "mode": "frame-center" }, "zoom": 1, "ease": { "in": 0.4, "out": 0.4 } },
              { "startSec": 7,  "endSec": 10, "focus": { "mode": "point", "x": 0.72, "y": 0.66 }, "zoom": 0.55, "ease": { "in": 0.4, "out": 0.4 } },
              { "startSec": 10, "endSec": 12, "focus": { "mode": "frame-center" }, "zoom": 1, "ease": { "in": 0.4, "out": 0.4 } }
            ] }
          }
        }
      ]
    },
    {
      "id": "fx", "kind": "effect", "contents": [
        { "id": "grade", "startTime": 0, "duration": 12, "source": { "kind": "effect", "primitiveId": "color-grade", "params": { "preset": "cinematic" } } }
      ]
    }
  ]
}
```

### EX2 · Social vertical with captions (9:16)
Reframe + a `lower-third` title, then a `cursor-flow` overlay (non-overlapping on one overlay track), transcript `captions` (ms timing), warm grade. `$brand:` refs bind brand colors/fonts at render.

```json
{
  "v": 1,
  "format": { "aspectRatio": "9:16", "fps": 30, "platform": "tiktok" },
  "tracks": [
    {
      "id": "v", "kind": "video", "contents": [
        {
          "id": "rec", "startTime": 0, "duration": 10,
          "source": {
            "kind": "media", "mediaId": "<mediaId>",
            "reframe": { "segments": [
              { "startSec": 0, "endSec": 4,  "focus": { "mode": "point", "x": 0.3,  "y": 0.4 },  "zoom": 0.7,  "ease": { "in": 0.4, "out": 0.4 } },
              { "startSec": 4, "endSec": 10, "focus": { "mode": "point", "x": 0.62, "y": 0.55 }, "zoom": 0.62, "ease": { "in": 0.4, "out": 0.4 } }
            ] }
          }
        }
      ]
    },
    {
      "id": "ov", "kind": "overlay", "contents": [
        {
          "id": "title", "startTime": 0, "duration": 3.5,
          "source": {
            "kind": "overlay", "primitiveId": "lower-third",
            "params": {
              "text": "AI video, one command", "subtitle": "cueframe", "variant": "modern",
              "tokens": { "textColor": "$brand:colors.textOnMedia", "accentColor": "$brand:colors.accent", "fontFamily": "$brand:fonts.heading.family" }
            }
          }
        },
        {
          "id": "cursor", "startTime": 3.5, "duration": 6,
          "source": {
            "kind": "overlay", "primitiveId": "cursor-flow",
            "params": {
              "waypoints": [ { "x": 200, "y": 180 }, { "x": 540, "y": 240, "click": true, "label": "Generate" }, { "x": 1040, "y": 520, "click": true, "label": "Publish" } ],
              "cursorColor": "$brand:colors.text", "showTargets": true
            }
          }
        }
      ]
    },
    {
      "id": "fx", "kind": "effect", "contents": [
        { "id": "grade", "startTime": 0, "duration": 10, "source": { "kind": "effect", "primitiveId": "color-grade", "params": { "preset": "warm" } } }
      ]
    }
  ],
  "captions": {
    "segments": [
      { "words": [
        { "text": "Watch",   "startMs": 0,    "endMs": 320 },
        { "text": "this",    "startMs": 320,  "endMs": 560, "emphasis": true },
        { "text": "render",  "startMs": 560,  "endMs": 980 },
        { "text": "in",      "startMs": 980,  "endMs": 1120 },
        { "text": "one",     "startMs": 1120, "endMs": 1360, "emphasis": true },
        { "text": "command", "startMs": 1360, "endMs": 1900 }
      ] }
    ],
    "style": { "fontFamily": "Inter", "fontSize": 6.5, "fontWeight": 900, "color": "#ffffff", "highlightColor": "#10B981", "position": "bottom", "textTransform": "uppercase" }
  }
}
```

### EX3 · Picture-in-picture (16:9)
Full-frame screen recording + a webcam **inset** placed with `region`/`fit` on a second video track (composites on top by track order). Two uploads → two `mediaId`s.

```json
{
  "v": 1,
  "format": { "aspectRatio": "16:9", "fps": 30 },
  "tracks": [
    { "id": "v-screen", "kind": "video", "contents": [
      { "id": "screen", "startTime": 0, "duration": 10, "source": { "kind": "media", "mediaId": "<screenMediaId>" } }
    ] },
    { "id": "v-cam", "kind": "video", "contents": [
      { "id": "cam", "startTime": 0, "duration": 10, "source": { "kind": "media", "mediaId": "<webcamMediaId>" }, "region": { "x": 0.68, "y": 0.04, "w": 0.3, "h": 0.3 }, "fit": "cover" }
    ] }
  ]
}
```

### EX4 · Split-screen (16:9)
Two sources side-by-side, each with a half-frame `region` on its own video track.

```json
{
  "v": 1,
  "format": { "aspectRatio": "16:9", "fps": 30 },
  "tracks": [
    { "id": "v-left", "kind": "video", "contents": [
      { "id": "left", "startTime": 0, "duration": 8, "source": { "kind": "media", "mediaId": "<leftMediaId>" }, "region": { "x": 0, "y": 0, "w": 0.5, "h": 1 }, "fit": "cover" }
    ] },
    { "id": "v-right", "kind": "video", "contents": [
      { "id": "right", "startTime": 0, "duration": 8, "source": { "kind": "media", "mediaId": "<rightMediaId>" }, "region": { "x": 0.5, "y": 0, "w": 0.5, "h": 1 }, "fit": "cover" }
    ] }
  ]
}
```

### EX5 · Presenter intro — title behind the speaker (9:16)
Talking-head with an `active-speaker` reframe and a `heroText` title at `zPlane:"behind-subject"`. The speaker **detection** and the person **matte** are both resolved automatically at render (see the `cueframe-cli` skill's "Render resolves expensive intents" section) — author the intent, render, done.

```json
{
  "v": 1,
  "format": { "aspectRatio": "9:16", "fps": 30 },
  "tracks": [
    { "id": "v", "kind": "video", "contents": [
      { "id": "cam", "startTime": 0, "duration": 6, "source": { "kind": "media", "mediaId": "<mediaId>", "reframe": { "segments": [ { "startSec": 0, "endSec": 6, "focus": { "mode": "active-speaker" }, "zoom": 0.8 } ] } } }
    ] },
    { "id": "ov", "kind": "overlay", "contents": [
      { "id": "hero", "startTime": 0.5, "duration": 5, "source": {
        "kind": "overlay", "primitiveId": "heroText",
        "params": { "text": "SHIP IN MINUTES", "fontSizePct": 14, "textColor": "$brand:colors.textOnMedia", "fontFamily": "$brand:fonts.heading.family" },
        "zPlane": "behind-subject", "anchor": { "space": "scene", "x": 0.5, "y": 0.42 }
      } }
    ] }
  ]
}
```

## Notes / honesty

- **Picture-in-picture / inset cards render** — per-clip output-space placement
  (`region:{x,y,w,h}` in `[0,1]` + `fit`) is wired for PiP / inset / split-screen,
  for video, image, and overlay clips. Set `region`/`fit` on the **clip** (siblings
  of `source`, not inside it — as an agent, patch them with an `apply_composition`
  `clip.update` op: `{ type: 'clip.update', clipId, patch: { region, fit } }`); two
  clips with different placement composite by track order instead of occluding the
  background. See EX3 / EX4 below.
- This recipe lives in a skill on purpose: the engine stays use-case-free; the
  product opinions (style, which primitives, layout) live here and ship via
  `npx -y cueframe@0.12 install`. Add sibling recipes (`cueframe-podcast-clip`, …) the same way.

Files in this skill

  • SKILL.md15.3 KB
  • agents/openai.yaml577 B
  • assets/icon.svg1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in ai-agents →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.