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

@craftthingy-digital-innovation/cty-paddle-ocr

v1.0.4

Published

[Bahasa Indonesia](#bahasa-indonesia) | [English](#english)

Readme

Client-Side PaddleOCR Compiler & Bundler

Bahasa Indonesia | English


Bahasa Indonesia

Proyek ini merupakan cty-paddle-ocr, sebuah library (SDK) PaddleOCR mandiri, ringkas, dan berkinerja tinggi yang berjalan secara isomorphic (baik di sisi client/web browser menggunakan WebAssembly maupun di sisi server-side Node.js).

Pustaka ini tidak lagi bergantung pada dependency eksternal ppu-paddle-ocr atau ppu-ocv. Seluruh logika pemrosesan gambar OpenCV (cty-ocv) dan eksekusi ONNX Runtime (cty-ocr) telah di-porting secara lokal dan disempurnakan. Modul ini secara dinamis berpindah ke pemrosesan sekuensial (dengan jeda setTimeout yield) di browser untuk mencegah tab membeku, dan berjalan paralel (multi-threaded) di Node.js untuk performa server tertinggi.

1. Cara Kerja & Shimming Engine

Modul dikompilasi menggunakan bundler Vite dalam Library Mode dengan konfigurasi alias khusus pada vite.config.js. Berikut adalah detail shim yang disematkan:

  1. Canvas Shim (browser-canvas-shim.js): Menangkap impor @napi-rs/canvas (pustaka biner canvas Node) dan mengalihkan seluruh pemanggilan method-method gambarnya ke objek global browser asli (HTMLCanvasElement, document.createElement('canvas'), dan new Image()). Ini memungkinkan pembuatan canvas secara dinamis di dalam browser.
  2. Filesystem Shim (browser-fs-shim.js): Mengganti pemanggilan sinkron Node fs.readFileSync dengan XHR sinkron (XMLHttpRequest) yang dikonfigurasikan dengan overrideMimeType('text/plain; charset=x-user-defined'). Teknik ini memaksa browser mengunduh biner model ONNX sebagai aliran byte raw tanpa merusak struktur filenya, menghindari kesalahan parser browser.
  3. URL-Aware Path Shim (browser-path-shim.js): Menggantikan parser POSIX path-browserify dengan wrapper kustom. Ketika mendeteksi URL absolute (http:// atau https://), modul ini langsung mengembalikan nilainya secara utuh tanpa merusak karakter double-slash (//) menjadi single-slash.
  4. WASM Sequential Engine (main.js): Menyusun inisialisasi AI secara asinkron (ort.InferenceSession.create(url)). Crucial Browser Optimization: Meng-override method processBoxesInParallel milik RecognitionService agar berjalan secara Sekuensial (satu-demi-satu) dan menambahkan jeda mikro setTimeout(resolve, 10) sebelum memproses tiap kotak gambar. Ini mencegah runtime WebAssembly (WASM) membekukan / me-lock main thread GUI browser Anda saat memproses puluhan kotak deteksi sekaligus.

2. Cara Menginstal & Membangun Bundle

Langkah A: Persiapan Awal

Pastikan Anda memiliki Node.js terinstal pada sistem Anda. Masuk ke folder proyek bundler:

cd D:\CraftThingy\client-side-paddle-ocr-project

Langkah B: Instal Dependencies

Unduh dependencies standar yang diperlukan:

npm install

Langkah C: Bangun Modul (Compilation)

Kompilasikan kode sumber beserta seluruh shimming-nya menjadi satu berkas JavaScript tunggal:

npm run build

Hasil kompilasi akan ditaruh di folder dist/ dalam format:

  • dist/paddle-ocr-client.umd.js: Format UMD yang siap diimpor via <script src="..."> di HTML/PHP biasa.
  • dist/paddle-ocr-client.es.js: Format ES Modules untuk proyek modern (Vite, Webpack, React, Vue, dll.).

3. Struktur Berkas Proyek

  • main.js: Titik masuk utama (Entrypoint) yang membungkus PaddleOcrService menjadi kelas global browser PaddleOCRClient dan menyematkan patch sekuensial.
  • vite.config.js: Berisi pemetaan alias bundler dan konfigurasi library output.
  • browser-canvas-shim.js: Menjembatani fungsi canvas server ke HTML5 Canvas client.
  • browser-fs-shim.js: Menjembatani fungsi fs ke XMLHttpRequest browser.
  • browser-path-shim.js: Menjembatani fungsi manipulasi direktori ke string URL web.
  • browser-url-shim.js: Menjembatani fungsi pemetaan berkas URL Node.

4. API Reference

class PaddleOCRClient

Pustaka pembungkus (wrapper) utama untuk menjalankan deteksi & rekognisi teks PaddleOCR di dalam browser.

constructor(options)
  • options.verbose (boolean): Menampilkan log debugger di konsol browser (default: false).
  • options.maxSideLength (number): Skala sisi gambar maksimum untuk detektor OCR. Nilai yang lebih tinggi (seperti 2000) meningkatkan akurasi deteksi simbol/teks kecil, namun memakan lebih banyak memori (default: 2000).
async init(modelConfig)

Mengunduh model ONNX/ORT dan file dictionary kamus secara asinkron lewat HTTP dan memuatnya ke runtime WebAssembly.

  • modelConfig.detection (string): URL path file model deteksi ONNX/ORT (default: '/models/en_PP-OCRv3_det_infer.onnx').
  • modelConfig.recognition (string): URL path file model rekognisi ONNX/ORT (default: '/models/en_PP-OCRv3_rec_infer.onnx').
  • modelConfig.charactersDictionary (string): URL path file kamus karakter (default: '/models/en_dict.txt').

[!TIP] Berkas model ONNX dan ORT (teroptimasi FlatBuffers untuk browser) yang kompatibel dapat diunduh langsung dari repositori model resmi organisasi Anda: cty-paddle-ocr-models.

async recognize(imageInput)

Mengekstrak teks dan koordinat layout geometris dari input gambar/canvas.

  • imageInput (HTMLImageElement | HTMLCanvasElement | Blob | File | ArrayBuffer): Elemen gambar DOM, elemen canvas, blob file, file lokal, atau buffer biner gambar yang akan dipindai.
  • Return Value: Mengembalikan Promise yang menghasilkan objek berstruktur seperti berikut:
    {
      "text": "CRAFTTHINGY SHOP\nTOTAL: 15000\nTERIMA KASIH",
      "lines": [
        {
          "text": "CRAFTTHINGY SHOP",
          "box": {
            "x": 45,
            "y": 20,
            "width": 210,
            "height": 28
          },
          "words": [
            {
              "text": "CRAFTTHINGY",
              "box": { "x": 45, "y": 20, "width": 130, "height": 28 }
            },
            {
              "text": "SHOP",
              "box": { "x": 180, "y": 20, "width": 75, "height": 28 }
            }
          ]
        },
        {
          "text": "TOTAL: 15000",
          "box": {
            "x": 45,
            "y": 60,
            "width": 150,
            "height": 24
          },
          "words": [
            {
              "text": "TOTAL:",
              "box": { "x": 45, "y": 60, "width": 70, "height": 24 }
            },
            {
              "text": "15000",
              "box": { "x": 120, "y": 60, "width": 75, "height": 24 }
            }
          ]
        }
      ]
    }

5. Contoh Penggunaan (Code Examples)

Contoh A: Memindai Gambar dari Tag <img>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ort.min.js"></script>
<script async src="https://docs.opencv.org/4.5.4/opencv.js"></script>
<script>
  window.cv = window.Module = {
    onRuntimeInitialized: () => window.isOpencvReady = true
  };
  window.process = { env: { NODE_ENV: 'production' }, cwd: () => '/' };
  window.setImmediate = (fn, ...args) => setTimeout(fn, 0, ...args);
</script>
<script src="/js/paddle-ocr-client.js"></script>

<script>
  async function runOCR() {
    const ocr = new PaddleOCRClient({ verbose: true });
    await ocr.init({
      detection: '/models/en_PP-OCRv3_det_infer.onnx',
      recognition: '/models/en_PP-OCRv3_rec_infer.onnx',
      charactersDictionary: '/models/en_dict.txt'
    });

    const img = document.getElementById('my-image');
    const result = await ocr.recognize(img);
    console.log("Hasil pemindaian:", result.text);
  }
</script>

Contoh B: Memindai Halaman PDF (Menggunakan PDF.js)

async function scanPdfPage(pdfUrl, pageNum) {
  const loadingTask = pdfjsLib.getDocument(pdfUrl);
  const pdfDoc = await loadingTask.promise;
  const page = await pdfDoc.getPage(pageNum);
  
  const viewport = page.getViewport({ scale: 1.5 });
  const canvas = document.createElement('canvas');
  canvas.width = viewport.width;
  canvas.height = viewport.height;
  const context = canvas.getContext('2d');
  
  await page.render({ canvasContext: context, viewport: viewport }).promise;

  const ocr = new PaddleOCRClient();
  await ocr.init();
  
  const result = await ocr.recognize(canvas);
  console.log(`Teks Halaman ${pageNum}:`, result.text);
}

6. ModelManager API

Kelas ModelManager disediakan untuk berinteraksi langsung dengan repositori model resmi Anda di GitHub.

static async listAvailableModelsFromGithub()

  • Mengembalikan daftar seluruh berkas model (.ort, .onnx) dan dictionary (.txt) yang tersedia di repositori GitHub model Anda.
  • Contoh Penggunaan:
    import { ModelManager } from '@craftthingy-digital-innovation/cty-paddle-ocr';
    const models = await ModelManager.listAvailableModelsFromGithub();
    console.log(models); // [{ name: "PP-OCRv6_medium_det.ort", size: 62160320, downloadUrl: "..." }]

static async downloadModelFromGithub(fileName, destFolder)

  • Mengunduh berkas model tertentu dari GitHub LFS dan menyimpannya di folder server lokal secara offline. (Hanya didukung di lingkungan Node.js).
  • Contoh Penggunaan:
    import { ModelManager } from '@craftthingy-digital-innovation/cty-paddle-ocr';
    await ModelManager.downloadModelFromGithub('PP-OCRv6_medium_det.ort', './public/models');

7. Panduan Performa & Optimasi (Performance Guide)

A. Format Berkas Model (.ort vs .onnx)

  • Sangat Direkomendasikan: Gunakan model format .ort (FlatBuffers) untuk lingkungan browser.
  • Format .ort menonaktifkan optimasi grafis runtime bawaan ONNX (graphOptimizationLevel: 'disabled') sehingga memangkas waktu inisialisasi awal di browser hingga 3-5x lebih cepat dibanding .onnx.

B. WASM Multithreading

  • Untuk mengaktifkan akselerasi multi-core di browser, konfigurasikan server web Anda (seperti Apache/Nginx/CodeIgniter) untuk mengirimkan header HTTP berikut:
    Cross-Origin-Opener-Policy: same-origin
    Cross-Origin-Embedder-Policy: require-corp
  • Setel variabel lingkungan ONNX di JavaScript sebelum memproses gambar:
    ort.env.wasm.numThreads = navigator.hardwareConcurrency || 4;

English

This project is cty-paddle-ocr, a lightweight, high-performance, standalone PaddleOCR SDK designed for isomorphic execution (running anywhere JavaScript runs: Web browsers using WebAssembly and Node.js servers).

It has been decoupled from the external ppu-paddle-ocr and ppu-ocv packages. The entire OpenCV wrapper engine (cty-ocv) and ONNX session wrappers (cty-ocr) have been ported locally. It dynamically scales to run sequentially (with setTimeout yields) on single-threaded browser runtimes to prevent freezing, and concurrently (multi-threaded) on Node.js backends for high-performance server environments.

1. Architecture & Shimming Engine

The compiler bundles modules using Vite in Library Mode with custom aliases defined in vite.config.js. Below are the detailed shims applied:

  1. Canvas Shim (browser-canvas-shim.js): Reroutes @napi-rs/canvas methods (a native canvas library for Node) to browser-native canvas elements (HTMLCanvasElement, document.createElement('canvas'), and new Image()). This allows canvas elements to be created dynamically in the browser.
  2. Filesystem Shim (browser-fs-shim.js): Replaces Node's synchronous fs.readFileSync with a synchronous XMLHttpRequest configured with overrideMimeType('text/plain; charset=x-user-defined') to download raw binary ONNX models without corruption, bypassing browser parser errors.
  3. URL-Aware Path Shim (browser-path-shim.js): Patches POSIX path helpers to handle absolute URL paths (http:// or https://) and prevent double-slash (//) paths from being converted into single slashes.
  4. WASM Sequential Engine (main.js): Sets up asynchronous AI initialization (ort.InferenceSession.create(url)). Crucial Browser Optimization: Overrides processBoxesInParallel inside RecognitionService to process bounding boxes sequentially instead of concurrently, yielding with setTimeout(resolve, 10) before each run. This prevents concurrent WebAssembly inferences from locking up the browser's main GUI thread.

2. How to Install & Build

Step A: Preparation

Ensure you have Node.js installed. Navigate to the bundler directory:

cd D:\CraftThingy\client-side-paddle-ocr-project

Step B: Install Dependencies

Download the standard required dependencies:

npm install

Step C: Build the Bundle (Compilation)

Compile the source code and shims into a single JavaScript library file:

npm run build

The compiled output is created under the dist/ directory:

  • dist/paddle-ocr-client.umd.js (Universal Module Definition for script tags in legacy browsers or vanilla HTML/PHP).
  • dist/paddle-ocr-client.es.js (ES Modules for modern bundlers like Vite or Webpack).

3. Project Directory Structure

  • main.js: The primary entry point. Wraps PaddleOcrService into a global browser class PaddleOCRClient and hooks the sequential run patch.
  • vite.config.js: Defines the bundler alias mappings and library output config.
  • browser-canvas-shim.js: Redirects canvas operations to HTML5 Canvas.
  • browser-fs-shim.js: Routes Node fs calls to XMLHttpRequest.
  • browser-path-shim.js: Routes directory manipulation to standard web URLs.
  • browser-url-shim.js: Emulates URL mapping.

4. API Reference

class PaddleOCRClient

The primary library wrapper class to initialize and run PaddleOCR client-side inside the browser.

constructor(options)
  • options.verbose (boolean): Prints debug statements to browser developer tools console (default: false).
  • options.maxSideLength (number): Scaled limit of the maximum side length for the text detector. Larger values (e.g. 2000) increase accuracy for small/blurry characters but consume more memory (default: 2000).
async init(modelConfig)

Asynchronously downloads ONNX/ORT model binaries and character files over HTTP and compiles them into WebAssembly.

  • modelConfig.detection (string): URL path to the detection ONNX/ORT model file (default: '/models/en_PP-OCRv3_det_infer.onnx').
  • modelConfig.recognition (string): URL path to the recognition ONNX/ORT model file (default: '/models/en_PP-OCRv3_rec_infer.onnx').
  • modelConfig.charactersDictionary (string): URL path to the character dictionary text file (default: '/models/en_dict.txt').

[!TIP] The pre-converted ONNX and optimized ORT (FlatBuffers-serialized) model files can be downloaded from your organization's model repository: cty-paddle-ocr-models.

async recognize(imageInput)

Extracts text boundaries and text lines from a given graphical element.

  • imageInput (HTMLImageElement | HTMLCanvasElement | Blob | File | ArrayBuffer): The source image/canvas or file binary to scan.
  • Return Value: Returns a Promise resolving to the following populated schema:
    {
      "text": "CRAFTTHINGY SHOP\nTOTAL: 15000\nTERIMA KASIH",
      "lines": [
        {
          "text": "CRAFTTHINGY SHOP",
          "box": {
            "x": 45,
            "y": 20,
            "width": 210,
            "height": 28
          },
          "words": [
            {
              "text": "CRAFTTHINGY",
              "box": { "x": 45, "y": 20, "width": 130, "height": 28 }
            },
            {
              "text": "SHOP",
              "box": { "x": 180, "y": 20, "width": 75, "height": 28 }
            }
          ]
        },
        {
          "text": "TOTAL: 15000",
          "box": {
            "x": 45,
            "y": 60,
            "width": 150,
            "height": 24
          },
          "words": [
            {
              "text": "TOTAL:",
              "box": { "x": 45, "y": 60, "width": 70, "height": 24 }
            },
            {
              "text": "15000",
              "box": { "x": 120, "y": 60, "width": 75, "height": 24 }
            }
          ]
        }
      ]
    }

5. Code Examples

Example A: Scanning an Image element (<img>)

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ort.min.js"></script>
<script async src="https://docs.opencv.org/4.5.4/opencv.js"></script>
<script>
  window.cv = window.Module = {
    onRuntimeInitialized: () => window.isOpencvReady = true
  };
  window.process = { env: { NODE_ENV: 'production' }, cwd: () => '/' };
  window.setImmediate = (fn, ...args) => setTimeout(fn, 0, ...args);
</script>
<script src="/js/paddle-ocr-client.js"></script>

<script>
  async function runOCR() {
    const ocr = new PaddleOCRClient({ verbose: true });
    await ocr.init({
      detection: '/models/en_PP-OCRv3_det_infer.onnx',
      recognition: '/models/en_PP-OCRv3_rec_infer.onnx',
      charactersDictionary: '/models/en_dict.txt'
    });

    const img = document.getElementById('my-image');
    const result = await ocr.recognize(img);
    console.log("Scanned Text Output:", result.text);
  }
</script>

Example B: Scanning a PDF page (with PDF.js)

async function scanPdfPage(pdfUrl, pageNum) {
  const loadingTask = pdfjsLib.getDocument(pdfUrl);
  const pdfDoc = await loadingTask.promise;
  const page = await pdfDoc.getPage(pageNum);
  
  const viewport = page.getViewport({ scale: 1.5 });
  const canvas = document.createElement('canvas');
  canvas.width = viewport.width;
  canvas.height = viewport.height;
  const context = canvas.getContext('2d');
  
  await page.render({ canvasContext: context, viewport: viewport }).promise;

  const ocr = new PaddleOCRClient();
  await ocr.init();
  
  const result = await ocr.recognize(canvas);
  console.log(`Page ${pageNum} parsed text:`, result.text);
}

6. ModelManager API

The ModelManager class provides native utilities to interact directly with your official models repository on GitHub.

static async listAvailableModelsFromGithub()

  • Returns a list of all model weights (.ort, .onnx) and vocabulary dictionaries (.txt) hosted in your GitHub models repository.
  • Usage Example:
    import { ModelManager } from '@craftthingy-digital-innovation/cty-paddle-ocr';
    const models = await ModelManager.listAvailableModelsFromGithub();
    console.log(models); // [{ name: "PP-OCRv6_medium_det.ort", size: 62160320, downloadUrl: "..." }]

static async downloadModelFromGithub(fileName, destFolder)

  • Downloads a specific model file from GitHub LFS and saves it to a local storage path. (Server-side Node.js environment only).
  • Usage Example:
    import { ModelManager } from '@craftthingy-digital-innovation/cty-paddle-ocr';
    await ModelManager.downloadModelFromGithub('PP-OCRv6_medium_det.ort', './public/models');

7. Performance & Optimization Guide

A. Model File Formats (.ort vs .onnx)

  • Highly Recommended: Use the .ort format (FlatBuffers serialized graph) in client-side web browsers.
  • The .ort graph representation bypasses ONNX Runtime Web's graphic optimization step (graphOptimizationLevel: 'disabled'), loading the network in the browser 3x to 5x faster than conventional .onnx files.

B. WASM Multithreading

  • To unlock multi-core CPU inference inside web browsers, configure your hosting server (Apache/Nginx/Express) to serve the following headers:
    Cross-Origin-Opener-Policy: same-origin
    Cross-Origin-Embedder-Policy: require-corp
  • Initialize the ONNX thread pool size in your frontend JavaScript code:
    ort.env.wasm.numThreads = navigator.hardwareConcurrency || 4;

Asal Usul & Kredit / Origins & Credits

Bahasa Indonesia

Proyek ini dikembangkan oleh CraftThingy Digital Innovation (Alif Nurhidayat). Proyek ini dibangun di atas fondasi inovasi open-source berikut:

  1. Baidu PaddleOCR: Model deteksi & pengenalan teks kelas dunia yang menjadi inti dari sistem OCR ini.
  2. cty-paddle-ocr-models: Repositori model resmi kami tempat menampung dan mendistribusikan model ONNX/ORT secara mandiri.
  3. ONNX Runtime Web (Microsoft): Engine eksekusi WebAssembly yang menjalankan model neural network di browser.
  4. OpenCV.js: Pustaka pengolahan citra komputer yang menangani transformasi geometris dan cropping karakter.
  5. PDF.js (Mozilla): Pustaka rendering dokumen PDF yang memproses halaman dokumen menjadi frame canvas.

English

This project is developed by CraftThingy Digital Innovation (Alif Nurhidayat). It is built upon the following open-source projects and innovations:

  1. Baidu PaddleOCR: The world-class OCR system providing the core deep learning models for text detection and recognition.
  2. cty-paddle-ocr-models: Our official model repository hosting pre-converted ONNX and optimized ORT models.
  3. ONNX Runtime Web (Microsoft): The WebAssembly execution runtime that powers the model inference in browser clients.
  4. OpenCV.js: The computer vision engine handling character cropping and geometry conversions.
  5. PDF.js (Mozilla): The document rendering library enabling multi-page PDF scanning inside the browser canvas.