
LiteParse 浏览器端 WASM 解析实战在浏览器中运行 PDF 解析与自定义 OCR【免费下载链接】liteparseA fast, helpful, and open-source document parser项目地址: https://gitcode.com/GitHub_Trending/li/liteparse本文围绕 LiteParse 的 WebAssemblyWASM构建llamaindex/liteparse-wasm展开讲解如何在纯浏览器环境中完成 PDF 解析、文本/JSON/Markdown 输出、文档复杂度检测与自定义 OCR 引擎接入无需任何服务器或云端调用。读完本文你将掌握 WASM 包的安装、API 用法、完整配置项语义、能力边界以及底层 Rust 绑定crates/liteparse-wasm/src/lib.rs的实现原理可以直接在自己的前端项目中落地一套本地文档解析管线。一、WASM 构建的定位解析完全发生在本地LiteParse 是一个快速、开源的多格式文档解析器其核心解析引擎由 Rust 实现。官方文档明确说明WASM 包完全运行在浏览器中——不上传文档、不调用云服务PDF 字节经由Uint8Array直接喂给 WebAssembly 模块解析在用户设备上完成。这一点对隐私敏感场景合同、财务文件、个人证件尤其有价值。从仓库结构看WASM 绑定位于 crates/liteparse-wasm发布包定义在 packages/wasm/package.json包名llamaindex/liteparse-wasm采用 ESM 模块格式main指向pkg/liteparse_wasm.js。它复用了核心 crateliteparse的解析与渲染管线只是通过wasm-bindgen暴露出一层精简的 JS API并强制使用单线程模式详见下文能力边界。二、安装与快速开始npm install llamaindex/liteparse-wasm安装后即可在 TypeScript 项目中导入。核心流程分三步初始化 WASM 模块 → 构造LiteParse解析器 → 传入 PDF 字节调用parse()import init, { LiteParse } from llamaindex/liteparse-wasm; // Load the WASM module await init(); const parser new LiteParse({ ocrEnabled: false, outputFormat: json, }); // data is a Uint8Array (e.g. from input typefile or fetch) const bytes new Uint8Array(await file.arrayBuffer()); const result await parser.parse(bytes); console.log(result.text); console.log(result.pages[0]);几点实用说明file.arrayBuffer()适用于input typefile、拖拽上传或fetch下载的 PDF。得到的是原始字节必须包装为Uint8Array后再传入。result.text的形状由outputFormat决定默认 JSONresult.pages是逐页数组每页包含text、markdown、text_items带 bbox 的文本项、width/height等字段。完整的返回结构含totalPages、images、pageErrors、creator/producer等可对照 crates/liteparse-wasm/src/lib.rs 中的ParseResult定义。源码层面parse()最终调用核心的LiteParse::parse_input(PdfInput::Bytes(data))见 crates/liteparse-wasm/src/lib.rs也就是说传入的字节被当作PdfInput::Bytes变体直接送入核心解析器——这也是文件路径输入不可用的根源。三、能力边界什么可用什么不可用3.1 浏览器中可用PDF 解析输入为Uint8Array文件选择器用file.arrayBuffer()取字节即可。自定义 OCR通过ocrEngine回调接口接入见下文第四节。三种输出格式Text、JSON 与 Markdown。文档复杂度检测parser.isComplex(bytes)详见复杂度指南。提取类选项注解annotations、表单字段form fields、结构树structure tree、矢量图形vector graphics等详见提取选项指南。3.2 不可用与替代方案原生能力浏览器中的状态替代做法文件路径输入✗ 不可用一律传Uint8ArrayDOCX/XLSX/PPTX 转换✗ 不可用依赖 LibreOffice浏览器中不存在内置 Tesseract / HTTP OCR✗ 不可用改用自定义ocrEngine接口截图screenshots✗ 不可用WASM 构建未暴露该能力numWorkers并发✗ 未暴露WASM 为单线程解析imageOutputDir✗ 不可用无文件系统改用extractImages并从结果中读取字节其中numWorkers的限制可以直接在源码中得到印证WASM 配置转换函数into_core()在把所有 JS 配置映射到核心配置后末尾无条件执行cfg.num_workers 1见 crates/liteparse-wasm/src/lib.rs因此无论调用方传什么解析始终单线程运行。四、浏览器内 OCR自定义ocrEngine接口原生 Tesseract 与 HTTP OCR 后端在 WASM 构建中不可用。要启用 OCR需要传入一个带recognize方法的ocrEngine对象const parser new LiteParse({ ocrEnabled: true, ocrLanguage: eng, ocrEngine: { /** * param imageData PNG-encoded image bytes * param width rendered page width in pixels * param height rendered page height in pixels * param language e.g. eng * returns array of { text, bbox: [x1, y1, x2, y2], confidence } */ async recognize(imageData, width, height, language) { // e.g. call a Web Worker wrapping tesseract.js, or a remote OCR service return [ { text: Hello, bbox: [10, 20, 80, 40], confidence: 0.98 }, ]; }, }, });4.1 回调契约的源码级细节从 crates/liteparse-wasm/src/lib.rs 中的JsOcrEngine实现可以看到这个回调的精确约定imageData是 PNG 编码字节而非原始像素缓冲。绑定内部先把渲染管线产出的紧致灰度/RGB 缓冲通过liteparse::extract::encode_pixels_png编码为 PNG再包装成Uint8Array传给 JS源码注释明确说明这是为了兼容 tesseract.js、远程服务等消费编码图片的 OCR 库。参数顺序与类型recognize(imageData, width, height, language)width/height是渲染页面的像素尺寸language即配置里的ocrLanguage。返回值必须是 Promise绑定通过js_sys::Promise等待异步结果然后用serde_wasm_bindgen把返回数组解码为OcrResult结构{ text, bbox: [x1,y1,x2,y2], confidence, polygon? }见 crates/liteparse-wasm/src/lib.rs。若回调抛出、拒绝或返回非 Promise解析会报错。仓库自带的浏览器兼容性测试 scripts/browser-compat/wasm-test.html 提供了一个可参考的验证样例它在回调中校验imageData是否为Uint8Array、是否为合法的 PNG 签名89 50 4E 47 0D 0A 1A 0A、尺寸是否合法、language 是否匹配然后返回一条带 bbox 与 confidence 的文本并断言它被合并进解析结果。4.2 可插拔的 OCR 实现这个接口让 OCR 后端完全可替换既可以用 Web Worker 包装 tesseract.js 做本地识别也可以调用云端 OCR API注意这会引入网络请求与纯本地定位不同属于你自己的集成决策。唯一要求是返回文本 边界框 置信度的结构化结果。五、完整配置选项所有选项均为可选、使用 camelCase。下表为官方文档中的完整配置清单OptionTypeDefaultDescriptionocrLanguagestringeng传给 OCR 引擎的语言代码ocrEnabledbooleanfalse对文本稀疏页运行 OCR。WASM 中默认关闭——没有内置引擎缺少ocrEngine时该选项不生效ocrEngineobject—自定义 JS 侧 OCR 引擎见上文ocrFailureFatalbooleantrue设为false时OCR 失败返回部分结果而非直接抛错ocrHedgeDelaysMsnumber[][]远程ocrEngine的请求对冲request-hedging调度maxPagesnumber1000解析到该页数后停止targetPagesstring—如1-5,10,15-20dpinumber150OCR 渲染 DPIoutputFormatjson \| text \| markdownjsonresult.text的形状也接受md其他值直接抛错preserveVerySmallTextbooleanfalse保留通常会被过滤掉的极小文本skipDiagonalTextbooleanfalse丢弃偏离最近直角超过 2° 的旋转文本cropBox{ top, right, bottom, left }—每页四边裁剪的比例passwordstring—受保护 PDF 的密码quietbooleanfalse抑制进度日志imageModeoff \| placeholder \| embedplaceholderMarkdown 中图片引用的呈现方式也接受none表示offextractLinksbooleantrue在 Markdown 中渲染textkeepHeadersFootersbooleanfalse在 Markdown 中保留页眉/页脚emitWordBoxesbooleanfalse为每个文本项输出逐词子框5.1 关键选项的底层实现outputFormat的别名与校验WASM 绑定接受json、text、markdown以及mdmd被映射为OutputFormat::Markdown任何其他字符串都会抛出invalid outputFormat错误见 crates/liteparse-wasm/src/lib.rs。核心配置枚举OutputFormat定义在 crates/liteparse/src/config.rs。imageMode的别名none等价于off完全剥离图片引用embed会提取内嵌图片字节到result.images。核心语义在 crates/liteparse/src/config.rs 的ImageMode枚举中有完整注释Placeholder只输出占位引用而不返回像素字节Embed则同时启用图片提取effective_extract_images()中image_mode Embed隐式开启提取。targetPages的解析规则支持逗号分隔的单页与区间如1-5,10,15-20解析后排序去重区间起点大于终点、非法数字都会报错且总页数上限为 100,000防止1-4294967295这类参数触发超大内存分配。实现与单元测试见 crates/liteparse/src/config.rs。ocrHedgeDelaysMs为远程 OCR 引擎配置请求对冲。核心配置的注释crates/liteparse/src/config.rs说明给出如[0, 5000, 10000]的延迟序列时每个 OCR 任务会在每个延迟点发出重复请求并取最先成功者——以增加服务器负载换取慢节点场景下的更低尾延迟。cropBox每边取值在[0,1]表示从该侧裁剪的页面比例文本项只有完全落在剩余矩形内才会被保留。WASM 侧对应的CropBox结构同样以 top-left 为原点见 crates/liteparse-wasm/src/lib.rs。5.2 提取选项同样可用提取选项指南 中列出的选项——extractImages、extractVectorGraphics、extractAnnotations、extractFormFields、extractStructureTree、extractContentBounds、extractXfaPackets、extractTextMetadata、includeComplexity、renderFormFields——在 WASM 构建中全部可用保持相同的 camelCase 命名与默认false。它们逐一映射到核心LiteParseConfig的同名字段映射代码见 crates/liteparse-wasm/src/lib.rs。六、解析前的复杂度检测isComplex在处理前先用parser.isComplex(bytes)判断文档是否需要 OCR 或更重的处理是官方推荐的做法。isComplex是一次廉价的纯文本层扫描返回每页一组复杂度信号其中needsOcr判决与reasons列表可直接用于路由const parser new LiteParse({ ocrEnabled: false }); const bytes new Uint8Array(await file.arrayBuffer()); const pages await parser.isComplex(bytes); if (pages.some((p) p.needsOcr)) { // This document would benefit from OCR for (const page of pages.filter((p) p.needsOcr)) { console.log(Page ${page.pageNumber}: ${page.reasons.join(, )}); } }reasons的取值包括scanned、no-text、sparse-text、embedded-images、garbled、vector-text、annotation-text。底层实现见 crates/liteparse-wasm/src/lib.rs它调用核心的is_complex(PdfInput::Bytes(data))并返回PageComplexityStats[]——每个条目包含textLength、textCoverage、imageCoverage、fullPageImage单张覆盖 ≥90% 页面的栅格、isGarbled等信号。完整的复杂度指南见 复杂度指南。七、大文档的分批解析openBatchSessionWASM 堆有硬性内存上限一次性解析超大文档可能耗尽内存。为此绑定额外提供了openBatchSession(data, batchSize?)分批 API默认每批 25 页常量定义于 crates/liteparse/src/config.rs返回ParseSession循环调用session.nextBatch()直到返回undefined用完调用session.free()及时释放 WASM 侧内存wasm-bindgen 对象不会被垃圾回收。每个批次返回{ startPage, endPage, result }其中result与整文档parse()的结果结构完全一致共用同一个to_js_result转换函数。需要注意跨页处理页眉/页脚去重、图片去重只感知当前批次内的页面因此分批输出可能与整文档解析存在差异且批次必须逐个 await并发调用会触发 wasm-bindgen 的递归借用错误见 crates/liteparse-wasm/src/lib.rs 的注释说明。八、从源码构建 WASM 包如果不想直接用 npm 包可以自行构建。构建脚本定义在 packages/wasm/package.json需要 Rust 工具链与wasm-pack# from packages/wasm npm run build # web target (default) npm run build:bundler # for webpack/rollup/vite npm run build:nodejs # for node.js输出到pkg/目录。web目标配合patch-wasi-imports.js使用由于底层 pdfium 静态链接了 wasi-libc生成的 WASM 二进制内含wasi_snapshot_preview1::*系统调用导入浏览器无法解析构建脚本会在 JS glue 中注入这些系统调用的桩实现见 packages/wasm/scripts/patch-wasi-imports.js并把env模块中用于 setjmp/longjmp 的__c_longjmp声明为WebAssembly.Tag。Rust 侧还提供了一批 libc/pthread 桩getpid、pthread_mutex_*等见 crates/liteparse-wasm/src/wasi_stubs.rs。这些是 WASM 模块能在浏览器中成功实例化的关键工程细节。九、写在最后适用场景与限制WASM 构建让 LiteParse 的核心解析能力下沉到浏览器端非常适合需要隐私保护、离线可用或减少服务器负担的前端场景——文件选择、拖拽、fetch获取 PDF 后即可在本地完成结构化解析。但它也有清晰的边界不处理 Office 文档转换、没有内置 OCR 引擎需要自行实现ocrEngine回调、单线程解析、无文件系统。结合本仓库的证据链crates/liteparse-wasm/src/lib.rs 的绑定实现、packages/wasm/package.json 的发布配置、scripts/browser-compat/wasm-test.html 的端到端兼容性验证你可以在项目中放心接入并为后续排查问题保留完整的源码级依据。【免费下载链接】liteparseA fast, helpful, and open-source document parser项目地址: https://gitcode.com/GitHub_Trending/li/liteparse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考