Video your agent can measure

Cuts, easing, colour and beats from any video, to the frame.

npx -y framelens init
Star on GitHub

Free, local and MIT. Works in Claude Code, Codex, Cursor and any MCP client.

Frame of the Big Buck Bunny trailer at 26.5 seconds
Time
26.50 s, frame 663
Shot
17 of 20, 0.72 s
Change
move, ease-in, 15 frames, cubic-bezier(0.7, 0, 0.84, 0)
Palette
#F9E2D6
The Big Buck Bunny trailer, read by Frame Lens: red cuts, pale fades and dissolves, green moves.

Frame Lens read our curve back within 0.18 px

What we animated in HyperFrames

cubic-bezier(0.22, 1, 0.36, 1)

640 px in 18 frames at 30 fps

Measured curve
cubic-bezier(0.231, 0.951, 0.384, 0.996)
Start
10.600 s, 0 frames off
Largest gap on any frame
0.18 px
Grade
exact

The demo above was rendered, then measured by Frame Lens. A spring of stiffness 170 read back as 170.01.

A podcast gets one sheet, a promo gets every frame

“Use this as a reference for my product promo.”

  1. boundaries every cut, ten samples a second
  2. frames one sheet of the whole piece
  3. frames every frame around each move
  4. style shots, palette, moves and curves
  5. export a starter project, then compare
The style goal’s first pass: a frame a second, red where a cut falls.

Video is measured; Lottie, Rive and websites are read exactly

SourceHowWhat Frame Lens read
The trailer above, a video fileFrom pixels20 shots, 11 cuts, 10 fades and dissolves
A live website, makkov-harnessFrom the browser328 animations, mostly 500 ms on cubic-bezier(0.16, 1, 0.3, 1)
A Lottie file, our export read backFrom keyframesIts keyframes and curves, back exactly
Rive files and Figma prototypesFrom the fileKeyframes and transitions
YouTube and most video sitesFrom pixelsThrough a pinned yt-dlp

The measured move in five renderers

Frame Lens writes the curve it measured into each tool. Render yours, then compare names what drifted.

Measured positions of the square on each frame, on the fitted curve cubic-bezier(0.231, 0.951, 0.384, 0.996)
Dots: where the square was on each frame. Line: the fitted curve.
/* motion.css */
#shot-15 h1 { animation: fl-enter 0.542s
  cubic-bezier(0.2312, 0.9511, 0.3843, 0.9964)
  10.6s both; }

Tested at 24, 30 and 60 fps against known answers

33/33
cuts found on the exact frame
36/36
easing families named right
1.00
frame, the mean error on where a move starts

Synthetic clips with known cuts and curves. Read the benchmark.

Point it at a video tonight

Star on GitHub

Node 20 and ffmpeg on your computer. framelens doctor --prepare checks the rest.

  • This project

    npx -y framelens init

    Adds .mcp.json and the agent skill here.

  • Claude Code, everywhere

    claude mcp add framelens -s user -- npx -y framelens

    On Windows, cmd /c before npx.

  • Any MCP client

    "framelens": {
      "command": "npx",
      "args": ["-y", "framelens"] }