PaddleOCR.js 浏览器端 OCR SDK 实战指南:架构、开发与部署全解析
2026/9/19 22:00:10 网站建设 项目流程

PaddleOCR.js 浏览器端 OCR SDK 实战指南:架构、开发与部署全解析

【免费下载链接】PaddleOCR飞桨多语言OCR工具包(实用超轻量OCR系统,支持80+种语言识别,提供数据标注与合成工具,支持服务器、移动端、嵌入式及IoT设备端的训练与部署) Awesome multilingual OCR toolkits based on PaddlePaddle (practical ultra lightweight OCR system, support 80+ languages recognition, provide data annotation and synthesis tools, support training and deployment among server, mobile, embedded and IoT devices)项目地址: https://gitcode.com/paddlepaddle/PaddleOCR

PaddleOCR.js 是飞桨 PaddleOCR 官方推出的浏览器端 OCR SDK 与演示应用,它将 PaddleOCR 的检测、识别产线以 TypeScript 重写,并基于 ONNX Runtime Web 与 OpenCV.js 实现在浏览器中直接完成文本检测与识别的全流程推理。本文以仓库内 paddleocr-js/README_cn.md 为骨架,结合 架构说明、开发指南、Monorepo 约定 与 SDK 源码,带你掌握项目结构、安装使用、双线程执行模型、自定义模型接入、可视化渲染以及完整的本地开发与发布流程。

项目概览:官方浏览器 OCR SDK 与演示应用

PaddleOCR.js 是 PaddleOCR 仓库下的一个独立 npm workspace,由两个核心部分构成,其目录结构如下表所示:

路径作用
packages/core/浏览器 SDK 源码;发布到 npm 时的包名为@paddleocr/paddleocr-js
apps/demo/依赖该 SDK 的 Vite 演示应用

SDK 与上层应用的分工非常清晰:SDK 负责 OCR 运行时初始化与推理编排(运行时初始化、执行后端选择、模型下载、推理会话创建、OCR 产线执行),而宿主应用仍需要负责部署响应头、静态资源托管与模型 URL 配置、Worker 打包支持,以及应用界面与可视化等职责。apps/demo就是这样一个承载 SDK 的宿主应用示例,可在浏览器中直接体验模型选择、后端切换与 OCR 可视化。

SDK 的运行时依赖集中在 packages/core/package.json 中,主要包括:

  • onnxruntime-web(^1.22.0):浏览器端 ONNX 推理引擎,负责加载并执行检测/识别模型;
  • @techstark/opencv-js(^4.10.0):浏览器端 OpenCV 实现,负责图像预处理与后处理;
  • clipper-lib:用于检测框多边形裁剪等几何计算;
  • js-yaml:用于解析产线 YAML 配置。

本地开发与演示:五分钟跑起来

安装依赖与启动演示

paddleocr-js/目录下执行:

npm install npm run dev:demo

其中npm run dev:demo会启动依赖 SDK 的 Vite 演示应用(开发服务器)。注意 Node.js 版本要求为>= 20.11(见 paddleocr-js/package.json 的engines字段)。

常用命令一览

根目录提供了一系列常用命令,覆盖构建、测试、类型检查与发布:

npm run build # 先构建 SDK 再构建 demo(显式拓扑顺序) npm run build:sdk # 仅构建 SDK(packages/core) npm run build:demo # 仅构建 demo 应用(apps/demo) npm run lint # ESLint 检查 npm run test # Vitest 单元测试 npm run typecheck # 对所有 workspace 执行类型检查(core + demo) npm run check # format:check → lint → build:sdk → typecheck → test → build:demo npm run clean # 删除所有 dist/ 目录 npm run release # 构建 SDK 并通过 changeset publish 发布

按 workspace 作用域执行:

npm run build --workspace packages/core npm run build --workspace apps/demo npm run dev --workspace apps/demo

各命令的语义可以在 paddleocr-js/package.json 的scripts字段中逐一确认。npm run check是一条全量质量门禁命令,完整串联了格式化检查、Lint、SDK 构建、类型检查、测试与 demo 构建,适合在提交前或 CI 中执行。

SDK 包布局与高层架构

源码目录结构

SDK 源码位于 packages/core/src/,按职责划分为多个子模块:

src/ ├── runtime/ — 推理运行时初始化(ONNX Runtime Web / OpenCV.js) ├── resources/ — 模型与资源管理(下载、tar 解析、模型资产校验) ├── models/ — 模型接线(检测/识别模型封装) ├── platform/ — 浏览器 / Worker 输入适配 ├── worker/ — Worker 传输层 ├── pipelines/ — 产线实现(OCR 产线、配置解析、运行时参数) ├── viz/ — 可视化(可选子路径) ├── types/ — 外部库类型声明 └── utils/ — 共享工具

高层产线入口:PaddleOCR.create()

整个 SDK 的高层产线入口是PaddleOCR.create()(实现见 packages/core/src/pipelines/ocr/index.ts),它负责协调:

  1. 运行时初始化(OpenCV.js 与 ONNX Runtime Web);
  2. 执行后端选择(auto/wasm/webgpu);
  3. 模型下载与资源校验;
  4. 推理会话创建;
  5. OCR 产线执行(检测 → 方向分类 → 识别)。

从源码可以看到,PaddleOCR.create(options)默认会自动执行initialize()(除非显式传入initialize: false),并支持传入worker: true{ worker: { createWorker } }切换执行模式。

双执行模式:主线程与 Worker

PaddleOCR.create()支持两种执行模式,这是 SDK 架构中最重要的设计之一:

  • 主线程模式:返回PaddleOCR,直接在调用线程上执行 OCR;
  • Worker 模式:返回WorkerBackedPaddleOCR,将 OCR 生命周期调用(init/predict/dispose)转发到独立 Worker,避免阻塞 UI 线程。

Worker 模式下的运行流程(详见 架构说明):

  1. PaddleOCR.create({ worker: true })解析 OCR 选项并创建WorkerBackedPaddleOCR
  2. WorkerBackedPaddleOCR通过WorkerTransportClient发送init/predict/dispose请求;
  3. OCR 产线层持有默认 Worker 工厂,指向 src/pipelines/ocr/worker-entry.ts;
  4. Worker 入口将通用 Worker 引导逻辑与 OCR 专用处理逻辑绑定;
  5. OcrPipelineRunner在 Worker 内运行 OpenCV.js、ONNX Runtime Web、模型加载、检测与识别;
  6. 结果和错误被序列化后传回主线程。

输入处理按环境拆分:主线程将浏览器输入(BlobImageBitmapImageDataHTMLCanvasElementHTMLImageElement)标准化为可传输的负载;Worker 端再将负载还原为cv.Mat等运行时输入。

Worker 模式有一个关键技术细节:SDK 使用包内的 Worker 路径(worker-entry.ts),并在内部显式关闭 ONNX Runtime Web 的 wasm proxy,避免双层 Worker 叠加,同时让包自身负责并发模型管理。

WASM 路径配置:ortOptions.wasmPaths

ONNX Runtime Web 在运行时需要 WASM 二进制。ortOptions.wasmPaths对两种执行模式统一生效,设置一次即可同时控制主线程和 Worker 两侧的 WASM 加载位置:

PaddleOCR.create({ ortOptions: { wasmPaths: "/assets/" } });

设置了wasmPaths时,两种模式都会从指定路径拉取 WASM。未设置时,两种模式的回退行为不同:

  • 主线程模式:ORT 通过使用方的打包工具解析 WASM(通常由打包工具把node_modules/onnxruntime-web/dist/下的.wasm文件拷贝到构建产物并自动改写 URL);
  • Worker 模式:SDK 回退到与构建时安装的 ORT 版本绑定的 CDN,并在控制台提示建议显式设置ortOptions.wasmPaths

因此,在 Worker 模式下建议显式设置ortOptions.wasmPaths,以保证两种模式使用同一套 WASM 版本。演示应用 apps/demo/src/main.ts 即使用了 CDN 路径https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/作为wasmPaths

快速开始:三行代码跑通 OCR

安装

npm install @paddleocr/paddleocr-js

最小示例

import { PaddleOCR } from "@paddleocr/paddleocr-js"; const ocr = await PaddleOCR.create({ lang: "ch", ocrVersion: "PP-OCRv5", ortOptions: { backend: "auto" } }); const [result] = await ocr.predict(fileOrBlob); console.log(result.items);

需要注意:predict返回的是OcrResult组成的数组(每张输入图像对应一项)。即使传入单个Blob/File,返回的也是长度为 1 的数组,请使用解构或results[0]取值。

构造方式与模型选择详解

方式一:直接参数

可通过直接参数指定模型,也可配置推理 batch size、ORT 选项等运行参数。

模型选择 —lang+ocrVersion

await PaddleOCR.create({ lang: "ch", ocrVersion: "PP-OCRv5" });

ocrVersion: "PP-OCRv6"会将受支持的lang映射到内置的PP-OCRv6_small检测/识别模型对。若需PP-OCRv6_tiny,请显式指定模型名:

await PaddleOCR.create({ textDetectionModelName: "PP-OCRv6_tiny_det", textRecognitionModelName: "PP-OCRv6_tiny_rec" });

模型选择 — 显式模型名:

await PaddleOCR.create({ textDetectionModelName: "PP-OCRv5_mobile_det", textRecognitionModelName: "PP-OCRv5_mobile_rec" });

自定义模型— 为检测 / 识别分别指定模型名与资源地址:

await PaddleOCR.create({ textDetectionModelName: "my_det_model", textDetectionModelAsset: { url: "https://example.com/models/my_det_model.tar" }, textRecognitionModelName: "my_rec_model", textRecognitionModelAsset: { url: "https://example.com/models/my_rec_model.tar" } });

自定义模型的包格式与校验行为

接入自有模型时必须满足以下约束(SDK 在初始化时会严格校验,不满足即报错,不会静默忽略):

  • 资源需为未压缩的标准 tar.tar)。SDK 按字节解析 tar,不对 gzip 压缩包解压;若 URL 指向.tar.gz等,通常会解析失败并报错;
  • tar 内必须包含inference.onnxinference.yml(可位于子目录中,按文件名匹配);
  • inference.yml必须能解析出model_name,且须与textDetectionModelName/textRecognitionModelName一致;在initialize加载模型后会进行校验。

初始化阶段的典型失败场景包括:下载失败、tar 中缺少条目、空资源、model_name缺失或不匹配、模型配置不完整、ONNX 会话创建失败等。

batch size 与 ORT 运行参数

await PaddleOCR.create({ lang: "ch", ocrVersion: "PP-OCRv5", textDetectionBatchSize: 2, textRecognitionBatchSize: 8, ortOptions: { backend: "wasm", wasmPaths: "/assets/" } });

方式二:产线配置(YAML)

SDK 兼容 PaddleOCR 风格的产线 YAML 配置:

import { PaddleOCR } from "@paddleocr/paddleocr-js"; const pipelineConfig = ` pipeline_name: OCR SubModules: TextDetection: model_name: PP-OCRv5_mobile_det batch_size: 2 TextRecognition: model_name: PP-OCRv5_mobile_rec batch_size: 6 `; const ocr = await PaddleOCR.create({ pipelineConfig });

pipelineConfig可以是 YAML 文本,也可以是解析后的对象。如果同时提供直接参数和pipelineConfig,则以直接参数为准。

从源码看(packages/core/src/pipelines/ocr/config.ts),YAML 文本会通过js-yaml解析并规范化为NormalizedPipelineConfig,支持pipeline_nametext_typeSubPipelinesSubModules等结构,并提供两个独立的解析工具函数:parseOcrPipelineConfigText(text)normalizeOcrPipelineConfig(config)。SDK 内置的默认产线配置(packages/core/src/pipelines/ocr/default-config.ts)展示了完整的字段结构,包括TextDetectionlimit_side_len: 64limit_type: minmax_side_limit: 4000thresh: 0.3box_thresh: 0.6unclip_ratio: 1.5等检测参数,以及TextRecognitionscore_thresh等识别参数。

预测 API:参数、输入类型与返回值

参数命名:同时支持 camelCase 与 snake_case

ocr.predict(image | images[], params?)同时接受 camelCase 命名和 PaddleOCR 风格的 snake_case 命名,参数对应关系如下:

camelCasesnake_case作用
textDetLimitSideLentext_det_limit_side_len检测输入图缩放边长限制
textDetLimitTypetext_det_limit_type限制类型(min/max
textDetMaxSideLimittext_det_max_side_limit最大边长限制
textDetThreshtext_det_thresh检测二值化阈值
textDetBoxThreshtext_det_box_thresh检测框过滤阈值
textDetUnclipRatiotext_det_unclip_ratio检测框扩展比例
textRecScoreThreshtext_rec_score_thresh识别置信度过滤阈值

这些字段在 PaddleOCRCreateOptions 中均有定义,且与 PaddleOCR 传统 snake_case 风格保持兼容。演示应用 apps/demo/src/main.ts 中给出的运行默认值可供参考:textDetThresh: 0.3textDetBoxThresh: 0.6textDetUnclipRatio: 1.5textRecScoreThresh: 0.1

输入类型

支持的image输入包括BlobImageBitmapImageDataHTMLCanvasElementHTMLImageElementcv.Mat。传入上述类型的数组可在一次调用中对多张图像做检测与识别。

⚠️ 注意:在 Worker 模式下,cv.Mat无法跨线程传输,因此不能作为 Worker 输入

返回值

返回Promise<OcrResult[]>。每个OcrResult包含:

  • image:该图源的尺寸{ width, height }
  • items:识别行(polytextscore);
  • metricsdetMsrecMstotalMsdetectedBoxesrecognizedCount—— 其中detectedBoxesrecognizedCount每张图统计;detMsrecMstotalMs表示整次predict()调用的耗时(传入多图时,数组中每一项上的这三个值相同);
  • runtime:请求的后端与各阶段 Provider 等元数据。

演示应用正是利用这些字段渲染识别结果列表(items)与性能指标(metrics),例如detected boxesrecognized lines、各阶段耗时等。

Worker 模式实战

在专用 Worker 中运行 OCR 产线,同时保持相同的高层 API:

import { PaddleOCR } from "@paddleocr/paddleocr-js"; const ocr = await PaddleOCR.create({ lang: "ch", ocrVersion: "PP-OCRv5", worker: true, ortOptions: { backend: "wasm", wasmPaths: "https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/", numThreads: 2, simd: true } });

Worker 模式的核心行为:

  • 使用包内的 worker 路径(worker-entry.ts),而不是 ONNX Runtime Web 的env.wasm.proxy
  • 启用worker: true时,包内部会强制关闭 ORT 的 wasm proxy;
  • 浏览器输入会先在主线程标准化,再传入 Worker 执行推理;
  • cv.Mat仅支持直接在主线程产线路径中使用;
  • Worker 模式不支持自定义fetch实现(worker: truefetch同时传入会直接抛出错误,见 index.ts)。

可视化:将 OCR 结果渲染为图像

SDK 提供可选的可视化子路径@paddleocr/paddleocr-js/viz,将 OCR 结果渲染为一张左右对比的合成图像:左侧为带有检测框叠加的原始图像,右侧为识别出的文字。

使用OcrVisualizer

import { OcrVisualizer } from "@paddleocr/paddleocr-js/viz"; const viz = new OcrVisualizer({ font: { family: "Noto Sans SC", source: "/fonts/NotoSansSC-Regular.ttf" } }); const blob = await viz.toBlob(imageBitmap, result); // 触发浏览器下载 const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "ocr_result.png"; a.click(); URL.revokeObjectURL(url); viz.dispose();

一次性便捷函数

import { renderOcrToBlob } from "@paddleocr/paddleocr-js/viz"; const blob = await renderOcrToBlob(imageBitmap, result, { font: { family: "Noto Sans SC", source: "/fonts/NotoSansSC-Regular.ttf" } });

使用注意:

  • viz 模块支持加载自定义字体,以正确渲染中日韩等文字(如上面示例中的 Noto Sans SC);
  • 可视化需传入单个OcrResult(单张图时取predict返回数组的首项,例如const [result] = await ocr.predict(image));
  • deterministicColor(index)同样从 viz 子路径导出,它根据数字索引生成稳定的 RGB 颜色,内部用作检测框和文字标签的默认配色函数;构建自定义可视化并需要与内置渲染器保持一致配色时,可直接调用。

演示应用 apps/demo/src/main.ts 就是利用OcrVisualizer.toBlob()将识别结果渲染成对比图展示在页面上的,其字体配置为远程加载的 PingFang SC 字体。

完整 API 参考

SDK 顶层导出(见 packages/core/src/index.ts)包括:

  • PaddleOCR.create(options)—— 创建 OCR 实例(默认自动初始化,可传initialize: false延迟初始化)
  • ocr.initialize()—— 手动初始化(下载模型、创建会话)
  • ocr.getInitializationSummary()—— 获取初始化摘要
  • ocr.predict(image | images[], params?)Promise<OcrResult[]>—— 执行预测
  • ocr.dispose()—— 释放资源
  • parseOcrPipelineConfigText(text)—— 解析产线配置文本
  • normalizeOcrPipelineConfig(config)—— 规范化产线配置
  • OcrVisualizer(来自@paddleocr/paddleocr-js/viz
  • renderOcrToBlob(来自@paddleocr/paddleocr-js/viz
  • deterministicColor(来自@paddleocr/paddleocr-js/viz

index.ts的导出列表可以看到,SDK 同时导出了大量类型:OcrResultOcrResultItemOcrResultMetricsInitializationSummaryDetModelConfigRecModelConfigOrtOptionsPaddleOCRCreateOptionsModelAsset等,便于 TypeScript 用户获得完整的类型提示。SDK 的exports字段将./viz作为独立子路径导出(见 packages/core/package.json)。

构建产物与发布

SDK 使用 Vite 的库模式构建(在packages/core中执行npm run build)。dist/下的构建产物包括:

  • index.mjs—— ESM 入口
  • index.d.ts—— 类型声明
  • viz.mjs—— 可视化子路径的 ESM 入口
  • assets/worker-entry-*.js—— 自包含的 Worker bundle(OpenCV.js + ORT JS 运行时)

自定义 Vite 插件libraryWorkerPlugin会对构建产物做后处理,以兼容 npm 分发场景:

  1. 将 Worker 资源的绝对路径改写为相对路径,使文件相对于 SDK 模块路径解析,而不是站点根路径;
  2. new Worker(new URL(STRING, import.meta.url))拆成 URL 变量与 Worker 构造,便于下游打包工具复制 Worker 文件,并避免被当作二次打包目标;
  3. 移除 Vite 内联到 Worker 产物中的 base64 WASM 二进制——在 Worker 模式下,ORT 会在运行时通过ort.env.wasm.wasmPaths加载 WASM(由使用方配置,或回退到与安装 ORT 版本绑定的 CDN),从而显著减小 Worker 文件体积。

开发阶段,demo 通过 Vitealias直接引用 SDK 源码,获得更好的 HMR 体验;生产构建时则通过 workspace 链接使用 SDK 预构建的dist/产物。

发布方面(详见 Monorepo 约定):

  • 版本由Changesets管理;demo 包在.changeset/config.json中被忽略,不作为 npm 发布目标;
  • npm run release会构建 SDK 并通过changeset publish发布;
  • packages/coreprepublishOnly会在npm publish/npm pack前自动执行构建。

工程化与测试策略

TypeScript 严格模式与代码规范

SDK 与 demo 都使用 TypeScript 严格模式,并配置了分级 ESLint 规则(详见 monorepo_cn.md):

  • packages/**/src/**/*.tsapps/**/src/**/*.ts使用typescript-eslintstrictTypeChecked规则集,并启用面向浏览器的全局变量;
  • packages/**/test/**/*.ts使用较轻的recommendedTypeChecked规则集(浏览器 + Node 全局),并放宽部分规则(例如no-unsafe-*no-explicit-any);
  • 配置文件(*.config.{js,ts})使用基础 ESLint 规则,同时启用 Node 与浏览器全局。

npm run typecheck会在所有 workspace 上执行tsc --noEmit。demo 在tsconfig.json里通过paths直接引用 SDK 源码,因此类型检查并不严格依赖先执行build:sdk

测试策略

SDK 使用 Vitest 作为测试框架(测试文件位于 packages/core/test/),测试策略包括:

  • 配置解析与注册表行为的单元测试(如ocr-config-branches.test.tsmodel-config.test.ts);
  • 面向浏览器平台辅助函数的 jsdom 测试(如platform-browser.test.tsruntime-ort.test.tsruntime-opencv.test.ts);
  • Worker 传输层与产线逻辑测试(如worker-client.test.tsworker-protocol.test.tsocr-worker-entry.test.tsworker-backed.test.ts);
  • 可视化模块测试(如viz-draw-boxes.test.tsviz-renderer.test.ts);
  • 公共 API 导出测试(public-api.test.tsbrowser-source.test.ts等)。

CI 默认不运行大规模真实模型推理,模型加载与真实推理通常依赖本地手动验证(例如通过 demo 应用)。

宿主应用的运行环境要求

使用 SDK 时,宿主应用仍需负责以下运行时环境相关事项:

  • 启用多线程 WASM 或 WebGPU 时所需的COOP/COEP 响应头Cross-Origin-Opener-Policy/Cross-Origin-Embedder-Policy,用于crossOriginIsolated上下文,例如演示应用根据self.crossOriginIsolated决定是否启用多线程);
  • ONNX Runtime Web 的环境选项:wasm 资源托管路径(wasmPaths)、线程数(numThreads)和 SIMD 开关;
  • 使用worker: true时,能够产出并加载 module worker 的构建工具或运行时配置;
  • 静态资源托管与模型 URL 配置。

演示应用 apps/demo/src/main.ts 中展示了线程数选择的参考逻辑:在crossOriginIsolated环境下使用Math.min(4, Math.max(1, hardwareConcurrency - 1))计算线程数,否则回退为单线程。

更多参考文档

  • 架构说明(中文) / 英文版
  • 开发指南(中文) / 英文版
  • Monorepo 约定(中文) / 英文版
  • SDK 包 README(中文) / 英文版

SDK 的核心能力建立在 ONNX Runtime Web(浏览器端 ONNX 推理)与 OpenCV.js(浏览器端图像处理)之上,这也是 PaddleOCR.js 能在纯浏览器环境中完成端到端 OCR 的技术基础。

【免费下载链接】PaddleOCR飞桨多语言OCR工具包(实用超轻量OCR系统,支持80+种语言识别,提供数据标注与合成工具,支持服务器、移动端、嵌入式及IoT设备端的训练与部署) Awesome multilingual OCR toolkits based on PaddlePaddle (practical ultra lightweight OCR system, support 80+ languages recognition, provide data annotation and synthesis tools, support training and deployment among server, mobile, embedded and IoT devices)项目地址: https://gitcode.com/paddlepaddle/PaddleOCR

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询