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

@pixel-point/aval-alpha

v0.1.0

Published

Tiny player for packed-alpha AV1, VP9, HEVC and H.264 video.

Readme

@pixel-point/aval-alpha

A small transparent-video player with no runtime dependencies. An ordinary AV1, VP9, HEVC, or H.264 video contains an RGB picture and a grayscale coverage mask in the same frame. The browser decodes it; one WebGL texture and shader reconstruct transparent pixels. Color and alpha share the same media clock.

This is a new 0.1 preview package, independent of the interactive AVAL player. It does not require WebCodecs or ship a demuxer, worker, or WASM decoder. Codec support comes from the browser and device. Software libx265 produces the HEVC files; Apple's native HEVC-alpha extension and VideoToolbox are not required.

Dedicated React and Svelte packages use this same player and an optional shared ./adapter entry for reactive configuration and lifecycle. Plain JavaScript users do not download that binding or either framework. See the framework contract.

Tested compatibility

The device and browser matrix records the tested iPhone, iPad, Pixel, Galaxy, Windows and macOS configurations, exact browser versions, and AV1/VP9/HEVC/H.264 results. It distinguishes the initial qualification from the fixed-build retests and documents native codec limitations. H.264 passed on every listed configuration.

Compile

Install the player and the compiler (the alpha command requires compiler 1.1.0 or later):

npm install @pixel-point/aval-alpha
npm install --save-dev @pixel-point/aval-compiler@^1.1.0
npx avl alpha motion.mov --out public/motion

The default encodings are AV1 (SVT-AV1), VP9, HEVC, and H.264. FFmpeg and FFprobe must be installed on the compiler machine, with the requested encoders. Select fewer codecs or use a configuration file to control each one:

npx avl alpha motion.mov --codecs h265 \
  --crf 24 --preset veryslow --out public/motion

npx avl alpha 'frames/frame-%04d.png' \
  --fps 30 --frames 120 --codecs av1,vp9,h265,h264 --out public/motion

Compilation produces av1.mp4, vp9.webm, h265.mp4, h264.mp4, sources.json, sources.js, sources.html, and an offline build.json report. Existing output directories are refused. A failed compile removes its staging files. sources.html contains ready-to-copy markup; sources.js contains the same inlineable descriptor array. Playback does not fetch build.json or require a sidecar request.

Use child sources

Import and explicitly register the optional element in your application bundle:

import { defineAvalAlphaElement } from '@pixel-point/aval-alpha/element';

defineAvalAlphaElement();

Copy the compiler's generated markup. Each source has its own MIME/codec and layout. For a 640×360 clip, vertical packing looks like this:

<aval-alpha autoplay loop style="width:640px;height:360px"
            role="img" aria-label="Animated transparent illustration">
  <source src="/motion/av1.mp4" type="video/mp4"
          data-layout="640 728 0 0 640 360 0 368 640 360">
  <source src="/motion/vp9.webm" type="video/webm"
          data-layout="640 728 0 0 640 360 0 368 640 360">
  <source src="/motion/h265.mp4" type="video/mp4"
          data-layout="640 728 0 0 640 360 0 368 640 360">
  <source src="/motion/h264.mp4" type="video/mp4"
          data-layout="640 728 0 0 640 360 0 368 640 360">
</aval-alpha>

Use the actual codec declarations emitted by your compilation. The numbers above illustrate the layout, not a codec level to copy into arbitrary assets. data-layout is ten space-separated integers: packed width/height, color x/y/w/h, then alpha x/y/w/h. Width and height are the decoded packed dimensions.

Sources are tried in authored order. Unsupported types are skipped; load errors, a startup timeout, a dimension mismatch, or a failed first draw advance to the next candidate. Only one candidate is assigned to the video at a time. The browser may fetch bytes from a rejected candidate; later alternatives are not preloaded. This is ordered fallback, not adaptive bitrate switching.

const element = document.querySelector('aval-alpha');
element.addEventListener('error', (event) => showPoster(event.detail));
element.addEventListener('autoplayblocked', () => showPlayButton());
await element.ready;               // First transparent frame, even without autoplay
await element.play();
element.pause();
await element.seek(0.5);            // Seconds

Install error listeners before registration when catching initial upgrade errors is important. ready, error, and autoplayblocked are direct element events; errors are also available through the rejected readiness/play/seek promise. Removing the element releases its owned media and GPU resources. Reconnecting starts a new player. Changing child sources or assigning element.sources replaces the player; use a new array to update programmatic sources. Set element.sources = undefined to return to child sources. Changing loop updates playback without reloading. Importing either entry is safe during SSR; call the registration function only in the browser.

Use a canvas directly

import { createAvalAlpha } from '@pixel-point/aval-alpha';
import sources from './generated/sources.js';

const player = createAvalAlpha(document.querySelector('canvas'), {
  sources, autoplay: true, loop: true,
  timeoutMs: 15000,
  onError: (error) => showPoster(error),
  onAutoplayBlocked: () => showPlayButton()
});
await player.ready;
console.log(player.source);        // Successfully selected descriptor
// Later:
player.destroy();

The canvas and its WebGL context belong exclusively to this player until destroy(). The player creates one muted inline video beside the canvas. player.video exposes native timing, duration, playback rate and looping; do not replace its src or its children. Source replacement uses a new player. The canvas intrinsic dimensions match the visible color rectangle; style its display size with CSS. The runtime pauses frame uploads while paused, ended or hidden, and restores its WebGL resources after context restoration.

AvalAlphaError.code is invalid-source, unsupported-source, rendering, media, or disposed. Exhausted candidates are recorded in error.cause. Autoplay rejection keeps the selected source ready. Errors after readiness are reported as terminal playback failures; there is no midstream codec switching. The application owns poster, loading, accessibility and error presentation.

Compression controls

A JSON configuration passed to avl alpha keeps settings specific to each codec:

{
  "input": "motion.mov",
  "fps": 30,
  "width": 640,
  "baseUrl": "/motion/",
  "encodings": [
    { "codec": "av1", "encoder": "libsvtav1", "preset": "4", "crf": 30 },
    { "codec": "vp9", "cpuUsed": 0, "deadline": "best", "crf": 30 },
    { "codec": "h265", "preset": "veryslow", "crf": 24,
      "x265": { "aqMode": 3, "psyRd": 1, "sao": false } },
    { "codec": "h264", "preset": "slow", "crf": 23 }
  ]
}

Input paths in JSON are relative to that file. --out is required and relative to the working directory. Run avl alpha config.json --out public/motion using the installed CLI. The Node API is compileAlpha(input, options) from @pixel-point/aval-compiler/alpha.

| Encoder | Controls | | --- | --- | | SVT-AV1 | encoder: "libsvtav1", CRF 0–63, preset "0"–"13" | | libaom AV1 | encoder: "libaom-av1", CRF 0–63, cpuUsed 0–8 | | VP9 | CRF 0–63, cpuUsed 0–5, deadline: "good" or "best" | | x265 HEVC | CRF 0–51, ultrafast through placebo, typed x265 options | | x264 H.264 | CRF 0–51, ultrafast through placebo |

All support threads (1–64) and gop (maximum keyframe interval in seconds, default 2). AV1 and HEVC additionally accept bitDepth: 10; the default is 8. The compiler preserves normal lookahead and frame reordering. It reads codec configuration from the output rather than guessing from a filename. Requested encoders must exist; it does not silently switch an unavailable encoder.

Typed x265 controls are aqMode, aqStrength, psyRd, psyRdoq, rd, rdoqLevel, lookahead, bframes, ref, and sao. They use x265's documented semantics. Slower settings may reduce bytes; the best result depends on the clip. FFmpeg encoders, x265 controls.

Optional quality search tries every CRF/preset combination and selects the smallest qualifying candidate per codec:

{
  "optimize": {
    "crfs": [20, 26, 32],
    "presets": { "h265": ["slow", "veryslow"] },
    "maxAlphaMae": 2,
    "maxCompositeMae": 3
  }
}

Merge that into the configuration; preset searches apply only to encoders with a preset control. At most 32 CRFs and 64 CRF/preset combinations per codec are allowed. build.json records bytes, encode time, exact arguments, encoder versions, decoded alpha/composite errors, selected candidates, and the Pareto frontier. Errors use the 0–255 channel scale and cover every output frame; composites use black, white, and magenta backgrounds. The search rejects if a codec has no qualifying output. These offline metrics are not a substitute for testing browser rendering on target devices. Equal CRF values across different codecs do not mean equal quality. RGB and alpha share one stream, so there is no independent alphaCrf.

Input and delivery contract

  • Input is SDR, square-pixel, unrotated media with alpha, or a numbered PNG sequence. Sequences need fps and frames; numbering starts at zero unless startNumber is supplied. frames also limits video inputs. Use fps to normalize variable-rate media. Fully opaque inputs are rejected.
  • Input colors use straight alpha; set premultiplied: true / --premultiplied for premultiplied input. Transparent VP9 WebM is decoded with libvpx so its existing alpha plane is preserved. Audio is discarded.
  • Output is full-resolution RGB plus full-resolution alpha, SDR BT.709 limited YUV420, with even chroma alignment and an eight-pixel gutter. layout: "auto" packs portrait clips horizontally and others vertically. Override with "horizontal" or "vertical". This reduces the longest decoded side without affecting the runtime contract; it does not guarantee device decoder limits.
  • The WebGL upload disables optional browser color-space conversion. The shader recovers mask coverage using BT.709 luma weights and outputs premultiplied RGBA. Compression remains lossy. The color checks guard against an extra FFmpeg matrix conversion before encoding.
  • Serve correct video MIME types, HTTP byte ranges and MP4 fast-start files. External origins must permit CORS texture access. The default is anonymous CORS; crossorigin="use-credentials" / crossOrigin: "use-credentials" is available when the server supports credentialed CORS.
  • A native decoder and WebGL1 are required. There is no WASM or Canvas2D fallback. A generic video viewer shows the packed picture and mask; aval-alpha supplies the interpretation. The runtime has no dependency on the AVAL binary format.

Verify and measure

npm run alpha:fixtures        # Build compiler and generate synthetic media
npm run alpha                # Demo on http://127.0.0.1:4188
npm run test:alpha            # Unit validation
npm run test:alpha:media      # Real FFmpeg integration tests
npm run test:alpha:browser    # Chromium, Firefox, WebKit; also without WebCodecs/rVFC
npm run alpha:size           # Standalone ES2022 bundle, all executable resources
npm run alpha:pack           # Tarball, isolated install, type and SSR checks

The size gate enforces ≤5,000 gzip / 4,000 Brotli bytes for the core and ≤1,000 additional compressed bytes for the element. Generated standalone ES modules and raw/gzip/Brotli totals are in .cache/alpha/bundles; copy the appropriate bundle to your static server if using no application bundler. The measurement rejects external modules, workers, decoder assets, and imports outside this package. Media bytes are additional. See verification evidence for measured sizes, tested engines and the remaining device checks.