Skip to content
Back to skills

screenstudio-alt

ASecurity

Screen-Studio-style post-production for screen recordings, headless — auto speed-up of idle, auto-zoom on click clusters, keystroke overlay chips, smoothed synthetic cursor, and 9:16 vertical export that follows the action. Use when polishing a screen recording / demo video for sharing, when the user mentions Screen Studio, auto-zoom, idle speed-up, or vertical/social video from a screen capture, and for any social-facing demo (vertical output is the default for those).

  • 8 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added August 30, 2026
ai-agentspythonrustgoswiftbashspring

Works with

  • cursor
  • terminal
  • cli

Security analysis

A100/100

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

Scanned August 30, 2026

npx -y skills add connerkward/screenstudio-alt-skill --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of screenstudio-alt?

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

Security grade badge for screenstudio-alt
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/connerkward-screenstudio-alt/badge)](https://www.skillsdirectory.com/skills/connerkward-screenstudio-alt)

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: screenstudio-alt
description: Screen-Studio-style post-production for screen recordings, headless — auto speed-up of idle, auto-zoom on click clusters, keystroke overlay chips, smoothed synthetic cursor, and 9:16 vertical export that follows the action. Use when polishing a screen recording / demo video for sharing, when the user mentions Screen Studio, auto-zoom, idle speed-up, or vertical/social video from a screen capture, and for any social-facing demo (vertical output is the default for those).
author: Conner K Ward
---

# screenstudio-alt

The skill's code lives in this directory (`polish.py`, `render.py`, `studio.py`,
`events-log.swift`, test fixtures, etc.). Published publicly as
`connerkward/screenstudio-alternative-skill`.

Two components:

- `events-log` (Swift) — capture-side input logger (cursor 60Hz, clicks, keys;
  drops keys during macOS secure input). Runs ONLY while recording. Needs
  Accessibility/Input Monitoring for the terminal. **Auto-zoom/keys/cursor need
  this data at capture time — it cannot be recovered from pixels later.**
- `polish.py` (Python, ffmpeg + PIL) — the post-production pass:

```bash
python3 src/polish.py in.mp4 --events in.events.jsonl \
  --speedup            # compress idle (input-gap ∩ frozen-pixels; animations stay 1x)
  --zoom               # eased auto-zoom on click clusters (zoompan)
  --keys               # accumulating keystroke chips (PIL overlays, no drawtext dep)
  --smooth-cursor      # synthetic eased cursor (best with sck-record --no-cursor)
  --vertical           # ALSO emit 1080x1920 following the action
```

`--speedup` works WITHOUT events (freezedetect only) — usable on the whole
existing dailies corpus.

- `render.py` — **high-quality non-destructive renderer** (preferred): single-pass
  spring-physics camera over the original high-res frames, LANCZOS into a smaller
  target (crisp zoom, ~1.3× sharper than the ffmpeg upscale path), 60fps, H + 9:16 V.
  Tunable `--freq`/`--zeta` (spring), `--fps`, `--target-w`. Takes explicit
  `--regions [{t0,t1,z,cx,cy}]` — plus optional `cx1,cy1,z1` end-keyframe per region:
  when present the camera **pans** (eases start→end across the held span, `ease_traj`).
  `polish.py` is the older ffmpeg-filter fallback.
- `studio.py [recording.mp4]` — local web UI, **NLE-style fixed-ruler timeline** (bar =
  source duration, never rescales → upstream always planted): zoom regions are draggable
  blocks (move / retime edges / click to add / double-click delete). Selecting a zoom
  shows a **draggable crop-rect overlay on the preview** (reframe where the zoom looks:
  drag body = move cx/cy, corner handle = zoom level). **+ pan** adds a second END
  keyframe → a two-keyframe camera move: start rect (solid) + end rect (dashed) + a path
  arrow on the preview, a `[ Start | End ]` toggle picks which the drag edits, and
  scrubbing interpolates the pan live (same `ease_traj` as the export). Idle spans are
  **speed blocks with rate-only editing** — source range locked, rate set via inspector
  slider on select or right-edge **rate-stretch** drag (FCP retime / Premiere Rate
  Stretch); rate changes ripple downstream only. Camera easing is **smootherstep
  ease-in-out by default** (full ease, no constant-velocity middle — cinematic
  slow-start/smooth-middle/gentle-stop on zoom AND pan); Advanced section exposes an
  **easing curve** selector (Smooth · Snappy · Linear) + smoothness/ramp slider
  (`--curve`/`--ramp`, persisted in session.json, preview == export). Tunable default zoom,
  aspect, frame styling. Always-smooth synthetic cursor + click ripple + real recorded
  click sound (CC0 #735771). Export uses render.py. Free port, local. (Keystroke overlay
  exists in the engine but is off by default.)

## Easy path

`screencast.sh --demo` (screencast skill) does the whole chain: starts the event
logger, records, then polishes + emits the 9:16 vertical automatically. Vertical
is the DEFAULT for social-facing demos.

## Gotchas (learned the hard way, kept here so they're not relearned)

- ffmpeg CANNOT do animated `scale=eval=frame` → `crop` (link reinit wedges crop's
  per-frame exprs). That's why zoom uses `zoompan` (no `t` var there — use `on/FPS`).
- This machine's ffmpeg lacks `drawtext`; all text/cursor overlays are PIL-rendered
  PNGs + `overlay`.
- Test rig: `make-fixture.py` synthesizes a fake screen recording + ground-truth
  events.jsonl — validate any change against it before trusting real footage.
- Do NOT use Playwright `recordVideo` to capture the studio demo — its VFR→CFR
  conversion judders on the auto-zoom (a frozen frame wedged mid-motion); use
  `test/record-demo.js` instead.

## Recording the demo

- `test/record-demo.js` is the canonical smooth demo recorder: it steps the studio's
  logical timeline frame-by-frame against the live page (not `recordVideo`), so every
  output frame is captured exactly once → perfect CFR, no judder. See
  [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for mechanism + usage.

## Text callouts / keystroke chips — NEVER overlap or crowd

Callouts are read one at a time. **Two text callouts must never overlap in output time, and
must not be closely spaced** — only one on screen at a time, with a clear gap (~0.3s+) between
them so each is legible before the next appears. Rules:

- **Anchor callouts CLEAR of the content they describe** — don't park them on top of the search
  bar, nav, or the result/image being shown. A callout covering the thing it points at is worse
  than none.
- **On long enough to read** — ≥~1s of *output* time at the playback rate. Over a sped-up span,
  **extend the callout's window** so it survives the compression (a callout inside a 5× block is
  gone in a blink otherwise).
- Time the callout to **lead or coincide with** the moment it labels, never trail it.

(Burn 2026-06-18: five callouts set with overlapping windows, sitting on top of the results, too
brief over a sped-up idle — read as clutter; the features didn't register.)

## Get an objective critique — send the rendered demo to a VIDEO model (don't iterate blind)

Before handing a demo over, **stop judging it from stills — send the actual rendered mp4 to a
video-understanding model and act on its critique.** Repeatedly, demos shipped with broken
framing/pacing/loop because they were judged frame-by-frame, not as motion. Standing practice:

1. Render the cut (`render.py`).
2. **Pick the model dynamically — do NOT hardcode one.** At this moment, list the current
   video-understanding (video-to-text) models with `fal search_models category="video-to-text"`
   (use this, NOT `recommend_model` — that one is popularity-ranked and returns video *generators*
   for a "video" task), look at what's actually available right now, and choose the
   strongest one for *this* job (a critique needs temporal/motion reasoning, so prefer a
   reasoning-capable VLM; e.g. `openrouter/router/video` pointed at the latest Gemini, or a
   native reasoning VLM like `nvidia/nemotron-3-nano-omni/video`). The right model changes over
   time — decide from the live list, not from a name written here. **Bias slightly toward SOTA:**
   when options are close, prefer the newest-generation / most-capable model (cost here is pennies,
   so favor capability over the cheap/older pick).
3. Upload the mp4 and run the chosen model with a **harsh-critique `prompt`** that states the
   demo's PURPOSE + the 4 features + the region/speed/callout spec and asks for a **blunt,
   timestamped, prioritized fix list** covering: each zoom's framing (on the right thing? on dead
   UI?), pan smoothness (eased vs hard-cut), speed-up legibility (feature vs glitch), callout
   placement/timing/overlap, overall pacing, and **clean loop (last frame ≈ first)**. A stills-only
   fallback (image VQA on a labeled contact sheet) **cannot judge motion**, so it's a weak
   substitute, not the check.

This loop catches what self-review misses (e.g. Gemini flagged a broken loop + a hard-cut "pan" +
a zoom landing on the Search button, all of which had passed self-inspection). Don't skip it for a
demo that's going public.

Files in this skill

  • .claude-plugin/marketplace.json779 B
  • .claude-plugin/plugin.json733 B
  • SKILL.md8 KB
  • assets/CREDITS.txt198 B
  • assets/click.wav7.8 KB
  • docs/ARCHITECTURE.md10.7 KB
  • docs/logo.svg374 B
  • llms.txt647 B
  • requirements.txt25 B
  • src/events-log.swift10.1 KB
  • src/fcpxml.py30.3 KB
  • src/iteration.py3 KB
  • src/polish.py30.8 KB
  • src/render.py34.9 KB
  • src/sequence.py43.5 KB
  • test/make-fixture.py6.1 KB
  • test/record-demo.js4.3 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.