首页
/ OCRmyPDF 下游打包与维护指南:v17 依赖架构、版本策略与发行版集成

OCRmyPDF 下游打包与维护指南:v17 依赖架构、版本策略与发行版集成

2026-09-08 22:19:33作者:吴年前Myrtle

导读

本文是写给 下游发行版打包维护者与平台移植者 的实操指南,围绕官方维护文档 docs/maintainers.md 展开。内容覆盖 OCRmyPDF v17 之后的可选依赖架构(Ghostscript 不再是唯一选择)、按功能拆分的运行时依赖清单、官方给出的依赖速查矩阵与最小/推荐安装组合、可用于 debian/control 的依赖声明样例,以及版本号管理、JBIG2 打包注意点、shell 补全安装等发行版集成细节。读完本文,你将能判断自己的目标发行版缺什么依赖、各依赖缺了会损失哪些能力,并知道如何为 OCRmyPDF 编写正确的依赖元数据与打包配置。


1. 这篇文档服务谁:packagers 与 porters

docs/maintainers.md 开篇即说明它面向两类人:

  • 为下游发行版打包 OCRmyPDF 的维护者(Debian、Fedora、Arch、Homebrew、FreeBSD 等);
  • 希望把 OCRmyPDF 移植到新平台的开发者。

文档的核心诉求是:帮打包者把「运行依赖」和「可选能力」区分清楚,避免为了一个可选项引入整套重型依赖,也避免因为缺少某个组件导致核心 OCR 功能静默降级而不自知。

在动手打包一个新平台之前,文档给出的一个关键经验是:先确认你的发行版能否打包 pikepdfdocs/maintainers.md)。pikepdf 与 OCRmyPDF 同作者,是一个 Python 与 C++14 混合的包,构建要求远比纯 Python 包苛刻。若 pikepdf 无法在目标平台上构建,OCRmyPDF 的移植也就无从谈起——pikepdf>=10 被列为 pyproject.toml 中的硬性运行时依赖。


2. v17 的架构级变化:Ghostscript 从「必需」到「可选」

::: versionchanged 17.0.0

维护文档用 versionchanged 17.0.0 标注了一个重要变更:Ghostscript 不再是严格必需的运行时组件docs/maintainers.md)。OCRmyPDF v17 为两大核心功能分别提供了可替换的代码路径:

功能 替代方案 说明
PDF 栅格化(转图片供 OCR) pypdfium2(Python 包) 可选路径 A
PDF 栅格化 ghostscript(系统二进制) 可选路径 B
PDF/A 转换 verapdf(校验)+ pikepdf(推测式转换) 可选路径 A
PDF/A 转换 ghostscript(系统二进制) 可选路径 B

文档同时强调:Ghostscript 仍是功能丰富、历史悠久的成熟工具,但近期版本引入了一些兼容性挑战,v17 正是通过替代代码路径来规避这些问题的。因此给用户的最佳体验建议是 GS 与替代工具都装上,运行时再按可用性选择(docs/maintainers.md)。

这一设计在源码层面有清晰印证:

  • src/ocrmypdf/_exec/_probe.py 提供了统一的 ToolProbe 探测机制,通过 version()/available() 判断某个外部可执行文件是否存在且版本可用,每个外部工具(Ghostscript、Tesseract、unpaper 等)各自在 src/ocrmypdf/_exec/ 下用 ToolProbe 描述自己的探测方式;
  • Ghostscript 路径在 src/ocrmypdf/_exec/ghostscript.py 中定义 PROBE = ToolProbe(program=GS),其中 Windows 上使用 gswin64c、其他平台使用 gs
  • 而 pypdfium2 路径是独立的 built-in 插件 src/ocrmypdf/builtin_plugins/pypdfium.py,只有当 pypdfium2 可用或用户显式指定 --rasterizer pypdfium 时才生效。

2.1 PDF 栅格化:pypdfium2 优先

维护文档将 pypdfium2 列为「优先项」。在 docs/installation.md 中有更直白的解释:pypdfium2 基于 Chromium 使用的 pdfium 库提供快速栅格化,性能通常优于 Ghostscript,因此可用时优先。从源码看,pypdfium2 是纯 Python 依赖(pyproject.tomlpypdfium2>=5.0.0),不需要系统包管理器参与,这也是它成为发行版友好选项的重要原因。插件实现里还专门加了线程锁——pdfium 库并非线程安全(src/ocrmypdf/builtin_plugins/pypdfium.py),打包者无需处理这一点,但它提醒我们该路径是进程内调用而非子进程。

2.2 PDF/A 转换:verapdf + pikepdf 的「推测式转换」

PDF/A 是 OCRmyPDF 的默认输出格式要求。v17 之前这条路只能靠 Ghostscript;v17 之后,OCRmyPDF 先用 pikepdf 直接添加元数据与 ICC 色彩配置做一次推测式(speculative)转换,再用 verapdf 校验产物是否符合 PDF/A 规范。只有校验通过才跳过 Ghostscript;校验不通过则回退到 Ghostscript 路径(docs/installation.md)。

这意味着 verapdf 缺失时 PDF/A 能力并不完全丧失(只要还有 Ghostscript),但 verapdf 缺失会堵死那条更快的路径。因此安装指南建议两个都装,以获得最佳兼容体验(docs/installation.md)。


3. 按功能拆分的完整运行时依赖清单

维护文档把 OCRmyPDF 的运行时依赖按功能角色划分,而不是简单罗列包名,这对打包者极其有用——它能直接回答「砍掉某个包会损失什么」:

3.1 PDF 栅格化(把 PDF 页转成图片供 OCR)

  • pypdfium2(Python 包)——或——
  • ghostscript(系统二进制)
  • 推荐:两者都装,兼容性最好。

3.2 PDF/A 转换

  • verapdf(系统二进制,配合 pikepdf 的推测式转换)——或——
  • ghostscript(系统二进制)
  • 推荐:两者都装

3.3 OCR 引擎

  • tesseract-ocr(系统二进制)——MVP 必需。

注意:Tesseract 依赖 SIMD 指令集获得性能,官方只在 ARM 与 x86_64 上提供完善支持,其他处理器架构上性能可能较差(docs/maintainers.md)。这一点对面向小众 CPU 架构的发行版尤其需要评估。

3.4 文本渲染(把 OCR 结果写进 PDF 文本层)

  • fpdf2(Python 包)——必需;
  • uharfbuzz(Python 包)——必需;
  • Noto 字体(系统包)——推荐。不同发行版包名不同:Debian/Ubuntu 为 fonts-noto,Fedora 为 google-noto-fonts-all;Homebrew 没有统一的 Noto 包,只有按字体族拆分的 cask(如 font-noto-sans)。

fpdf2uharfbuzz 承担的是文本层渲染引擎:fpdf2 负责生成 PDF 文本层,uharfbuzz 负责文本塑形(shaping),保证多语言(尤其非拉丁文字)正确排布。它们替代了旧版基于 hOCR 的渲染器(docs/installation.md)。OCRmyPDF 只内置一款拉丁字体,其余字形依赖系统安装的字体发现——这正是 Noto 字体被「推荐」而非「必需」但仍建议打包的原因。若缺字体导致某些字符无法渲染,OCRmyPDF 会提示具体字符码位(例如 'Ꮳ' U+13E3 CHEROKEE LETTER TSA),安装对应 Noto 字体族即可(docs/installation.md)。

3.5 其他可选依赖

  • unpaper(系统二进制)——可选,启用 --clean--clean-final
  • pngquant(系统二进制)——可选,启用 --optimize 2--optimize 3
  • jbig2enc(系统二进制)——可选,改善单色图像的压缩比。

这三者是「能力开关」而非基础依赖:缺了 unpaper,仅 --clean 相关选项报错;缺了 pngquant,仅较高档位的优化不可用;缺了 jbig2enc,输出文件会更大但流程照常。

3.6 Windows 打包者的额外注意点

在 Windows 上,OCRmyPDF 除 PATH 之外还会查注册表定位 Tesseract 与 Ghostscript(docs/maintainers.md)。对应的实现位于 src/ocrmypdf/subprocess/_windows.py:Ghostscript 读取 HKEY_LOCAL_MACHINE\SOFTWARE\Artifex\GPL Ghostscript 下的最新版本子键,Tesseract 读取 HKEY_LOCAL_MACHINE\SOFTWARE\Tesseract-OCRInstallDir 值。因此 Windows 安装包只要写对了注册表项,OCRmyPDF 即可自动发现,无需强制用户改 PATH。


4. 官方依赖速查矩阵(v17.0.0 引入)

维护文档在 versionadded 17.0.0 标记下提供了一张面向打包者的依赖决策矩阵docs/maintainers.md),把「功能 → 选项 1 → 选项 2 → 备注」浓缩成一张表:

Feature Option 1 Option 2 Notes
PDF rasterization pypdfium2 (Python) ghostscript (binary) pypdfium2 preferred when available
PDF/A conversion verapdf + pikepdf ghostscript verapdf validates speculative conversion
Text rendering fpdf2 (Python) - Required, replaces legacy hOCR renderer
OCR tesseract-ocr --ocr-engine none Can be skipped entirely

其中两条信息容易被忽略,值得展开:

  1. 文本渲染这一行没有「选项 2」——fpdf2 是唯一的文本层渲染实现,属于硬依赖。这与 pyproject.tomlfpdf2>=2.8.0uharfbuzz>=0.53.2 被列入强制 dependencies 一致。
  2. OCR 可以完全跳过——通过 --ocr-engine none 可以让 OCRmyPDF 只做图像清理、优化等处理而不调用 Tesseract(src/ocrmypdf/builtin_plugins/null_ocr.py 即该空引擎的实现)。因此对某些只想用其 PDF 处理管线、不想背 Tesseract 依赖的场景,存在合法的最小裁剪路径。

4.1 最小可行安装(MVP)与推荐安装

根据矩阵,文档给出两档打包基准(docs/maintainers.md):

最小可行安装:

  • tesseract-ocr +(pypdfium2 ghostscript)+ fpdf2

推荐安装(完整能力):

  • tesseract-ocr + pypdfium2 + ghostscript + verapdf + fpdf2 + unpaper + pngquant + jbig2enc

注意安装指南中的推荐清单比维护文档多了 uharfbuzz 与 Noto 字体,因为前者站在最终用户角度、后者站在打包最小依赖角度(docs/installation.md)。两处都强调:64 位版本受官方支持,32 位不受支持(Linux 上可能碰巧可用,Windows 上明确不支持)。

4.2 关键警告:PDF/A 能力可能整体消失

维护文档附了一条 warningdocs/maintainers.md):

如果既没有安装 Ghostscript,verapdf 也不可用,则 PDF/A 输出无法产生,输出将退化为普通标准 PDF。

这是一处相对旧版配置的破坏性变更——少数此前只靠 Ghostscript 之外机制输出 PDF/A 的罕见配置将受影响。打包时务必想清楚:你的依赖组合到底是「三选一都有」,还是「两头都空」。兜底判断完全由运行时探测驱动:Ghostscript 的探测在 src/ocrmypdf/_exec/ghostscript.py 中通过 ToolProbe 完成,探测不到就当作不可用,管线随即走对应降级分支。


5. 移植新平台的第一道关卡:pikepdf 之外还要过一遍版本门

维护文档反复强调 pikepdf 的可打包性是前提(见第 1 节)。除此之外,打包者还应当对照 pyproject.toml 逐条核对:

requires-python = ">=3.11"
dependencies = [
  "fpdf2>=2.8.0",
  "img2pdf>=0.5",
  "packaging>=20",
  "pdfminer.six>=20260107",
  "pi-heif",
  "pikepdf>=10",
  "Pillow>=10.0.1",
  "pluggy>=1",
  "pydantic>=2.12.5",
  "pypdfium2>=5.0.0",
  "rich>=13",
  "typing-extensions>=4.12; python_version < '3.13'",
  "uharfbuzz>=0.53.2",
]

其中有几条值得打包者专门注意:

  • Python 版本门槛为 3.11+,安装指南建议 3.12+(docs/installation.md);
  • 系统二进制类依赖(Tesseract ≥ 4.1.1、可选 pypdfium2 之外的 Ghostscript 9.54+ 等)无法由 pip 提供,必须由系统包管理器满足(docs/installation.md)。这是打包者与「pip 用户」责任边界所在:pip 安装并不能补全外部程序;
  • pi-heif 被刻意设计成可安全移除的依赖——源码注释直接写明 "maintainers: if this is removed, it will NOT break"(pyproject.toml),这与本文第 9 节的 HEIF/HEIC 降级机制呼应;
  • pdfminer.sixpikepdfPillowpydanticrich 等还有各自的 >= 下界,通常对应修复了特定缺陷的版本,不建议发行版为追新而盲目放宽,也不建议低于下界打包。

6. 版本管理:hatch-vcs、__version__ 与发行版修订号

版本号策略是发行版维护者与上游最容易起摩擦的点。维护文档指出(docs/maintainers.md):

  • OCRmyPDF 的版本由 hatch-vcs 从 Git 派生,Git 是「单一事实来源」。这种策略对某些发行版不友好——例如发行版往往需要在版本号上标注「本地打了补丁」之类的差异。
  • 若确需覆盖版本,文档给了两条出路:
    1. 直接修补 src/ocrmypdf/_version.py 中的 __version__ 变量;
    2. 设置环境变量 SETUPTOOLS_SCM_PRETEND_VERSION 为所需版本。

在本文对应的仓库快照里,可观察到的实际状态是:构建后端为 hatchling(pyproject.toml),pyproject.toml 中静态声明了 version = "17.8.1",而 src/ocrmypdf/_version.py 中同样持有 __version__ = "17.8.1"(ruff 配置也将其标注为自动生成文件,见 pyproject.toml)。docs/conf.py 则通过 importlib.metadata 读取已安装包的版本用于文档构建(docs/conf.py)。这意味着无论版本来自 Git 派生还是静态注入,最终对外可见的版本入口高度集中,发行版只需要保证该单一入口被正确改写,即可让 ocrmypdf --version、文档版本号等处保持一致。版本发布流程可参考仓库内的 src/ocrmypdf/RELEASE.md


7. jbig2enc:专利已过期,v17 起仅支持无损编码

jbig2enc 是一个 JBIG2 编码器,OCRmyPDF 只要能在 PATH 上找到它就会自动用于单色图像压缩(docs/maintainers.md)。历史上部分发行版因 JBIG2 内含专利算法而拒绝打包,但文档明确指出:

所有 JBIG2 专利已于 2017 年全部过期。

因此官方建议:条件允许时尽量把 jbig2enc 一并打包,以改善 OCRmyPDF 的压缩率。Debian/Ubuntu、Fedora 与 AUR 的官方包目前都省略了 JBIG2 编码器,OCRmyPDF 缺它仍可正常工作,只是输出文件更大;用户也可以从源码构建 jbig2enc,把它放到 PATH 上即可被自动识别(docs/installation.md)。构建步骤的细节见 docs/jbig2.md

jbig2enc 打包时还需注意一条 v17.0.0 的功能删减(note 标注,docs/maintainers.md):

有损 JBIG2 编码已在 v17.0.0 移除。此前该功能以「caveat emptor」(买者自负)方式提供,但由于存在有据可查的字符替换错误风险,官方决定移除该选项。现在只支持无损 JBIG2 压缩。

对应命令行选项 --jbig2-lossy 随之消失(docs/installation.md 再次以 warning 形式重申)。如果下游发行版仍停留在引用 --jbig2-lossy 的旧版本或旧文档,需要同步更新。


8. 可直接参考的 debian/control 依赖声明样例

维护文档直接给出了一段完整的 debian/control 依赖规格样例(docs/maintainers.md),这是全文最「拿来即用」的部分,完整摘录如下:

Depends:
 fonts-noto,
 fpdf2 (>= 2.8),
 ghostscript (>= 9.55),  # Not strictly required, but best user experience
 icc-profiles-free,
 img2pdf,
 python3-coloredlogs,
 python3-deprecation,
 python3-pdfminer (>= 20181108+dfsg-3),
 python3-pikepdf (>= 8.14.0),
 python3-pil,
 python3-pluggy,
 python3-reportlab,
 python3-rich,
 python3-uharfbuzz,  # Not currently in Debian
 tesseract-ocr (>= 5.0.0),
 zlib1g,
 ${misc:Depends},
 ${python3:Depends},
Recommends:
 cyclopts,   # Not currently in Debian
 jbig2
 paddleocr,  # Not currently in Debian
 pngquant,
 pypdfium2,  # Not currently in Debian
 unpaper,
 verapdf,    # Not currently in Debian
Suggests:
 ocrmypdf-doc,
 python-watchdog,

读这张表可以学到几层打包思路:

  1. Depends(硬依赖)被压缩到最小——凡是缺了会导致核心管线无法工作的项才放进来,例如 fpdf2(文本层渲染硬需求)、pikepdftesseract-ocr
  2. Recommends(推荐依赖)承载可选能力开关——jbig2pngquantunpaperverapdfpypdfium2 全部归入此档,对应「装了更好、不装可用」的定位,与第 3、4 节的矩阵完全对应;
  3. 注释坦诚标出「Not currently in Debian」——如 python3-uharfbuzzcycloptspaddleocrpypdfium2verapdf,说明这是一份「上游理想清单」,下游具体发行版需要结合自身仓库现状取舍;
  4. 版本号下界与安装指南呼应——fpdf2 >= 2.8ghostscript >= 9.55tesseract-ocr >= 5.0.0 等与 docs/installation.md 列出的最低版本要求一致(Tesseract 官方要求 4.1.1+,样例进一步约束到 5.x,属发行版自身的收紧策略)。

值得强调:ghostscript (>= 9.55) 行内注释写着「Not strictly required, but best user experience」——这是 v17 依赖策略的缩影:Ghostscript 从 Depends 的语义中心退为「增强体验」,但发行版若完全省略它,就必须确保 pypdfium2/verapdf 组合能覆盖栅格化与 PDF/A 两条路径(见 4.2 的降级警告)。


9. 其他发行版集成事项

9.1 Shell 补全必须随包安装

维护文档提醒:请务必安装命令行补全脚本,具体位置见安装文档(docs/maintainers.md)。对应文件就在仓库的 misc/completion/ocrmypdf.bashmisc/completion/ocrmypdf.fish。安装指南给出的安装位置(docs/installation.md):

  • bash:将 ocrmypdf.bash 复制为 /etc/bash_completion.d/ocrmypdf
  • fish:将 ocrmypdf.fish 复制到 ~/.config/fish/completions/ocrmypdf.fish

bash 版补全大概率兼容 zsh,但官方尚未确认——zsh 发行版打包时需自行验证。

9.2 32 位 Linux 支持:不承诺、不设障

只要全部依赖仍有 32 位版本可用,OCRmyPDF 在 32 位 x86/ARM 上「应该能继续工作」,但官方明确不在 32 位平台上测试docs/maintainers.md)。安装指南的措辞更强硬:不支持任何 32 位系统,包括 32 位 Python 与 Windows 上的 32 位 Ghostscript(docs/installation.md)。加上 Tesseract 的 SIMD 依赖(见 3.3),32 位或小众架构的打包者需要对性能和稳定性有合理的预期管理。

9.3 HEIF/HEIC:可移除、可优雅降级

OCRmyPDF 默认安装 pi-heif(PyPI 包),用于在命令行把 HEIF/HEIC 图片转成 PDF(docs/maintainers.md)。如果发行版没有该库,可以安全地将其排除——OCRmyPDF 会自动优雅降级,只是失去 HEIF/HEIC 输入支持。源码侧的证据是 pyproject.tomlpi-heif 依赖旁的那句维护者注释:移除它不会破坏构建,这是上游刻意留给发行版的裁剪空间。


10. 打包自查清单

把维护文档的内容收敛成一份可执行的自查清单,供打包与发布前逐项核对:

  1. 前提关卡:能否打包 pikepdf?(Python + C++14,构建要求苛刻)
  2. 栅格化路径:是否提供了 pypdfium2(Python)与/或 ghostscript(系统二进制)?推荐两者皆备。
  3. PDF/A 路径:是否提供了 verapdf + pikepdf 与/或 ghostscript?⚠️ 若 GS 与 verapdf 都不在,PDF/A 输出将退化为普通 PDF。
  4. OCR 路径:是否提供 tesseract-ocr?若明确不需要 OCR,是否已通过 --ocr-engine none 验证空引擎流程可用?
  5. 文本层渲染:是否提供 fpdf2(必需)与 uharfbuzz(必需)?是否随包带上/推荐 Noto 字体以获得完整字形覆盖?
  6. 能力开关:unpaper(--clean/--clean-final)、pngquant(--optimize 2/3)、jbig2enc(单色压缩)是否至少进入 Recommends
  7. 版本一致性:是否只改 src/ocrmypdf/_version.py__version__(或使用 SETUPTOOLS_SCM_PRETEND_VERSION),保证 --version 与文档版本一致?是否已声明本地补丁修订号?
  8. JBIG2 合规:若打包 jbig2enc,确认仅支持无损模式,--jbig2-lossy 在 v17 已移除。
  9. 补全脚本:bash/fish 补全是否随包装到了系统路径?
  10. 架构声明:是否明确 32 位不受官方测试支持,Windows 注册表探测路径(Artifex/Tesseract-OCR)是否被安装器正确写入?

结语:把「依赖」翻译成「能力」,是维护文档的核心方法论

docs/maintainers.md 表面上是一份依赖清单,实则提供了一套以功能角色为纲的依赖决策方法:每引入或剔除一个组件前,先问它服务的是「栅格化」「PDF/A」「OCR」「文本层渲染」中的哪条链路,再对照官方矩阵判断是否会触达降级分支(尤其是 PDF/A 全线缺失的警告)。这种「依赖 = 能力」的视角,配合 pypdfium2/verapdf 等 v17 新路径的源码佐证,能让发行版在依赖裁剪、能力保留与用户预期管理之间做出可解释的取舍。对想要移植或打包 OCRmyPDF 的维护者而言,本文覆盖的自查项就是一份与上游对齐的验收基线。

提示:以上实现细节均可在仓库中对照验证——维护指南见 docs/maintainers.md,安装与依赖下限见 docs/installation.md,打包元数据见 pyproject.toml,外部工具的探测与执行见 src/ocrmypdf/_exec/,Windows 注册表发现逻辑见 src/ocrmypdf/subprocess/_windows.py,补全脚本见 misc/completion/

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391