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

@motionvector/webcodecs-census-cdp

v0.3.1

Published

Inject the WebCodecs census into a running Chrome — page, iframes and Web Workers — over the DevTools Protocol.

Readme

@motionvector/webcodecs-census-cdp

npm provenance licence

Instrument a page and every one of its Web Workers, from outside the app, with no change to the code being measured.

Decoders almost always live in a Web Worker. Page-level monkey-patching — how every other web-graphics inspector works — cannot reach a worker the page created. This drives Chrome over the DevTools Protocol instead, and gets the census in before the worker's first line runs.

Install

npm install --save-dev @motionvector/webcodecs-census-cdp

Use

import { attach, launchChrome } from '@motionvector/webcodecs-census-cdp';
import { summarize, checkLeaks } from '@motionvector/webcodecs-census';

const chrome = await launchChrome({ executablePath: CHROME });
const session = await attach({ browserURL: chrome.browserURL });

await session.navigate('http://localhost:5173/');
// …drive the app…

console.log(summarize(await session.census()));

session.detach();
await chrome.kill();
3 context(s): main, worker, worker
  main (21s): nothing live
  worker (20s): VideoDecoder=1 VideoFrame=58

58 VideoFrame still live (allowed 0).

Held by:
  58x VideoFrame (decoded, oldest 124609ms) in worker
      at PackagerWorker.setupDecoder (worker.js:1756:21)
      (frame emitted by this VideoDecoder)

To attach to a browser you already started, pass its endpoint instead:

const session = await attach({ browserURL: 'http://127.0.0.1:9222' });

Why this needs two pauses, not one

Target.setAutoAttach with waitForDebuggerOnStart pauses a worker before its first line — but at that moment a dedicated worker's global is only half built. Measured on Chrome 151:

| At the auto-attach pause | | | --- | --- | | VideoFrame, AudioData, ImageBitmap, EncodedVideoChunk | present | | VideoDecoder, VideoEncoder, AudioDecoder, AudioEncoder | absent | | setInterval, setTimeout, queueMicrotask | absent |

Patch there and you instrument the frame types but miss every codec. So this resumes into a second, later pause — a beforeScriptExecution instrumentation breakpoint — which fires with the global fully populated and still before the worker's own script runs. It is the only moment that is both complete and early enough.

Auto-attach is not recursive, so each attached target arms it again for its children. That is what reaches nested workers. data: and blob: URL workers are covered too.

This behaviour is measured rather than specified, so the repository has a test that asserts it directly and prints what it found — a Chrome change is reported as a Chrome change, rather than surfacing as a mysterious failure.

API

| | | | --- | --- | | attach(options) | Instrument a page and its workers. Returns a CensusSession. | | launchChrome(options) | Launch Chrome with a throwaway profile on a free port. | | findPageTarget(origin, match?) | Resolve a page target from a DevTools endpoint. | | CdpClient | A minimal flat-session CDP client, if you need one. |

CensusSession provides census(), contexts(), evaluate(expr, sessionId?), navigate(url), redirect(rules) and detach().

redirect() serves a matching URL from somewhere else — useful for pinning a large media asset to a local copy so runs are fast and repeatable without editing the app under test.

Safety

launchChrome() always uses a throwaway profile and lets Chrome pick a free port. It never reuses, and never kills, a browser you already have open. Instrumenting a browser you are signed into risks touching your session, and a shared profile makes runs non-repeatable.

Chrome's DevTools Protocol is unauthenticated by design — anything that can reach the port controls the browser. Never expose a debugging port beyond localhost.

Documentation

Full documentation, the extension, and the MCP server: github.com/motionvector-dev/webcodecs-census

MIT