- 后端
- AI 应用
- NLP
【免费下载链接】xberg
Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.
本篇技术指南基于仓库中的 C 语言示例 ocr_force_all_pages.md,讲解如何通过 xberg 的 C FFI 接口启用force_ocr,让已经带有原生文本层的 PDF 页面也逐页走 OCR 识别。读完本文,你将掌握 xberg C 绑定中"输入句柄 → 配置句柄 → 提取 → 释放"的完整调用链,理解force_ocr与ocr、ocr_strategy、force_ocr_pages、disable_ocr等配置项之间的语义关系,并能结合 e2e 契约测试验证该配置的实际效果。
场景与完整示例
该示例要解决的问题是:默认情况下,xberg 对已有可用文本层的 PDF 页面直接使用原生文本提取,不跑 OCR;而某些 PDF 的文本层质量差(例如扫描仪生成的"隐形文本层"),需要强制用 OCR 引擎重新识别每一页。为此,xberg 在提取配置顶层提供了force_ocr开关。
下面是文档中给出的完整 C 示例,它通过 JSON 字符串构造输入与配置,再调用xberg_extract完成提取:
#include <assert.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "xberg.h" int main(void) { // 1. 构造提取输入:从 JSON 反序列化为 ExtractInput 句柄 // kind=uri 表示按 URI 拉取文档;mime_type 显式指定为 application/pdf XBERGAlefHandle input_handle = xberg_extract_input_from_json("{\"kind\":\"uri\",\"mime_type\":\"application/pdf\",\"uri\":\"https://example.com/pdf/fake_memo.pdf\"}"); // 2. 构造提取配置:force_ocr=true 强制 OCR 每一页; // ocr 子配置指定启用 OCR、后端为 tesseract、语言为英文 XBERGAlefHandle config_handle = xberg_extraction_config_from_json("{\"force_ocr\":true,\"ocr\":{\"backend\":\"tesseract\",\"enabled\":true,\"language\":[\"eng\"]}}"); // 3. 执行提取,返回提取结果句柄 XBERGAlefHandle result = xberg_extract(input_handle, config_handle); // 4. 逐个释放句柄,避免内存泄漏 xberg_extract_input_free(input_handle); xberg_extraction_config_free(config_handle); xberg_extraction_result_free(result); return EXIT_SUCCESS; }示例中有两个关键 JSON:
| JSON | 作用 | 关键字段 |
|---|---|---|
| 输入 JSON | 描述"从哪里取文档" | kind: "uri"、mime_type: "application/pdf"、uri |
| 配置 JSON | 描述"如何提取" | force_ocr: true、ocr.enabled、ocr.backend、ocr.language |
其中uri指向的fake_memo.pdf在 e2e 环境中由 mock 服务器提供——见下文"契约测试如何验证"一节。
C FFI 调用链解析
该示例体现了 xberg C 绑定的标准调用范式,所有跨语言对象都以不透明句柄XBERGAlefHandle传递:
xberg_extract_input_from_json(json):把 JSON 反序列化为一个提取输入(支持uri与bytes两种 kind),返回输入句柄。xberg_extraction_config_from_json(json):把 JSON 反序列化为ExtractionConfig,返回配置句柄。xberg_extract(input, config):执行提取管线,返回结果句柄。xberg_extract_input_free/xberg_extraction_config_free/xberg_extraction_result_free:三者必须分别调用,负责释放 Rust 侧堆内存。
这些函数由 FFI 头文件xberg.h声明,该头文件位于 crates/xberg-ffi 子 crate 中,并配合 cbindgen.toml 从 Rust 源码生成,保证声明与实现一致。因此 C 侧使用者不需要了解 Rust 类型系统,只需 include 头文件并按句柄模型管理生命周期。
force_ocr 的配置语义(源码级说明)
force_ocr定义在核心提取配置结构体 ExtractionConfig 中,与它同属一组的还有几个 OCR 相关配置项,理解它们的组合关系才能正确使用:
/// Force OCR even for searchable PDFs #[serde(default)] pub force_ocr: bool, // 默认 false /// Force OCR on specific pages only (1-indexed page numbers, must be >= 1). #[serde(default)] pub force_ocr_pages: Option<Vec<u32>>, // 仅对指定页强制 OCR /// Disable OCR entirely, even for images. #[serde(default)] pub disable_ocr: bool, // 与 force_ocr 互斥各配置项的语义如下:
force_ocr: bool(默认false):置为true时,即使是可检索 PDF(已有文本层),每一页也都会走渲染 + OCR 流程。这是本文示例采用的方式,适合"整份文档的文本层都不可信"的场景。force_ocr_pages: Option<Vec<u32>>:按 1 起始页码只对列出的页面强制 OCR,未列出的页面走原生文本提取。从源码注释看,当force_ocr为true时该字段被忽略;重复页码会自动去重。适合"只有个别页质量差"的局部修正场景。ocr: Option<OcrConfig>:OCR 子配置(后端、语言、Tesseract 参数等)。注意源码文档明确说明:None表示对已有可用文本的文档不跑 OCR;但在默认的OcrStrategy::Auto下,完全没有文本层的扫描件仍会以默认设置走 OCR,避免返回空结果。因此示例中在force_ocr之外同时给出ocr配置,是为了显式指定后端为tesseract、语言为eng。disable_ocr: bool(默认false):彻底禁用 OCR(图片只返回元数据,PDF 只用原生文本)。源码注释指出它与force_ocr不能同时为true,配置校验会拒绝这种冲突组合。
与 ocr_strategy 的关系:三种"哪些页被 OCR"的模式
当force_ocr与force_ocr_pages都不生效时,决定页面级 OCR 行为的是ocr_strategy字段,其类型为 OcrStrategy:
pub enum OcrStrategy { /// OCR only when the native text layer fails a quality check (default). #[default] Auto, /// Additionally OCR every page that looks like a scan. ScannedPages { min_confidence: f64 }, }Auto(默认):仅当某页原生文本层未通过质量检查时才 OCR。源码注释特别指出:扫描仪附带的"隐形 OCR 副层"通常能通过质量检查,因此这类页面在Auto下会被原生提取,而不是重跑 OCR——这正是force_ocr存在的动机之一。ScannedPages { min_confidence }:额外识别"看起来像扫描件"的页面(依据栅格覆盖度、文本层是否隐形/缺失、图像编解码器与文档生成者等信号打分),达到置信度阈值(默认0.70,见 ocr.rs 中的DEFAULT_SCANNED_MIN_CONFIDENCE)的页面走 OCR,其余页面仍保留原生文本并参与Auto质量检查。它识别的是"文本层是否来自扫描仪",而不是文本层是否准确。
三种模式的定位可以概括为:Auto保守兜底、ScannedPages按扫描概率选择性重识别、force_ocr无差别全量重识别。若只需局部修复个别页,force_ocr_pages是成本最低的选择。
配置 JSON 的解析细节
示例中的配置 JSON{"force_ocr":true,"ocr":{"backend":"tesseract","enabled":true,"language":["eng"]}}在 Rust 侧反序列化为ExtractionConfig与OcrConfig,有几个值得注意的解析规则(实现见 crates/xberg/src/core/config/ocr.rs):
language字段同时接受字符串和数组:"language":"eng"与"language":["eng"]均可;形如"eng+deu"的字符串会按+拆分为多语言列表(兼容 Tesseract 传统写法)。这也是多语言 OCR 的标准写法。ExtractionConfig启用#[serde(deny_unknown_fields)]:JSON 中出现未定义字段(例如拼错force_ocr为force_ocr_all)会直接报反序列化错误,而不是静默忽略,这对排查配置问题非常友好。- 配置校验:
force_ocr与disable_ocr同真、ScannedPages.min_confidence超出[0.0, 1.0]或为非有限值等组合,会被配置校验逻辑拒绝。
契约测试如何验证这条链路
该 C 示例对应的契约夹具 ocr_force_all_pages.json 完整描述了一次可复现的端到端验证:
{ "id": "ocr_force_all_pages", "description": "Forces OCR on every PDF page even when a text layer exists", "call": "extract", "input": { "mock_responses": [ { "path": "/pdf/fake_memo.pdf", "status_code": 200, "headers": { "content-type": "application/pdf" }, "body_file": "../test_documents/pdf/fake_memo.pdf" } ] }, "assertions": [ { "type": "equals", "field": "results[0].mime_type", "value": "application/pdf" }, { "type": "contains_all", "field": "results[0].content", "values": ["bottles", "blankets", "laptops"] } ], "config": { "force_ocr": true, "ocr": { "enabled": true, "backend": "tesseract", "language": ["eng"] } } }夹具的工作方式:
- mock 服务器(
side_effects: server)在/pdf/fake_memo.pdf路径上返回测试 PDFfake_memo.pdf,使 C 示例中的https://example.com/...类 URI 可被本地拦截。 - 断言要求结果 MIME 类型为
application/pdf,且提取内容包含bottles、blankets、laptops三个词——这些词只能由 OCR 从扫描件页面中识别出来,从而证明force_ocr确实覆盖了"已有文本层"的判定逻辑。 - 文档站的 C 示例标注
level: typecheck,即生成代码会随 e2e 体系做编译级校验,保证 FFI 签名持续可用。
实用建议
- 何时用
force_ocr:整份 PDF 的文本层来自早期扫描仪、乱码比例高,或你希望用更强的后端(如示例中的 tesseract 英文识别)统一重识别时,使用force_ocr: true。 - 何时不该用:文本层质量正常的文档上全量 OCR 会额外承担逐页渲染与识别开销;此时优先考虑
ocr_strategy的ScannedPages模式,或用force_ocr_pages只处理已知有问题的页码。 - C 侧生命周期纪律:每个
*_from_json创建的句柄和xberg_extract返回的结果句柄都必须调用对应的*_free释放;示例中先执行xberg_extract再依次释放输入与配置句柄,是可复制的标准写法。
延伸阅读
- 手写 C 示例(手工维护、非自动生成):ocr_extraction.md、basic_usage.md
- C 示例的自动生成源:snippets-generated/c 目录,文件头部注明由 alef 生成,可用
alef e2e generate再生 - FFI 实现与头文件生成配置:crates/xberg-ffi
- 相关契约夹具:ocr_basic_config.json、ocr_dpi_config
- 后端
- AI 应用
- NLP
【免费下载链接】xberg
Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.
相关推荐
Xberg C FFI 实战:使用 extract API 对 HWPX 韩文办公文档进行独立文本提取
Xberg C FFI 实战:使用 extract API 对 HWPX 韩文办公文档进行独立文本提取 本篇技术指南围绕 Xberg(Rust 核心的 Poly
后端AI 应用NLPxberg C FFI 实战:用 extract 完成独立 PDF 文本提取(从 ExtractInput 到结果校验)
xberg C FFI 实战:用 extract 完成独立 PDF 文本提取(从 ExtractInput 到结果校验) 本文基于 xberg 仓库中自动生成的
后端AI 应用NLPxberg C FFI 实战:用 extract 接口提取 XLSX 电子表格内容
xberg C FFI 实战:用 extract 接口提取 XLSX 电子表格内容 xberg 以 Rust 为核心实现了多语言文档智能,并通过 crates/
后端AI 应用NLP
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考