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

realtime-capture-nid

v0.1.3

Published

Real-time national ID card detection and auto-capture using YOLO ONNX in the browser. Provides a drop-in React component and low-level utilities for edge detection, perspective correction, and quality scoring.

Readme

realtime-capture-nid

Real-time national ID card detection and auto-capture in the browser, powered by YOLO ONNX inference via onnxruntime-web.

Provides a drop-in React component (<NidCapture />) and low-level utilities for edge detection, perspective correction, and quality scoring.

Features

  • Browser-only — runs entirely client-side using WebAssembly (no server needed)
  • YOLO ONNX inference for real-time ID card detection
  • Edge refinement — Sobel gradients + RANSAC line fitting to find precise card corners
  • Perspective unwarp — homography-based rectification produces a clean rectangular image
  • Quality gating — blur, glare, brightness, tilt, skew, and motion checks with automatic countdown capture
  • Fully configurable — custom model URL, locale strings, thresholds, and callbacks

Installation

npm install realtime-capture-nid onnxruntime-web
# or
pnpm add realtime-capture-nid onnxruntime-web
# or
yarn add realtime-capture-nid onnxruntime-web

Quick Start

1. Place your ONNX model

Put your YOLO ONNX model file in your app's public/weights/ directory (or any path accessible via URL):

public/
  weights/
    yolo26n.onnx

2. Configure Next.js

onnxruntime-web requires WASM files to be served and proper webpack/header config. Here's a full next.config.ts:

import type { NextConfig } from "next";
import { copyFileSync, mkdirSync, existsSync } from "fs";
import { join, dirname } from "path";

// Copy WASM files from onnxruntime-web to public/ so the browser can load them
function copyWasmFiles() {
  const wasmDir = join(process.cwd(), "node_modules", "onnxruntime-web", "dist");
  const publicDir = join(process.cwd(), "public");
  if (!existsSync(wasmDir)) return;

  const wasmFiles = [
    "ort-wasm-simd-threaded.wasm",
    "ort-wasm-simd.wasm",
    "ort-wasm.wasm",
    "ort-wasm-threaded.wasm",
  ];

  for (const file of wasmFiles) {
    const src = join(wasmDir, file);
    const dest = join(publicDir, file);
    if (existsSync(src) && !existsSync(dest)) {
      mkdirSync(dirname(dest), { recursive: true });
      copyFileSync(src, dest);
    }
  }
}

copyWasmFiles();

const nextConfig: NextConfig = {
  transpilePackages: ["onnxruntime-web"],

  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback = {
        ...config.resolve.fallback,
        fs: false,
        path: false,
        crypto: false,
      };
    }
    return config;
  },

  // Required only if you want multi-threaded WASM (wasmNumThreads > 1)
  async headers() {
    return [
      {
        source: "/(.*)",
        headers: [
          { key: "Cross-Origin-Opener-Policy", value: "same-origin" },
          { key: "Cross-Origin-Embedder-Policy", value: "require-corp" },
        ],
      },
    ];
  },
};

export default nextConfig;

3. Import the styles and use the component

"use client"; // if using Next.js App Router

import { NidCapture } from "realtime-capture-nid";
import "realtime-capture-nid/styles.css";

export default function CaptureIdPage() {
  return (
    <NidCapture
      modelUrl="/weights/yolo26n.onnx"
      onCapture={(result) => {
        console.log("Captured!", result.imageDataUrl);
        console.log("Quality:", result.quality.score);
        // Upload result.imageDataUrl to your server, etc.
      }}
    />
  );
}

Note: The CSS import (realtime-capture-nid/styles.css) includes all styles the component needs. You can import it in your root layout instead if you prefer.

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | modelUrl | string | "/weights/yolo26n.onnx" | URL to the ONNX model file | | onCapture | (result: CaptureResult) => void | — | Called when a card is successfully captured | | defaultConfidenceThreshold | number | 0.25 | Initial YOLO confidence threshold (0–1) | | maxOutputSide | number | 1280 | Max dimension (px) of the output JPEG | | jpegQuality | number | 0.92 | JPEG quality (0–1) | | locale | Partial<NidCaptureLocale> | Khmer defaults | Override any user-facing string | | className | string | — | Additional CSS class on the root container | | showHeader | boolean | true | Show the title and subtitle | | showConfidenceSlider | boolean | true | Show the confidence threshold slider | | showDetections | boolean | true | Show the detection list | | wasmNumThreads | number | 1 | WASM threads (1 = works everywhere; >1 requires COOP/COEP headers) |

CaptureResult

type CaptureResult = {
  imageDataUrl: string;   // JPEG data URL of the rectified card
  quality: QualityResult; // detailed quality metrics
  timestamp: Date;
};

Locale / i18n

Override any string by passing a partial locale object. The defaults are in Khmer:

<NidCapture
  locale={{
    title: "ID Card Scanner",
    subtitle: "Point your camera at the ID card.",
    openCamera: "Open Camera",
    closeCamera: "Close Camera",
    screenshot: "Screenshot",
    searchingCard: "Searching for ID card...",
    capturedDone: "Captured!",
    // ... see NidCaptureLocale type for all keys
  }}
/>

Low-Level Utilities

If you want to build your own UI, you can import the processing utilities directly:

import {
  // YOLO pre/post-processing
  preprocessImage,
  processOutput,
  setModelInputSize,
  getModelInputSize,

  // Edge detection & quad refinement
  refineToQuad,
  quadBBox,
  quadDimensions,

  // Perspective correction
  unwarpQuad,

  // Quality assessment
  evaluateQuality,

  // Constants
  AUTO_CAPTURE_THRESHOLD,
  CLASS_NAMES,
} from "realtime-capture-nid";

Example: Custom detection pipeline

import {
  preprocessImage,
  processOutput,
  setModelInputSize,
  refineToQuad,
  evaluateQuality,
  unwarpQuad,
} from "realtime-capture-nid";

// Set model input size (default 640)
setModelInputSize(640);

// Preprocess a video frame for YOLO
const { tensor, scale, offsetX, offsetY } = preprocessImage(videoElement);

// Run inference with onnxruntime-web (you manage the session)
const results = await session.run({ images: inputTensor });
const output = results[session.outputNames[0]];

// Post-process detections
const detections = processOutput(output, videoWidth, videoHeight, scale, offsetX, offsetY, 0.25);

// Refine the best detection to a precise quad
const { quad, refined } = refineToQuad(videoElement, {
  x: det.x, y: det.y, width: det.width, height: det.height,
});

// Check quality
const quality = evaluateQuality(videoElement, quad, bbox, prevBBox);

// Unwarp to a clean rectangular image
if (quality.ok) {
  const canvas = unwarpQuad(videoElement, quad, { maxSide: 1280 });
  const dataUrl = canvas?.toDataURL("image/jpeg", 0.92);
}

Types

All TypeScript types are exported:

import type {
  Detection,
  Point,
  Quad,
  BBox,
  QualityIssue,
  QualityResult,
  CaptureResult,
  NidCaptureProps,
  NidCaptureLocale,
} from "realtime-capture-nid";

Requirements

  • React >= 18
  • onnxruntime-web >= 1.17
  • Tailwind CSS (for the <NidCapture /> component styles)
  • A YOLO ONNX model trained to detect nationalid class
  • Browser with WebAssembly support

Development

# Install dependencies
pnpm install

# Run the demo app (Next.js)
pnpm dev

# Build the library
pnpm build

# Type-check
pnpm typecheck

License

MIT