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

@meiban-ocr/runtime

v0.3.2

Published

Browser-friendly alphanumeric OCR runtime (onnxruntime-web).

Readme

@meiban-ocr/runtime

Browser-friendly OCR for industrial nameplate serials (Ericsson E300MM000032 format). ONNX CRNN model bundled in-package, no separate model file or CDN required.

  • Inference engine: onnxruntime-web (WebGPU → WASM fallback)
  • Model: MobileNetV3-Small + Bi-GRU + CTC, ~3 MB FP32 ONNX (bundled inline)
  • Detection: built-in sliding-window proposal generator (no OpenCV.js dependency)
  • License: Apache-2.0

Install

npm i @meiban-ocr/runtime onnxruntime-web
# or pnpm / yarn

onnxruntime-web is a peer-style dependency — you bring your own version.

Usage

import { MeibanOCR } from '@meiban-ocr/runtime';

// init: モデルはバンドル済み、追加ダウンロード不要
const ocr = await MeibanOCR.create({ vendor: 'ericsson' });

// camera frame / Reticle crop / 任意の Canvas 画像を渡せる
const results = await ocr.recognize(canvas);
// → [{ text: 'E300MM000032', confidence: 0.96, bbox: [120, 340, 480, 420] }, ...]
// 該当なし → []

await ocr.dispose();

API

type ImageInput = HTMLCanvasElement | OffscreenCanvas | ImageBitmap | ImageData;

interface MeibanOCROptions {
  vendor?: 'ericsson';                                  // 補正パイプライン (default)
  executionProviders?: Array<'webgpu' | 'wasm'>;         // ORT EP (default: ['webgpu', 'wasm'])
  minConfidence?: number;                                // default 0.5
  modelUrl?: string;                                      // バンドル版を上書きしたいとき
  modelBytes?: Uint8Array | ArrayBuffer;                  // ↑ バイト列で渡すとき
  detector?: {
    maxInputDim?: number;                                 // default 1024
    strideX?: number;                                     // default 32
    strideY?: number;                                     // default 16
    scales?: number[];                                    // default [1.0]
  };
  maxBatchSize?: number;                                  // default 64
}

interface OCRResult {
  text: string;            // 確定値 (regex 通過済み)
  confidence: number;      // 0-1
  bbox: [number, number, number, number];  // 入力画像内座標 [x1,y1,x2,y2]
}

class MeibanOCR {
  static create(opts?: MeibanOCROptions): Promise<MeibanOCR>;
  recognize(image: ImageInput): Promise<OCRResult[]>;
  dispose(): Promise<void>;
}

Vendor pattern

Currently supports Ericsson only:

  • Strict regex: /^E[39]\d{2}MM\d{6}$/ 例: E300MM000032, E300MM999022
  • 6-stage correction pipeline (backend PlateSerialNumber.php と互換):
    1. Strict full match
    2. Strict full + O → 0 fallback
    3. Lenient full (Ericsson 対象外、将来用)
    4. Lenient + O → 0
    5. Strict partial + O → 0
    6. Strict partial

recognize()text は 6 段補正後の確定値です。

検出器 (Detector) の差し替え (v0.2.0+)

MeibanOCR.recognize() は内部で 「入力画像 → 候補テキスト行 bbox 列挙 → CRNN 認識 → 補正」 の順に処理する。最初のステップ "候補 bbox 列挙" が detector で、2 つの選択肢がある。

(1) Sliding-window (default、ゼロ依存) ★推奨

const ocr = await MeibanOCR.create();  // 省略 = sliding-window
// or 明示的にチューニング
import { createSlidingWindowDetector } from '@meiban-ocr/runtime';
const ocr = await MeibanOCR.create({
  detector: createSlidingWindowDetector({ strideX: 32, strideY: 16 }),
});

総当たり方式。Reticle 切り出し済の小入力 (e.g. 600x200) 用途には最適。 外部依存ゼロ・bundle bloat なし。WebGPU でバッチ推論されるので 100-500ms/frame 程度。

Reticle ユースケース (uranus2 等) のチューニング例

const ocr = await MeibanOCR.create({
  vendor: 'ericsson',
  detector: { strideX: 24, strideY: 12 },  // 細かめ stride で recall 上げる
  minConfidence: 0.5,
});
const results = await ocr.recognize(reticleCanvas);

(2) 独自検出器 (学習済モデル / Reticle 固定 / OpenCV.js 自作 / etc)

import type { DetectorFn } from '@meiban-ocr/runtime';

const reticleDetector: DetectorFn = (image) => [
  // 入力全体を 1 つの候補として扱う (uranus2 Reticle 互換)
  [0, 0, image.width, image.height],
];

const ocr = await MeibanOCR.create({ detector: reticleDetector });

DetectorFn = (image: ImageData) => BBox[] | Promise<BBox[]> を満たせば何でも OK。


v0.3.0 の変更点 (breaking)

  • OpenCV.js helper を削除createOpenCvDetector / loadOpenCv の export は廃止。 独自に OpenCV.js を使いたい場合は DetectorFn を自前実装する形に統一。
  • フロントエンド軽量化を最優先する方針。デフォルトの sliding-window で多くのユースケース (Reticle 切り出し等) は十分カバーできるため。
  • 移行ガイド: createOpenCvDetector(cv)DetectorFn で独自実装、もしくは省略して sliding-window を使う。

制限事項

  • Single product family: 訓練データは Ericsson 4 製品 (RRU 22F3, RRUS 11 B1, Radio 2218 B42B, Radio 2251 B18 B280) のみ。未学習銘板では精度低下の可能性あり。val_CER 3.85%, val_EM 53.8% (v0 ベンチマーク)。
  • Model size: 3 MB FP32 (FP16/INT8 化は次バージョンで検討)。
  • 訓練データの非公開: photo / 実シリアル番号は公開リポジトリに含まれません (samples/, data/, runs/ は gitignored)。詳細は SECURITY.md を参照。

Security considerations

OCRResult.text は untrusted な出力として扱うこと

recognize() の返却 text は、ユーザーがカメラ撮影した任意画像から抽出された 文字列です。攻撃者が 意図的な文字列を印字したラベルを撮影させる ことで、 任意文字列を OCRResult.text 経由でアプリに注入する余地があります。

DO:

  • textContent プロパティ / React の {text} 補間 (自動エスケープされる)
  • SQL は parameterized query
  • log では quote / escape

DON'T:

  • el.innerHTML = result.text
  • eval, Function, setTimeout(string) に渡す
  • shell command / SQL に直接埋め込む

modelUrl / modelBytes は信頼するソースからのみ

MeibanOCR.create({ modelUrl }) の引数は scheme 検証 (http: / https: / data: / blob: のみ許可) されますが、host の whitelist は無しです。 利用側は untrusted な値 (URL クエリパラメータ等) を直接渡さないこと:

// ❌ 危険: 攻撃者が ?model= で任意 ONNX を指定可能
const modelUrl = new URLSearchParams(location.search).get('model');
await MeibanOCR.create({ modelUrl });

// ✅ 自分で管理する CDN のみ
await MeibanOCR.create({ modelUrl: 'https://cdn.example.com/meiban/model.onnx' });

// ✅ 整合性検証して bytes で渡す (推奨)
const expectedSha = 'a1b2c3...';
const response = await fetch('https://cdn.example.com/model.onnx');
const buf = await response.arrayBuffer();
const hash = await crypto.subtle.digest('SHA-256', buf);
// hash を expectedSha と照合してから:
await MeibanOCR.create({ modelBytes: buf });

ONNX モデル整合性

現状の bundled モデル (@meiban-ocr/runtime に inline されている data URL) は SRI 不可です。npm パッケージ自体の integrity (shasum/sha512) は npm レジストリで検証されるため、npm install --ignore-scripts 等の通常導入なら問題なし。 さらに強い検証が必要なら modelBytes 経由で消費側 SHA-256 検証を行ってください。

報告窓口

脆弱性を発見したら public issue ではなく GitHub Private Vulnerability Reporting で報告してください: https://github.com/kogasura/meiban-ocr/security/advisories/new 詳細は SECURITY.md を参照。

Performance reference (HANDOFF.md 目標値)

1440×1080 nameplate sheet、20 ラベル想定:

| EP | 1 フレーム合計 | 1 ラベルあたり | |---|---|---| | WebGPU | ~120 ms | ~6 ms | | WASM (4 threads) | ~600 ms | ~30 ms |

実測は環境依存。

License

Apache-2.0. Model artifact ships under the same license as part of this package.