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

@ar-js-org/arjs-plugin-artoolkit

v0.1.3

Published

ARToolKit detection plugin for AR.js core (ECS plugin)

Downloads

21

Readme

🎯 arjs-plugin-artoolkit ⚡🕶️

GitHub stars GitHub forks CI Build npm version Types Prettier License Coverage

Lightweight WebWorker ARToolKit plugin for AR.js that detects square markers using WebAssembly and ImageBitmap zero-copy transfers, offering an event-driven API for realtime camera input, fast detection, and easy integration. 🔎🎯🚀⚡🧩

Table of Contents

Features ✨🧭

  • 🧠 Web Worker-based detection — marker detection runs off the main thread (Browser Module Worker)
  • 🖼️ ImageBitmap support — zero-copy frame transfer for efficient camera frames
  • 🧩 ARToolKit integration — square pattern markers (patt files)
  • ⚡ Event-driven API — markerFound / markerUpdated / markerLost + raw getMarker events
  • 🔍 Confidence filtering — only forwards PATTERN_MARKER events above minConfidence

Version 🏷️

The plugin exposes its build-time version both as a constant and on each instance:

import {
  ArtoolkitPlugin,
  ARTOOLKIT_PLUGIN_VERSION,
} from "@ar-js-org/arjs-plugin-artoolkit";

console.log("Build version:", ARTOOLKIT_PLUGIN_VERSION); // e.g. 0.1.0 or 'unknown'
const plugin = new ArtoolkitPlugin();
console.log("Instance version:", plugin.version);

If the build-time define is missing (for example when using raw source or some test runners), the version falls back to 'unknown'.

Installation 📦

# Attention: package may not be published yet
npm install @ar-js-org/arjs-plugin-artoolkit

Using the ESM build (recommended) 🚀

When you import the built ESM bundle from dist/, the worker and ARToolKit are already bundled and referenced correctly. You do NOT need to pass artoolkitModuleUrl.

Example:

<script type="module">
  import { ArtoolkitPlugin } from '/dist/arjs-plugin-artoolkit.es.js';

  const engine = { eventBus: /* your event bus */ };

  const plugin = new ArtoolkitPlugin({
    worker: true,
    cameraParametersUrl: '/path/to/camera_para.dat',
    minConfidence: 0.6
  });

  await plugin.init(engine);
  await plugin.enable();
  console.log('Plugin version:', plugin.version);
</script>

Serving notes:

  • Serve from a web server so /dist assets resolve. The build is configured with base: './', so the worker asset is referenced relative to the ESM file (e.g., /dist/assets/worker-*.js).
  • In your own apps, place dist/ where you serve static assets and import the ESM with the appropriate path (absolute or relative).

Using source (development mode) 🛠️

If you develop against src/ (not the built dist/), the worker will attempt to dynamically import ARToolKit. In that case, you must provide a valid artoolkitModuleUrl (for example a direct path to the UMD or ESM build) or ensure your dev server can resolve @ar-js-org/artoolkit5-js as an ES module. Browser module loading issues may occur if the module is not properly served or is not an ES module.

const plugin = new ArtoolkitPlugin({
  worker: true,
  artoolkitModuleUrl: '/node_modules/@ar-js-org/artoolkit5-js/dist/ARToolkit.js', // provide when using src/
  cameraParametersUrl: '/path/to/camera_para.dat',
  wasmBaseUrl: '/node_modules/@ar-js-org/artoolkit5-js/dist/', // optional; if your build requires it
  minConfidence: 0.6,
});
console.log('Plugin version:', plugin.version);

CDN fallback (for source/dev):

  • Set artoolkitModuleUrl to a CDN ESM endpoint (e.g., jsDelivr/UNPKG) for @ar-js-org/artoolkit5-js.

Notes:

  • The previous loader.js and manual WASM placement flow is no longer used.
  • In the dist/ build, ARToolKit is bundled and artoolkitModuleUrl is NOT needed.

Usage 🧩

Quick Start (copy-paste) ⚡

import { ArtoolkitPlugin } from "@ar-js-org/arjs-plugin-artoolkit";

// Minimal event bus stub
const eventBus = {
  _h: new Map(),
  on(e, h) {
    if (!this._h.has(e)) this._h.set(e, []);
    this._h.get(e).push(h);
  },
  emit(e, p) {
    (this._h.get(e) || []).forEach((fn) => {
      try {
        fn(p);
      } catch (err) {
        console.error(err);
      }
    });
  },
};
const engine = { eventBus };

const plugin = new ArtoolkitPlugin({ worker: true, minConfidence: 0.6 });
await plugin.init(engine);
await plugin.enable();
console.log("Version:", plugin.version);

// Load a marker (size is world units)
await plugin.loadMarker("/examples/simple-marker/data/patt.hiro", 1);

eventBus.on("ar:markerFound", (m) => console.log("FOUND", m.id));
eventBus.on("ar:markerUpdated", (m) => console.log("UPDATED", m.id));
eventBus.on("ar:markerLost", (m) => console.log("LOST", m.id));

Register and enable ✅

import { ArtoolkitPlugin } from "@ar-js-org/arjs-plugin-artoolkit";

const plugin = new ArtoolkitPlugin({
  worker: true,
  lostThreshold: 5, // frames before a marker is considered lost
  frameDurationMs: 100, // expected ms per frame (affects lost timing)
  // artoolkitModuleUrl: '/node_modules/@ar-js-org/artoolkit5-js/dist/ARToolkit.js', // Only for src/dev
  cameraParametersUrl: "/data/camera_para.dat",
  minConfidence: 0.6,
});

engine.pluginManager.register("artoolkit", plugin);
await engine.pluginManager.enable("artoolkit");

Events 🔔

The plugin emits the following events on your engine’s event bus:

// Marker first detected
engine.eventBus.on(
  "ar:markerFound",
  ({ id, poseMatrix, confidence, corners }) => {
    // poseMatrix is Float32Array(16)
  },
);

// Marker updated (tracking)
engine.eventBus.on("ar:markerUpdated", (data) => {
  // same shape as markerFound
});

// Marker lost
engine.eventBus.on("ar:markerLost", ({ id }) => {});

// Worker lifecycle
engine.eventBus.on("ar:workerReady", () => {});
engine.eventBus.on("ar:workerError", (error) => {});

// Raw ARToolKit getMarker (filtered: PATTERN_MARKER only, above minConfidence)
engine.eventBus.on("ar:getMarker", (payload) => {
  // payload = { type, matrix: number[16], marker: { idPatt, cfPatt, idMatrix?, cfMatrix?, vertex? } }
});

Sending frames 🎞️

// Create ImageBitmap from a <video> or <canvas>
const imageBitmap = await createImageBitmap(video);

// Emit an engine update; the plugin transfers the ImageBitmap to the worker
engine.eventBus.emit("engine:update", {
  id: frameId,
  timestamp: Date.now(),
  imageBitmap,
  width: imageBitmap.width,
  height: imageBitmap.height,
});

// The ImageBitmap is transferred and cannot be reused; the worker will close it.

Loading a pattern marker 📐

const { markerId, size } = await plugin.loadMarker(
  "/examples/simple-marker/data/patt.hiro",
  1,
);

Examples 🧪

A complete webcam-based example is available under examples/simple-marker/.

Serve from the repository root so that dist/ and example paths resolve:

# From repository root
npx http-server -p 8080
# or
python3 -m http.server 8080

Open:

  • http://localhost:8080/examples/simple-marker/index.html

The example demonstrates:

  • Webcam capture with getUserMedia
  • ImageBitmap creation and frame submission
  • Event handling and console output
  • Raw ar:getMarker payloads for debugging

API Reference 📚

ArtoolkitPlugin options 🧭

{
  worker?: boolean;            // Enable worker (default: true)
  lostThreshold?: number;      // Frames before 'lost' (default: 5)
  frameDurationMs?: number;    // ms per frame used with lostThreshold (default: 200)
  sweepIntervalMs?: number;    // Lost-sweep interval (default: 100)
  artoolkitModuleUrl?: string; // Only needed when using source/dev; not needed for dist build
  cameraParametersUrl?: string;// Camera params file URL (required unless you rely on a remote default)
  wasmBaseUrl?: string;        // Base URL for ARToolKit assets (optional)
  minConfidence?: number;      // Minimum confidence to forward getMarker (default: 0.6)
}

Methods 🛠️

  • async init(core) — initialize with engine core
  • async enable() — start worker and subscribe to frames
  • async disable() — stop worker and timers
  • dispose() — alias for disable
  • getMarkerState(markerId) — current tracked state
  • async loadMarker(patternUrl: string, size = 1) — load and track a pattern

Troubleshooting 🧰

  • Worker asset 404:
    • Ensure you import the ESM from /dist/arjs-plugin-artoolkit.es.js and that /dist/assets/worker-*.js is served.
    • The build uses base: './', so worker URLs are relative to the ESM file location.
  • “Failed to resolve module specifier” in the Worker (source/dev only):
    • Provide artoolkitModuleUrl or serve /node_modules from your dev server
  • Worker not starting:
    • Serve via HTTP/HTTPS; ensure ES modules and Workers are supported
  • No detections:
    • Confirm camera started, correct marker pattern, sufficient lighting

    • Adjust minConfidence to reduce/raise filtering

    • Check plugin.version (if 'unknown', ensure build-time define is configured)

Build & Publishing Notes

  • Sourcemap files (.map) generated in dist/ and types/ are excluded from the repository and the npm package to reduce package size and avoid shipping debug artifacts.
    • See .gitignore and .npmignore for details.
  • When installing the package from npm (npm install @ar-js-org/arjs-plugin-artoolkit), all required built files are included and ready to use.
    • If you install from source (e.g., cloning the repository), you must run the build manually: npm run build.

Releases and Built Artifacts

  • Built files (dist/) and TypeScript declarations (types/) are NOT committed to the repository. They are generated by the CI/build process and attached to GitHub Releases as downloadable assets.

  • To download the built files for a given release tag (example v1.2.3), use the Releases download URL:

    https://github.com/AR-js-org/arjs-plugin-artoolkit/releases/download/v1.2.3/dist/arjs-plugin-artoolkit.es.js

  • If/when the package is published to npm, you can use jsDelivr to serve files from the npm package:

    https://cdn.jsdelivr.net/npm/@ar-js-org/[email protected]/dist/arjs-plugin-artoolkit.es.js

  • Note: jsDelivr serves files from npm or from the repository tree at a tag/branch. Because dist/ and types/ are not committed to the repo, the npm package must contain the built files for jsDelivr to serve them.

If you want me to add publish instructions or a small note showing how to use the Release assets or jsDelivr URLs in your project, I can add examples.