結論から:数万件のスキャン PDF を OCR する場合、ボトルネックは「どの OCR エンジンを選ぶか」だけではほとんどありません。事前の振り分け、並列処理、再開可能なタスクキューがあるかどうかが本質です。GUI で 1 件ずつ処理すると 1 万件に数週間かかりますが、本記事のパイプラインを 8〜16 コアの VPS や GPU Worker で回せば、同じ規模を数時間〜1〜2 日に圧縮できることが多い——「まず高速スクリーニング、次に精密 OCR、不良ページは隔離」という工程上のトレードオフを受け入れる前提です。
本記事は、アーカイブのデジタル化、法務書類、医療レポート、歴史論文、企業契約のスキャンなど、1 万〜10 万件以上のファイルを扱う場面向けです。キーワード:バッチ OCR、スキャン PDF 認識、ocrmypdf、PaddleOCR。認識結果を RAG に流す場合は、RAG PDF パースのベストプラクティスでインポート前の品質ゲートを確認してください——OCR はパイプラインの第一段階にすぎません。
2026 年 8 月 8 日時点で OCRmyPDF 公式ドキュメント、Tesseract、PaddleOCR を確認。
大量スキャン PDF の OCR が異常に遅く感じる理由
よくある失敗パターン:フォルダをデスクトップツールに放り込み、CPU 使用率 15%、ファン静か、一晩で 200 件。原因は次のように重なります:
- 直列処理——1 プロセスで順番に回し、多コアが遊ぶ。
- 事前チェックなし——30% は既にテキスト層があるのにフル OCR を実行。
- ファイル単位の並列のみ——800 ページの束が 1 Worker を占有し、小ファイルは起動コストばかり。
- 重い出力——毎ページの画像再圧縮とフォント埋め込み。
- チェックポイントなし——9,000 件目でクラッシュし、最初からやり直し。
数万件規模では、パイプライン設計がエンジン調整より 1 桁重要です。まず最速の実装パス、次にスケールアーキテクチャの順で説明します。
ステップ 0:事前振り分け——OCR 不要なファイルに手を出さない
OCR の前にディレクトリを一括スキャン(Python マルチプロセスまたは find | parallel):
- PyMuPDF /
pdfinfoでページごとのget_text()を集計。約 80 文字以上の読み取り可能ページはtext_layerとタグ付けし、出力にコピーして OCR をスキップ。 - 暗号化・破損 PDF は
quarantine/へ——キュー全体を止めない。 - 混合 PDF はページ単位でルーティング——大規模時の最大の時間節約。
法務プロジェクトの例:4.2 万件の PDF のうち 38% は既にテキスト層、12% は暗号化——実際に OCR が必要なのは約 50%。エンジン選定より先に、これだけで総時間が半減しました。
ヒント:CSV マニフェスト(パス、ページ数、タイプ、推定 OCR ページ数)を出力。スケジュールはファイル数ではなく OCR ページ数で組む。
今日すぐ動かす最速パス(1,000〜5,000 件)
8 コア Linux またはクラウド VPS がある場合:
ocrmypdf+ Tesseract をインストール(中国語はchi_sim/chi_tra)。GNU parallelまたはxargs -Pでファイル単位並列。並列度 ≈ CPU コア数 − 1。- フラグ:
--skip-text、低い--optimize、各 ocrmypdf 内は--jobs 1でネスト過負荷を回避。 - ローカル SSD の一時領域に書き出し、バッチ後に
rsyncでオブジェクトストレージへ——ネットワークマウントはスループットを殺す。
cat scan_only.txt | parallel -j 8 \
'ocrmypdf --skip-text --optimize 0 --language chi_sim+eng \
{} /data/ocr_out/{/.}.pdf'
Tesseract は数分でデプロイ可能。PaddleOCR は複雑な中国語で有利なことが多い——低信頼度ページへの 2 パス目に使い、全体の再実行は避ける。
1 万件以上のアーキテクチャ:キュー、Worker、再開
- キュー:Redis+RQ、Celery、またはクラウド Batch。タスク = 1 PDF またはページ範囲。
- 状態 DB:SQLite/Postgres に
file_hash、ステータス、リトライ、エンジンバージョン。 - スケールアウト:CPU バウンドな OCR では、複数の中規模 VPS が 1 台の巨大マシンより有利なことが多い。
- ページ単位並列:
pdftoppm→ ページキュー → 200 ページ超の束はテキスト層をマージ。 - GPU プール:PaddleOCR/Surya を別 Worker に。言語・レイアウトでルーティング。
最初から Kubernetes は不要です。多くのチームは 2〜4 台の VPS Worker で Docker Compose + Redis を運用:1 台がキューとメタデータ、残りは OCR 専用。
ツール比較:速度、中国語、検索可能 PDF
| スタック | 最適用途 | スループット | 注意点 |
|---|---|---|---|
| OCRmyPDF + Tesseract | 欧文中心、検索可能 PDF 出力 | CPU フレンドリー | 複雑な中国語レイアウトは弱い |
| PaddleOCR 自ホスト | 中国語/混在文書、表 | GPU でページ単位が高速 | PDF へのテキスト層マージは自前 |
| 商用 API | コンプライアンス、運用不要 | 弾力的 | 10 万ページのコスト |
最速 ≠ 最安:200 件の代表サンプルで精度 × 秒/ページ × 価格をベンチマークしてから決める。
さらに 30〜50% 速くする実践的ノブ
- 600 DPI ソースなら 300 DPI レンダリングを試す——契約書では十分なことが多い。
- OpenCV でノイズ除去・二値化(きれいな白黒スキャン)。
- 必要最小限の言語パックのみロード。
- ピクセル分散で空白・スタンプページをスキップ。
- 検索のみなら
.txt/.jsonlをエクスポート。PDF/A はアーカイブ層のみ。 - クラウド VM では
TMPDIRをローカル NVMe に。
速度と品質を両立する
バッチ後:0.5% をサンプリングして人手確認または CER チェック。ID 密集ページは正規表現検証。低信頼度ページを再キュー。検索インデックスに不良 OCR を入れるコストは、2 パス目のエンジン実行より高い。アーカイブ案件では監査ログ(誰が、いつ、どのエンジンバージョンで)を残す。
概算:5 万 OCR ページ
Tesseract 中位で約 5 秒/ページ:単スレッド約 69 時間。8 コアで約 8〜12 時間。2 台の 8 コア Worker で約 4〜6 時間。GPU PaddleOCR は 1〜3 秒/ページ——カード数にほぼ線形。100 ページの自社サンプルで pages_per_hour を測定してください。
コピーできるチェックリスト
- 再帰インベントリ + SHA256 重複排除マニフェスト。
- 事前チェック:
text_layer/scan/mixed/encrypted。 - エンキュー(OCR ページ数でバランス)。
--skip-textまたはページルーティングで並列 OCR。- 検索可能 PDF またはサイドカーテキスト + JSON メタデータ。
- サンプル QA + 低信頼度 2 パス目。
ocr_engine_version付きでアーカイブ(将来の再実行用)。
RAG 下流ではページタイプをメタデータに保持。長文脈コスト管理は Context Caching コストガイド も参照。
最後に
数万件のスキャンに銀の弾丸はない——再現可能な最速パスはある:事前チェックで無駄 OCR を半減 → キューでクラッシュ耐性 → Worker で CPU/GPU を飽和 → QA で不良ページを遮断。まずパイプラインを緑にし、エンジン調整はその後。
バッチ OCR で CPU が飽和?クラウドで Worker を回そう
数万ページは典型的なバッチ計算——ノート PC は 72 時間フルロードを嫌いますが、Linux VPS や GPU Worker なら水平拡張と再開が可能です。Cloud Mac でスクリプトをデバッグし、重い OCR はキュー後のノードへ。VPSSpark はデジタル化とナレッジベース構築向けのクラウド開発環境と VPS を提供しています。