npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

kenburnz

v0.0.1

Published

TypeScript port of the burns BurnsPath motion spec — pure evaluate(t) + cover-crop geometry, WebCodecs export, and CSS preview. Conforms to the cross-language golden vectors.

Readme

kenburnz

A TypeScript port of the burns Ken Burns motion spec: a pure, time-parameterized BurnsPath.evaluate(t) → Rect plus the cover-crop pixel geometry (sampleBox), a WebCodecs video exporter, and a zero-cost CSS preview for the browser. The spec math is pinned bit-for-bit to the Python renderer by a shared golden-vector fixture, so a path rendered in Node/Python and previewed/exported in the browser frame the identical window.

npm install kenburnz

Quick start

import { BurnsPath, sampleBox, cssPreviewAt, exportWebmBlob } from 'kenburnz';

// A 2-second-ish push-in to 1.3×, centered, ease-in-out.
const path = BurnsPath.pushIn({ zoom: 1.3 });

// Pure spec: the normalized viewport at clock time t ∈ [0, 1].
path.evaluate(0.5); // → Rect { x, y, w, h }

// The exact integer crop box (x0, y0, x1, y1) a renderer reads from the image.
sampleBox(path, 0.5, imgW, imgH, outW, outH);

Live CSS preview (no re-rasterizing)

cssPreviewAt turns evaluate(t) into a GPU-friendly CSS transform on an <img>, so a preview scrubs with transform alone:

const css = cssPreviewAt(path, t, { imageAspect: 16 / 9, outputAspect: 1 });
img.style.width = css.width;            // e.g. "153.8462%"
img.style.height = css.height;
img.style.transform = css.transform;    // e.g. "translate(-26.92%, -0.00%)"
img.style.transformOrigin = css.transformOrigin;

See cssPreviewAt's docs for the expected .kb-viewport / .kb-img DOM.

Export to video (browser, WebCodecs)

The encoder draws each frame's sampleBox crop onto an OffscreenCanvas and hands it to a VideoEncoder. The core stays muxer-free and streams raw chunks; the optional exportWebmBlob helper produces a playable .webm:

import { exportWebmBlob, isWebCodecsSupported } from 'kenburnz';

if (isWebCodecsSupported()) {
  const { blob } = await exportWebmBlob(imageBitmap, path, {
    duration: 3,
    fps: 30,
  });
  videoEl.src = URL.createObjectURL(blob); // VP9 in WebM
}

exportWebmBlob / createWebmMuxer require the optional peer dependency webm-muxer:

npm install webm-muxer

If you'd rather mux elsewhere (a different library, or server-side), use the lower-level exportWebCodecsVideo directly — it takes no muxer dependency and streams every EncodedVideoChunk to your onChunk callback. (webm-muxer is soft-deprecated upstream in favor of Mediabunny; the helper's chunk-stream interface makes swapping muxers a local change.)

Development

This package lives co-located in the burns Python repo under ts/ so the single golden-vector fixture (../tests/golden/vectors.json) can't drift between the two languages.

pnpm install
pnpm test         # vitest — pure spec + conformance, offline
pnpm build        # tsup → dist/ (ESM + CJS + d.ts)
pnpm typecheck    # tsc --noEmit

Browser verification (local-only)

The CSS preview and WebCodecs encode path only run in a real browser, so they're verified against Python reference renders rather than in Node:

cd demo && pnpm dev     # side-by-side CSS preview vs Python frames + live export
pnpm test:e2e           # headed Playwright: pixel-diff the browser vs Python

Both regenerate the reference frames via the repo's misc/gen_preview_reference.py (needs the burns Python package importable), which is why the e2e suite is local-only and not in CI.

Publishing

npm releases go through wads's reusable NPM CI (.github/workflows/npm-ci.ymli2mint/wads/.github/workflows/npm-ci.yml), configured by the wads.ci block in package.json. Publishing is opt-in: bump the version, then push to main with [publish-npm] in the commit message. It uses OIDC trusted publishing + provenance (configure the trusted publisher on the npm package page once; NPM_TOKEN is only a first-publish fallback) and a version-already-published guard. kenburnz is a pnpm package, so the workflow runs the pnpm path.

License

MIT