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

@variax-ai/video-extractor

v0.3.2

Published

Video to VideoDocument schema inference (extractor)

Readme

@variax-ai/video-extractor

Turns a video into a VideoDocument: samples frames, asks a vision model what it is looking at, and returns a document the renderer can play.

The package does not talk to any model provider. It samples the frames, builds the prompt, and parses and validates what comes back — you supply an infer function that gets the frames to whichever model you use. That keeps API keys, retries, cost control and provider choice on your side of the boundary, and makes the pipeline testable without a network.

Extraction is inference, not decoding. The result is a plausible reconstruction, not the original timeline — expect to review and edit it.

Install

npm install @variax-ai/video-extractor

Usage

import { extractDocument, parseResponse } from '@variax-ai/video-extractor'
import type { VideoDocument } from '@variax-ai/video-schema'

const doc = await extractDocument({
  source: videoElement,          // an HTMLVideoElement, or your own FrameSource
  infer: async ({ frames, prompt, width, height, durationMs, fps }) => {
    // frames[i].data is a PNG (Uint8Array); frames[i].timeMs is its timestamp
    const text = await callYourVisionModel(prompt, frames)
    return parseResponse(text) as VideoDocument
  },
})

extractDocument runs the whole pipeline:

  1. Reads width, height, durationMs and fps from the source (your options override any of them).
  2. Picks timestamps — one per second by default, capped at 20 — spaced evenly, each centred in its slice rather than sitting on the boundary.
  3. Samples those frames.
  4. Builds the prompt with buildPrompt.
  5. Calls your infer.
  6. Runs the result through validateDocument before returning it.

The source is disposed whether or not any of that throws.

Options

| Option | Meaning | |---|---| | source | An HTMLVideoElement or a FrameSource | | infer | Your model call. Required | | width, height | Override the document's dimensions | | fps | Override the frame rate (default: the source's, else 30) | | sampleCount | How many frames to sample (default: one per second, max 20) |

Frame sources

In a browser, pass an HTMLVideoElement and createBrowserFrameSource seeks and grabs each frame through a canvas.

Anywhere else, implement the interface — three methods, no dependency on the DOM:

interface FrameSource {
  metadata(): Promise<VideoMetadata>            // width, height, durationMs, fps?
  sample(timestamps: number[]): Promise<Frame[]> // PNG bytes + timeMs
  dispose?(): void
}

An ffmpeg-backed source in Node is a handful of lines, and a source that reads pre-extracted PNGs off disk makes the pipeline fully offline for tests.

The pieces, separately

Each stage is exported, because the useful thing is rarely the whole pipeline:

import {
  buildPrompt,       // metadata → the prompt string
  parseResponse,     // model text → unknown (unwraps ``` fences, finds the object)
  validateDocument,  // unknown → VideoDocument, or throws
  createBrowserFrameSource,
} from '@variax-ai/video-extractor'

parseResponse exists because models wrap JSON in prose and code fences; it takes the fenced block if there is one, otherwise the outermost {…}.

validateDocument is a structural check, not a schema check. It enforces what must hold for the document to be renderable at all — positive dimensions, at least one scene, sane times — and drops layers whose type it does not recognise rather than throwing. For real validation, run the result against @variax-ai/video-schema's json/v1.json with a JSON Schema validator.

Licence

MIT