Skip to content

feat: animation inspection, burst capture, and screencast commands#1224

Open
Gablas wants to merge 6 commits intovercel-labs:mainfrom
Spiich:feat/animation-inspection
Open

feat: animation inspection, burst capture, and screencast commands#1224
Gablas wants to merge 6 commits intovercel-labs:mainfrom
Spiich:feat/animation-inspection

Conversation

@Gablas
Copy link
Copy Markdown

@Gablas Gablas commented Apr 12, 2026

Closes #1223

What this does

Adds commands for inspecting and capturing browser animations. More context in the linked issue, but the short version: agents couldn't see animations before, now they can.

Three things:

  1. Animation inspection - animation list/pause/resume/scrub/audit commands that use the Web Animations API to query and control animations
  2. Burst capture - screenshot --burst N --interval Ms --gif path for multi-frame capture with optional GIF encoding
  3. Screencast - screencast <duration_ms> --gif path using CDP's native Page.startScreencast for efficient frame streaming

No new dependencies. GIF encoding uses the image crate that's already in Cargo.toml.

New commands

Command What it does
animation list Lists all running CSS/JS animations with timing, keyframes, and target info
animation pause [index] Pauses all or a specific animation
animation resume [index] Resumes playback
animation scrub <0.0-1.0> [index] Scrubs to a specific progress point
animation audit Checks for layout-triggering properties, missing reduced-motion support
screenshot --burst 10 --interval 200 --gif out.gif Captures N frames at interval, optionally makes a GIF
screencast 3000 --gif out.gif Streams frames via CDP screencast for a duration, optionally makes a GIF

Testing

  • All 624 existing tests pass, 0 failures
  • Unit tests for GIF encoding (rejects empty frames, produces valid output)
  • Tested animation list on animate.style, returns CSS animation with full keyframes
  • Tested animation audit, correctly flags perf-good properties and reduced-motion handling
  • Tested screencast 5000 --gif on a real app, captured 352 frames of a streaming chat response

Happy to adjust anything based on your prefferences. First time contributing here so let me know if I missed something.

New commands for inspecting and capturing browser animations:

- `animation list` — query all running animations via Web Animations API
- `animation pause/resume [index]` — control animation playback
- `animation scrub <0.0-1.0> [index]` — scrub to specific progress
- `animation audit` — performance/a11y audit (layout triggers, reduced motion)
- `screenshot --burst N --interval Ms [--gif path]` — multi-frame capture
- `screencast <duration_ms> [--gif path]` — CDP Page.startScreencast streaming

GIF encoding uses the `image` crate (already a dependency). Screencast
achieves ~25fps via native CDP frame streaming, vs ~5fps with polling.
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 12, 2026

Someone is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

Gabriel Stenbäck added 5 commits April 12, 2026 17:40
Adds start/stop mode to screencast that records frames in the background
while logging every command that runs during the recording:

  agent-browser screencast start
  agent-browser click @E5
  agent-browser fill @e10 "hello"
  agent-browser screencast stop ./output --gif recording.gif

The stop output includes a timeline mapping each action to the nearest
captured frame by timestamp, so you can see exactly which frame
corresponds to each interaction.

Uses a background tokio task with its own CDP event subscriber for
continuous frame collection independent of command processing.
CDP's Page.startScreencast only sends frames when the screen changes,
so recordings during sleep/idle periods between commands had almost no
frames. Added a 250ms polling fallback using Page.captureScreenshot
that kicks in when no screencast frames arrive, ensuring continuous
frame coverage even on static pages.
screencast.rs:
- Replace abort+sleep with cooperative shutdown via oneshot channel
- Pass user's format/quality into background collector (was hardcoded jpeg/80)
- Fix Lagged broadcast error in screencast_capture (was breaking loop early)
- Propagate file write errors instead of silently swallowing with .is_ok()
- Log Page.stopScreencast cleanup failures instead of discarding
- Log ACK failures and base64 decode errors in background collector
- Use Option<String> for TimelineEntry.action instead of empty string sentinel
- Extract save_recording_output to reduce ScreencastRecording unit size

animation.rs:
- Detect JS-returned { error: "..." } objects in eval_and_return and
  convert to Err (was silently returned as Ok, bypassing error handling)
- Add keyframeError field to list output when getKeyframes() throws
- Add comments to catch blocks explaining why errors are expected

commands.rs:
- Validate --burst flag has a valid positive integer (was silently defaulting)
Timeline entries now capture action-specific metadata:
- navigate: url
- scroll: direction
- wait: duration
- press: key
- click/fill: selector, value (already worked)

Browser close during active recording no longer loses frames.
The close handler auto-saves collected frames to the default
screencast output directory before shutting down.

Also made screencast stop work even after browser close by not
requiring an active browser connection to save the recording.
… GIFs

screencast start now accepts --fps N and --quality N flags.
Default changed from ~4fps/q80 to 2fps/q60, producing ~18x smaller GIFs
(485KB vs 9MB for a 5-second recording).

Examples:
  screencast start                    # 2fps, jpeg quality 60
  screencast start --fps 1 --quality 30  # low bandwidth
  screencast start --fps 10           # high framerate for animation capture
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature idea: animation inspection + capture commands

1 participant