OSSのPDFツール比較:Stirling-PDF vs LibreOffice vs OCRmyPDF でPDF処理をセルフホスト
オープンソースラボ編集部 ・ 2026年6月13日
OSSのPDFツール比較:Stirling-PDF vs LibreOffice vs OCRmyPDF でPDF処理をセルフホスト
Adobe Acrobatは月$19.99/ユーザー、Small PDF・IlovePDFも月$6〜18と、PDFの変換・編集・OCRにはコストがかかります。Stirling-PDF(Docker製の多機能WebUI)・LibreOffice(オフィススイート)・OCRmyPDF(テキスト化)はOSSのPDF処理ツールです。セルフホストまたはCLIで無料・プライバシー安全にPDFを処理できます。
OSSのPDFツールを選ぶ理由
- コスト削減: Adobe Acrobat月$19.99 × 50名 = $1,000/月をゼロに
- プライバシー: 機密PDFを外部SaaSに送らずローカル・社内サーバーで処理
- バッチ処理: 数百〜数千のPDFを自動化スクリプトで一括処理
- CI/CDへの統合: PDF生成・変換をパイプラインに組み込む
- カスタマイズ: ウォーターマーク追加・ページ分割・フォームデータ抽出を自動化
主要ツールの概要
Stirling-PDF
複数のOSSライブラリ(Ghostscript・LibreOffice・Tesseract・PDFBox・qpdf)をバックエンドに持つ、PDF処理の多機能WebUIです。GitHubスター55k+。30種類以上のPDF操作(マージ・スプリット・圧縮・変換・OCR・ウォーターマーク・電子署名・フォーム抽出等)をブラウザから操作でき、REST APIも内蔵しているのでバックエンドからプログラムで呼び出せます。
# Stirling-PDFをDockerで起動
docker run -d --name stirling-pdf --restart unless-stopped -p 8080:8080 -v /opt/stirling-pdf/trainingData:/usr/share/tesseract-ocr/5/tessdata -v /opt/stirling-pdf/extraConfigs:/configs -v /opt/stirling-pdf/customFiles:/customFiles -v /opt/stirling-pdf/logs:/logs -e DOCKER_ENABLE_SECURITY=false -e INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false -e LANGS=ja_JP frooodle/s-pdf:latest
# または日本語OCR対応版
docker run -d --name stirling-pdf -p 8080:8080 -v $(pwd)/tessdata:/usr/share/tesseract-ocr/5/tessdata -e INSTALL_BOOK_AND_ADVANCED_HTML_OPS=true frooodle/s-pdf:latest
# 日本語OCRデータをダウンロード
docker exec stirling-pdf bash -c "wget -O /usr/share/tesseract-ocr/5/tessdata/jpn.traineddata https://github.com/tesseract-ocr/tessdata_best/raw/main/jpn.traineddata"
# Stirling-PDF REST APIをPythonから使用する例
import requests
STIRLING_URL = "http://localhost:8080"
# 複数PDFをマージ
def merge_pdfs(pdf_paths: list, output_name: str) -> bytes:
files = [('fileInput', (f'file{i}.pdf', open(p, 'rb'), 'application/pdf'))
for i, p in enumerate(pdf_paths)]
res = requests.post(
f"{STIRLING_URL}/api/v1/general/merge-pdfs",
files=files
)
return res.content
# PDFを圧縮
def compress_pdf(pdf_path: str, compression_level: str = "medium") -> bytes:
with open(pdf_path, 'rb') as f:
res = requests.post(
f"{STIRLING_URL}/api/v1/general/compress-pdf",
files={'fileInput': ('input.pdf', f, 'application/pdf')},
data={'optimizeLevel': compression_level} # low/medium/high/extreme
)
return res.content
# PDFをOCR処理してテキスト検索可能にする(日本語)
def ocr_pdf(pdf_path: str) -> bytes:
with open(pdf_path, 'rb') as f:
res = requests.post(
f"{STIRLING_URL}/api/v1/misc/ocr-pdf",
files={'fileInput': ('input.pdf', f, 'application/pdf')},
data={'languages': 'jpn', 'ocrType': 'normal'}
)
return res.content
# PDFをWordに変換
def pdf_to_word(pdf_path: str) -> bytes:
with open(pdf_path, 'rb') as f:
res = requests.post(
f"{STIRLING_URL}/api/v1/convert/pdf/word",
files={'fileInput': ('input.pdf', f, 'application/pdf')},
data={'outputFormat': 'docx'}
)
return res.content
# バッチ処理: フォルダ内の全PDFを圧縮
import os
from pathlib import Path
def batch_compress(input_dir: str, output_dir: str):
Path(output_dir).mkdir(parents=True, exist_ok=True)
for pdf_file in Path(input_dir).glob("*.pdf"):
print(f"圧縮中: {pdf_file.name}")
compressed = compress_pdf(str(pdf_file))
output_path = Path(output_dir) / pdf_file.name
with open(output_path, 'wb') as out:
out.write(compressed)
original_mb = pdf_file.stat().st_size / 1024 / 1024
compressed_mb = len(compressed) / 1024 / 1024
print(f" {original_mb:.1f}MB → {compressed_mb:.1f}MB ({(1 - compressed_mb/original_mb)*100:.0f}%削減)")
LibreOffice(CLIモード)
LibreOfficeはGUIオフィススイートとして有名ですが、libreoffice --headless でサーバー環境でのバッチ変換に使えます。Word・Excel・PowerPointからPDFへの変換が最も品質が高く、従来フォントを含む複雑なレイアウトの再現性が高い。
# LibreOfficeをDockerでインストール
docker run -it --rm -v $(pwd):/workspace ubuntu:22.04 bash -c " apt-get update && apt-get install -y libreoffice --no-install-recommends && libreoffice --headless --convert-to pdf /workspace/document.docx --outdir /workspace/output"
# Pythonでliboffice CLIを使ってバッチ変換
import subprocess
from pathlib import Path
def convert_to_pdf(input_path: str, output_dir: str) -> str:
'''Word/Excel/PowerPoint → PDF 変換'''
output = Path(output_dir)
output.mkdir(parents=True, exist_ok=True)
result = subprocess.run(
['libreoffice', '--headless', '--convert-to', 'pdf',
'--outdir', str(output), input_path],
capture_output=True,
text=True,
timeout=60
)
if result.returncode != 0:
raise RuntimeError(f"変換エラー: {result.stderr}")
# 出力ファイルパスを計算
input_name = Path(input_path).stem
return str(output / f"{input_name}.pdf")
# 例: フォルダ内の全.docxをPDFに変換
def batch_convert(input_dir: str, output_dir: str, extensions: list = ['.docx', '.xlsx', '.pptx']):
for ext in extensions:
for f in Path(input_dir).glob(f'*{ext}'):
try:
out = convert_to_pdf(str(f), output_dir)
print(f"✓ {f.name} → {Path(out).name}")
except Exception as e:
print(f"✗ {f.name}: {e}")
OCRmyPDF
スキャンPDF(画像PDF)にテキストレイヤーを追加してPDF検索・コピーを可能にするOSSです。GitHubスター13k+。TesseractをバックエンドにPDF/A形式への変換・ページの傾き補正・圧縮を行います。大量の紙帳票・契約書・領収書をデジタル化する業務に最適です。
# OCRmyPDFをインストール(Ubuntu)
apt-get install -y ocrmypdf tesseract-ocr-jpn
# 基本的なOCR処理(日本語)
ocrmypdf --language jpn input_scan.pdf output_ocr.pdf
# 傾き補正 + 品質最適化 + PDF/A変換
ocrmypdf --language jpn --rotate-pages --deskew --clean --optimize 1 --output-type pdfa scanned_contract.pdf output/contract_searchable.pdf
# バッチ処理(フォルダ内全スキャンをOCR化)
for f in /scans/*.pdf; do
base=$(basename "$f" .pdf)
ocrmypdf --language jpn --deskew --optimize 1 "$f" "/output/${base}_ocr.pdf"
echo "Done: $base"
done
# OCRmyPDFをPythonプロセスから呼び出してLLMに送る
import subprocess
import anthropic
import tempfile
import pdfplumber # pip install pdfplumber
def scan_pdf_to_text(pdf_path: str) -> str:
'''スキャンPDFをOCRして全テキストを抽出'''
with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as tmp:
tmp_path = tmp.name
# OCR処理
subprocess.run([
'ocrmypdf', '--language', 'jpn', '--deskew', '--optimize', '1',
pdf_path, tmp_path
], check=True, capture_output=True)
# テキスト抽出
with pdfplumber.open(tmp_path) as pdf:
text = '
'.join(page.extract_text() or '' for page in pdf.pages)
return text
def ask_about_contract(pdf_path: str, question: str) -> str:
'''契約書PDFについてClaude APIに質問する'''
contract_text = scan_pdf_to_text(pdf_path)
client = anthropic.Anthropic()
response = client.messages.create(
model='claude-sonnet-4-6',
max_tokens=2048,
messages=[{
'role': 'user',
'content': f'以下の契約書の内容を分析してください。
{contract_text}
質問: {question}'
}]
)
return response.content[0].text
機能比較表
| 比較項目 | Stirling-PDF | LibreOffice | OCRmyPDF |
|---|---|---|---|
| ライセンス | GPL-3.0 | MPL-2.0 | MPL-2.0 |
| WebUI | ✅ | ❌(CLI) | ❌(CLI) |
| REST API | ✅ | ❌ | ❌ |
| Office→PDF変換 | ✅ | ✅(高品質) | ❌ |
| スキャンOCR | ✅(Tesseract) | ❌ | ✅(専門) |
| PDF圧縮 | ✅ | ❌ | ✅ |
| PDF結合・分割 | ✅ | ❌ | ❌ |
| Docker対応 | ✅ | ✅ | ✅ |
PDF処理を自動化するパイプラインはDevOpsカテゴリ/categories/devopsのCI/CDツール比較も参照してください。PDFをLLMで分析するパターンはLLMツールカテゴリ/categories/llm-toolsにまとめています。
FAQ
Q. Stirling-PDFは社内のセキュリティポリシー上、外部にデータを送りますか?
A. セルフホストしたStirling-PDFは一切の外部通信を行いません。処理はすべてローカルのDockerコンテナ内で完結します。確認方法: docker inspect stirling-pdfでネットワーク設定を確認するか、DockerをInternalネットワークのみに接続させることでさらに確実に外部通信を遮断できます。-e DOCKER_ENABLE_SECURITY=trueを設定するとログイン認証が有効になり、社内ユーザーのみがアクセスできるよう制限できます。NginxでIPアドレス制限を追加することも推奨します。
Q. スキャンした日本語の契約書をOCR処理する際の精度はどのくらいですか?
A. Tesseract(OCRmyPDFのバックエンド)の日本語OCR精度は、スキャン品質と設定によって大きく変わります。精度が高い条件: ①スキャン解像度300dpi以上②文書が水平・傾きなし③フォントが明朝体・ゴシック体(標準的な印刷フォント)④背景が白で文字が黒。精度が低くなる条件: ①手書き文字(Tesseractは手書き認識が苦手)②特殊フォント・ロゴ・押印③コピーを重ねたような劣化スキャン。実測精度: 良質な印刷契約書のスキャン→漢字・ひらがな・数字で95%以上。スタンプ・手書き欄→50〜70%程度。精度を上げるにはtesseract_bestモデル(jpn.traineddataの精度最高版)を使い、前処理(画像の2値化・ノイズ除去)を追加します。
Q. LibreOfficeでWord→PDF変換したときに日本語フォントが崩れる場合の対処は?
A. フォント崩れの主な原因はDockerコンテナにWindowsフォントがないためです。対処法: ①Notoフォントをインストール: apt-get install -y fonts-noto-cjkでほとんどの日本語フォントをカバーできます②MS互換フォントをコンテナにコピー: 社内の場合、Windows PCからIPAフォント・源ノ角ゴシック等を取得してコンテナの/usr/share/fonts/にコピーしfc-cache -fを実行③フォントキャッシュの更新: Dockerビルド時にRUN fc-cache -fを実行。Dockerfileの例:
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y libreoffice fonts-noto-cjk fonts-noto-cjk-extra --no-install-recommends && fc-cache -f && rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["libreoffice", "--headless"]
Q. Next.jsアプリからPDFを動的生成するのにStirling-PDFは適していますか?
A. HTML→PDFの動的生成にはStirling-PDFより**Puppeteer・Playwright・または@react-pdf/renderer**の方が適しています。Stirling-PDFは「既存のファイルを変換・操作する」ツールであり、「HTMLテンプレートからPDFを生成する」用途は本来の設計外です。用途別の推奨:
// Next.js API Routeで請求書PDFを動的生成(react-pdf)
// npm install @react-pdf/renderer
import { renderToBuffer } from '@react-pdf/renderer';
import { Document, Page, Text, View, StyleSheet } from '@react-pdf/renderer';
const InvoicePDF = ({ invoice }: { invoice: Invoice }) => (
<Document>
<Page size="A4" style={{ padding: 40 }}>
<View style={{ marginBottom: 20 }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>請求書</Text>
<Text>請求番号: {invoice.number}</Text>
</View>
{/* ... */}
</Page>
</Document>
);
export async function GET(req: Request) {
const invoice = await getInvoice(req);
const buffer = await renderToBuffer(<InvoicePDF invoice={invoice} />);
return new Response(buffer, {
headers: {
'Content-Type': 'application/pdf',
'Content-Disposition': `attachment; filename="invoice-${invoice.number}.pdf"`,
},
});
}
Stirling-PDFは「ユーザーがアップロードしたPDFを圧縮・変換する」バックエンドとして活用し、動的生成は専用のPDFライブラリを使うのがベストプラクティスです。
まとめ
| ユースケース | 推奨ツール |
|---|---|
| PDF操作・変換の多機能WebUI | Stirling-PDF |
| Office→PDF高品質変換 | LibreOffice CLI |
| スキャンOCR・テキスト化 | OCRmyPDF |
| 動的PDF生成 | react-pdf / Puppeteer |