Skip to content
Back to skills

Teaser Video

ASecurity

Film, edit, and deliver a launch-quality teaser of any web app - real footage captured at 2x with Playwright + CDP (and Windows Graphics Capture for external windows such as an agent's browser), edited in Remotion with a virtual camera, motion graphics, kinetic type, and a synthesized license-free soundtrack. Use for "make a teaser", "record a demo video", "product launch video", "screen recording for the README".

  • 80 stars
  • 0 votes
  • 0 copies
  • 7 views
  • Added August 31, 2026
ai-agentsrustgobashreactnodegitsecurity

Works with

  • cursor
  • terminal
  • cli

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

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

Scanned October 5, 2026

npx -y skills add suxrobGM/jobpilot --skill teaser-video --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Teaser Video?

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

Security grade badge for Teaser Video
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/suxrobgm-teaser-video/badge)](https://www.skillsdirectory.com/skills/suxrobgm-teaser-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: teaser-video
description: Film, edit, and deliver a launch-quality teaser of any web app - real footage captured at 2x with Playwright + CDP (and Windows Graphics Capture for external windows such as an agent's browser), edited in Remotion with a virtual camera, motion graphics, kinetic type, and a synthesized license-free soundtrack. Use for "make a teaser", "record a demo video", "product launch video", "screen recording for the README".
user-invocable: true
compatibility: Node 24+, ffmpeg 8+ on PATH (gfxcapture + h264_nvenc on Windows; swap `ENCODER` in cam.js elsewhere), and a Chrome channel for Playwright. npm packages come from reference/capture and reference/edit package.json, installed in a scratch dir, never the project.
metadata:
  version: "1.1"
  updated: "2026-10-04"
  portable: "true"
---

# Teaser video

A ~40s teaser that looks like a product film, not a screen recording. The
difference is direction: one story, real proof, a camera that moves with
intent, graphics that explain cause and effect, and sound cut to a beat.

Pipeline: **capture** real footage (Playwright drives, CDP films at 2x) →
**edit** in Remotion (React components rendered frame by frame) → **review**
every frame for PII → deliver MP4 + poster + README GIF.

Work in a scratch directory, never in the project:

```bash
cp -r <skill>/reference/capture "$SCRATCH/film" && (cd "$SCRATCH/film" && npm install)
cp -r <skill>/reference/edit "$SCRATCH/edit" && (cd "$SCRATCH/edit" && npm install && npm run synth && npm run still)
export TEASER_BASE_URL="https://the-app.example.com"
export TEASER_LOCAL_STORAGE='{"some:ui-pref":"value"}'   # optional UI state to pin
```

`npm run still` renders the starter `Teaser.tsx` (no clips needed), proving the
toolchain works before any filming. Keep every `remotion` / `@remotion/*`
package on the same version; mismatches fail at render time.

## The two hard rules

**1. Real side effects need explicit, itemized consent.** Filming a real app
clicks real buttons: applications get submitted, emails sent, accounts
touched. Agree the scope with the user before rolling. Answer the app's own
prompts only within that scope; anything that creates accounts, picks a
sign-in method, or answers personal questions (tax, demographics) stays parked
for the user. Before stopping a long-running process, let the in-flight unit of
work finish instead of cutting it mid-way. Report every outcome, including
failures and anything the product did on its own (password resets, etc.).

**2. Every frame is public.** Agree what may show (e.g. name + email) and treat
everything else as private: phone numbers, other people's names (chat
bubbles), security answers, tokens. Hide by framing, by masking in the edit,
or by not filming that part of the page. Dashboards can quote secrets
verbatim (a "failure reasons" list once showed a security-question answer) -
read every captured screen, not just the part you meant to film.

## 1. Scout and storyboard

Screenshot every candidate screen with the saved session. Write the
storyboard on the music grid (120 BPM → 1 bar = 2s = 120 frames at 60fps),
then put the section lengths in `reference/edit/storyboard.json`. `theme.ts`
(`SECTIONS`) and `audio/synth.mjs` both read it, so retiming a section moves
the cuts and the music together:

| Beat | Length | Job |
| --- | --- | --- |
| Hook | 2 bars | The pain, as a pure motion graphic (no UI yet) |
| Reveal | 1 bar | Logo on the impact |
| Start | 4 bars | The one action the user takes |
| Hero | 5 bars | The product doing the thing, split-screen if two surfaces |
| Payoff | 5 bars | Results landing in the app (counters, lists, charts) |
| Trust | 3 bars | Control and where it runs |
| Close | 2 bars | Logo, URL, CTA |

The hero is the reason the video exists. Show cause and effect: the agent acts
in one pane, the result appears in another, and a graphic (a chip flying from
the success state into the counter) connects them.

## 2. Capture

- `login.js`: headed login once, saves `storageState.json`. In Git Bash set
  `MSYS_NO_PATHCONV=1` or path args like `/login` become Windows paths.
- `cam.js`: choreographed takes, and the shared kit `login.js`/`live.js` build
  on (`BASE`, `AUTH_PATHS`, `ENCODER`: swap to libx264 there without NVIDIA). `open()`, `roll()` (CDP screencast piped into
  ffmpeg with wall-clock timestamps), `click()`/`glide()` with an injected
  cursor, `scrollTo()`/`scrollToEl()` on the app's inner scroll container.
  Pass `ready` (a selector for the content the shot needs) to `open()`/`go()`
  so takes start on loaded UI instead of after a guessed sleep.
- `live.js`: long unattended takes of a real run. Films the page, auto-detects
  the agent's own Chrome window and records it with `gfxcapture` (works while
  covered by other windows, not while minimized), and logs status changes
  with timestamps so you can find the moments afterwards. Stop it by touching
  `takes/<name>/STOP`.

Film at **1600x900 CSS with `--force-device-scale-factor=2`** (3200x1800
frames). Without the flag, headless screencast silently returns 1x frames even
with `deviceScaleFactor: 2`. 2x is what lets the edit push in on a number or a
terminal line and stay sharp. Always check `ffprobe` width after the first take.

## 3. Prepare clips

Captures are variable-frame-rate (frames only arrive on repaint) and window
captures start at a non-zero timestamp with long gaps while nothing changes.
Normalize every clip before Remotion sees it:

```bash
ffmpeg -i take.mkv -vf "setpts=PTS-STARTPTS,crop=W:H:X:Y,fps=60,format=yuv420p" -c:v libx264 -crf 14 -g 30 -an clips/x.mp4
```

`crop` needs even dimensions. Map the clip with a 1-second contact sheet
(`fps=1,scale=200:-1,tile=15x6`) and read times off it. Don't trust `-ss`
seeks on the raw VFR capture.

## 4. Edit (Remotion)

Components in `reference/edit/src/components` (palette, fonts, `BRAND`, `alpha()`
and `clamp` in `src/theme.ts`):

- `Shot.tsx`: `Footage` = footage seen through a virtual camera. Keyframes
  `{f, x, y, z}` in source pixels, eased, zoom interpolated in log space,
  clamped to the footage edge. Overlays passed as children live in source
  pixel space and track the camera. `AppWindow` frames it as a browser.
  There's no ffmpeg `zoompan` anywhere (it quantizes and shakes).
- `Kinetic.tsx` / `Caption.tsx`: word-by-word rise + unblur, `*accent*`
  spans in the brand color, a scrim so text reads over any frame.
- `Overlays.tsx`: `Pulse` (look here), `Spotlight` (dim the rest),
  `FlyingChip` (the result travelling between scenes), `CountUp`, `Callout`.
- `Background.tsx`, `Logo.tsx`, `FormStack.tsx`: stage, logo sting, a sample
  hook graphic.
- `Sound.tsx`: music bed + SFX cues by frame.

Rules that made the difference:

- Copy the app's palette and fonts into `theme.ts`. Use its easing curve for
  every move.
- Speed-ramp real footage per segment (`Sequence` + `startFrom` + `rate`):
  compress the waiting, play the payoff near real time.
- One camera move per shot, motivated by what changes on screen.
- Prefer honest overlays: point at the real number and pop a "+1" instead of
  faking a count-up over the UI.
- Masks for PII must be on from the first frame the data renders. Find that
  frame (`crop` + `signalstats`, or a frame stack), don't guess.
- Render stills (`npx remotion still ... --frame=N`) at every beat and read
  them before any full render.

## 5. Sound

`audio/synth.mjs` renders the music bed and SFX from oscillators and noise, so
everything is license-free by construction. Structure follows the storyboard
bars: ticking intro, riser into an impact on the reveal, groove under the
product, adds an arp for the payoff, breakdown for trust, final impact. Mix
with separate drum/tonal stems, kick sidechain, and a limiter, then check
`ebur128` loudness (aim around -14 LUFS) and the waveform. You can't listen
to it, so say so and invite the user to swap in a track (cuts sit on the bar
grid, so any 120 BPM track drops in).

The video must also work muted: captions carry the story.

## 6. Review and deliver

- Render: `npm run render` (h264 + AAC into `out/teaser.mp4`).
- Full-resolution frames at 2fps for the PII read, plus a contact sheet.
- Poster: a frame that explains the product without motion (usually the hero
  split).
- README GIF: GitHub won't inline a committed MP4. Encode from the clean MP4,
  aim for 3-4 MB. Bayer dither + `diff_mode=rectangle` keeps static UI identical
  between frames; error-diffusion dither on moving footage bloats the file:
  `ffmpeg -i out/teaser.mp4 -vf "fps=10,scale=720:-1:flags=lanczos,split[a][b];[a]palettegen=max_colors=128:stats_mode=diff[p];[b][p]paletteuse=dither=bayer:bayer_scale=4:diff_mode=rectangle" teaser.gif`
- Update any page copy that states the duration or "no sound".

Report the outputs, what really happened during filming (applications sent,
failures, items left for the user), and what still needs a human (listening to
the mix).

Files in this skill

  • SKILL.md8.3 KB
  • reference/build.js5.4 KB
  • reference/cards.js5.8 KB
  • reference/jitter.js2.3 KB
  • reference/login.js1.8 KB
  • reference/package.json478 B
  • reference/rig.js10.7 KB
  • reference/scout.js1.1 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.

Comments

Loading comments…

Newsletter

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