mcpField
M
markitdown-ocr

markitdown-ocr

github.com/full-stack-skillsドキュメント248 回インストール4 週間前に更新
リポジトリ

markitdown-ocr について

markitdown-ocr プラグインの利用ガイドで、MarkItDown による PDF、DOCX、PPTX、XLSX 変換へ LLM ビジョン OCR を追加します。スキャンページや埋め込み画像向けに、互換クライアントやプロンプトの設定、問題の切り分けを案内します。

主な機能

  1. 01PDF、DOCX、PPTX、XLSX の OCR
  2. 02OpenAI 互換のビジョンクライアント利用
  3. 03OCR プロンプトのカスタマイズ
  4. 04Markdown 出力で OCR ブロックを保持
  5. 05プラグイン設定とトラブルシューティング

活用シーン

  1. 01スキャン PDF からテキストを抽出
  2. 02文書内画像の文字を認識
  3. 03ローカルまたは Azure の OCR バックエンド設定
  4. 04OCR 出力がない場合の原因調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/full-stack-skills/document-skills --skill markitdown-ocr

インストール後、Claude Code で/markitdown-ocrを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
examples/advanced/
cost-and-concurrency.md
scenarios.md
examples/backends/
azure-and-local.md
examples/basic/
first-ocr.md
references/backends/
compatible-clients.md
references/plugin/
internals.md

詳細

MarkItDown OCR(LLM Vision)完全ガイド

用途:LLM がこのスキルを使って markitdown-ocr プラグインを正しく設定して呼び出し、PDF/DOCX/PPTX/XLSX 内の埋め込み画像やスキャンページから OCR 抽出を行えるようにします。

オフラインの基準:packages/markitdown-ocr/ の main ブランチ(2026-08 時点)に基づきます。 「プラグインが現在 X に対応しているか/パラメーター名が変更されたか」に関する質問は、公式 README とソースコードを基準にしてください:

  • ソースコード:packages/markitdown-ocr/src/markitdown_ocr/
  • エントリーポイント:_plugin.py
  • OCR サービスの抽象化:_ocr_service.py

このスキルを使う場面

✅ このスキルを使う場面(LLM Vision OCR/スキャン文書/埋め込み画像):

  • ユーザーが「スキャンした PDF をどうやって Markdown に変換するのか」と尋ねた場合(元の PDF に選択可能なテキストがない)
  • ユーザーが「PPT/Word/Excel に埋め込まれた画像から、どうやって文字を抽出するのか」と尋ねた場合
  • ユーザーが GPT-4o/GPT-4o-mini/Claude/Gemini を使って OCR を行いたい場合
  • ユーザーが「Azure OpenAI で markitdown-ocr をどう設定するのか」と尋ねた場合
  • ユーザーが「markitdown-ocr プラグインをどうインストールして使うのか」と尋ねた場合
  • ユーザーがローカルで OCR を行いたい場合(vLLM/Ollama を使用)

❌ このスキルを使わない場面:

  • 通常の CLI の使い方だけを知りたい場合(画像内の文字は不要で、PDF/DOCX を変換するだけ)→ markitdown-cli
  • ユーザーが「MarkItDown とは何か/どの形式に対応しているか/どれを選べばよいか」と尋ねた場合 → markitdown-awesome
  • ユーザーが「Azure Document Intelligence をどう設定するのか」と尋ねた場合 → markitdown-cli(MarkItDown に組み込まれたバックエンドであり、この OCR プラグインではありません)
  • ユーザーが「PDF をプレーンテキストに変換するにはどうすればよいか」と尋ねた場合(textract のほうが適しています)→ markitdown-awesome に案内します(references/ecosystem/alternatives.md に markitdown/textract/unstructured/pandoc/docling の比較があります)

⚠️ 判断が曖昧な場合:

  • ユーザーが「PDF を Markdown に変換したが、画像内の文字がない」と言った場合 → デフォルトで OCR プラグインの手順を案内します(このスキル)
  • ユーザーが「LLM で表を抽出したい」と言った場合 → OCR で対応できますが、表の精度が重要な場合は Azure Document Intelligence を優先します
  • ユーザーがすでに別の OCR(Tesseract/PaddleOCR)を使っている場合 → このスキルの対象外です。ツールの比較を案内してください

ワークフロー

OCR に関する質問に回答する際は、毎回次の手順に沿って進めます。

Step 1 — 文書の種類とユーザーの目的を確認する
  • 入力形式:PDF/DOCX/PPTX/XLSX(このスキルはこの 4 種類のみを対象とします)
  • 文字の位置:埋め込み画像/ページ全体のスキャン/両方
  • LLM の選択肢:OpenAI/Azure/Gemini/ローカル
  • コストの予算:高コストか低コストか(gpt-4o と gpt-4o-mini)
Step 2 — 環境を確認する
pip show markitdown-ocr openai | grep -E '^(Name|Version)'
markitdown --list-plugins | grep ocr

どちらも出力があるはずです。

Step 3 — Python API の形式を選択する
  • OpenAI:MarkItDown(enable_plugins=True, llm_client=OpenAI(), llm_model="gpt-4o")
  • Azure OpenAI:AzureOpenAI(...) に置き換え、azure_endpoint/api_version を渡します
  • ローカル vLLM/Ollama:OpenAI(base_url=..., api_key=<your-token>)(ローカルサービスでは通常、キーは検証されません)
  • Gemini:OpenAI(base_url=..., api_key=<your-key>)
Step 4 — プロンプトを決める
  • デフォルトのプロンプト(プラグインに組み込み済み):「すべてのテキストを抽出 … レイアウトを維持 … 解説は不要」
  • 表を重視する場合:「表のレイアウトを Markdown のパイプで維持」を追加します
  • テキストのみの出力を重視する場合:「説明、要約、コメントはしないでください」を追加します
Step 5 — 自己チェックして実行する

Validation 自己チェックリストと照らし合わせます。

Step 6 — 結果を処理する
  • 出力に *[Image OCR]…[End OCR]* ブロックが含まれている → 成功です
  • 表示されない → プラグイン一覧、クライアント、モデル名を確認します(詳しくは §8 のトラブルシューティングを参照)

Validation(自己チェックリスト)

OCR に関する質問に回答する前後に、毎回確認します。

  • ユーザーは markitdown-ocr をインストールしていますか?(pip show markitdown-ocr)
  • ユーザーは OpenAI 互換 SDK をインストールしていますか?(openai/azure-openai/カスタム)
  • ユーザーは OPENAI_API_KEY(または同等の認証情報)を設定していますか?
  • Python コードで enable_plugins=True、llm_client、llm_model のすべてを指定していますか?(3 つのうち 1 つでも欠けると OCR はスキップされます)
  • モデルは vision に対応していますか?(gpt-3.5-turbo のようなテキスト専用モデルは使用できません)
  • Azure OpenAI を使用する場合、azure_endpoint の末尾に / がなく、api_version は有効ですか?
  • 機密文書を処理する場合、クラウド API ではなくプライベートなバックエンド(vLLM/Ollama)を推奨していますか?
  • CLI に --llm-client/--llm-model を設定できると誤って約束していませんか?(これら 2 つの CLI オプションは存在せず、Python でラップする必要があります)

Gotchas

按命中频率从高到低:

  1. CLI 没有 --llm-client / --llm-model — 任何"命令行直接启用 OCR"的说法都是错的。要么写 Python 包装,要么告诉用户走 Python API。__main__.py 的 argparse 注册表确认。
  2. enable_plugins=True 漏写 — MarkItDown 默认 enable_plugins=False,插件根本不会注册。必带。
  3. 漏 llm_client 或 llm_model — 插件"仍会注册"(无 OCR service),但实际转换静默跳过 OCR。检查清单:三个参数必须都给。
  4. LLM 失败被静默吞掉 — _ocr_service.py::extract_text 把异常转成 OCRResult(text="", error=str(e));插件的 convert() 继续,不抛。表现:某张图的 OCR 块缺失,但文档其它部分 OK。没有任何 stderr 警告。
  5. PPTX 描述优先于 OCR — 若 LLM 返回了"图像描述",OCR 仅作 fallback。这意味着:同一张图,不同调用可能得到不同文本(描述 vs OCR)。
  6. XLSX 位置上下文丢失 — 图片被统一追加在数据表后(### Images in this sheet:),不与行交错。表格密集场景慎用。
  7. 扫描 PDF 整页 300 DPI 渲染 — 比"嵌入小图"贵很多;50 页扫描件 ≈ 50 次 vision 调用,token 成本高。
  8. OCR 块靠正则识别 — 输出格式 *[Image OCR]\n…\n[End OCR]* 是公开契约;后处理依赖它时,改了插件源码会让正则失效。
  9. 本地视觉模型可能不支持 data: URI — vLLM / Ollama 部分模型对 Base64 内嵌图片支持不稳;若失败,确认模型本身支持。
  10. Azure OpenAI api_version 不匹配 — deployment 与 SDK 版本必须兼容;用太新的版本号可能 404。
  11. 每张图一次 LLM 调用 = 高并发风险 — 100 张图直接用线程池可能撞 OpenAI RPM/TPM 限制。429 被静默吞掉表现为"图片没 OCR",不易察觉。
  12. OCR 块污染正文摘要 — 想"只看正文"必须先正则剥离 *[Image OCR]…[End OCR]*,否则 LLM 会把 OCR 文本当正文引用。
  13. gpt-3.5-turbo 不支持 vision — 用户填错模型名时,API 会 400,但被插件静默吞;表现是 OCR 块全没。
  14. 缺 Pillow 或 PyMuPDF — markitdown-ocr 依赖列表里已有;若手贱 pip install markitdown-ocr --no-deps 会缺这些,导致 import 直接报错。
  15. 大文件单次 memory spike — 整 PDF 走 convert_local 时,PyMuPDF 渲染 + base64 编码同时在内存中;几十 MB 图片会爆内存。

1. 是什么 / 解决什么问题

MarkItDown 内置的 PDF/DOCX/PPTX/XLSX 转换器不会对内嵌图片或扫描页做 OCR——它们只取"已可解析的文本"。如果文档里有图片、扫描页、被转成图像的文字,默认输出里那块就是空的。

markitdown-ocr 插件接管上述四个内置转换器(优先级 -1.0,比内置 0.0 更高),通过 LLM Vision(任何支持图像输入的 OpenAI 兼容模型)抽取内嵌图片中的文字并按格式插回 Markdown 流。

核心特性:

  • ✅ PDF / DOCX / PPTX / XLSX 全部支持
  • ✅ 扫描 PDF 自动整页 OCR 回退(每页 300 DPI 渲染后整页送 LLM)
  • ✅ DOCX 图片关系图完整保留(段落/标题/表格流不被破坏)
  • ✅ PPTX 按"上→左"阅读顺序处理图片/占位符/组内图片
  • ✅ XLSX 按图像 anchor 还原列/行字母坐标,图片统一追加在表格后
  • ✅ 输出用 *[Image OCR]…[End OCR]* 包裹每个 OCR 块,便于后处理
  • ❌ 不引入新的 ML 库或二进制依赖(依赖已经在内置转换器里)
  • ⚠️ LLM 调用失败时静默跳过,转换继续

2. 安装

pip install markitdown-ocr
# 同时确保有可用的 OpenAI 兼容客户端
pip install openai            # 官方 OpenAI
# 或
pip install azure-openai      # Azure OpenAI(若走 Azure)

源码安装(开发/调试):

git clone https://github.com/microsoft/markitdown.git
cd markitdown/packages/markitdown-ocr
pip install -e .

依赖项(自动拉取):markitdown>=0.1.0、pdfminer.six、pdfplumber、PyMuPDF、mammoth、python-docx、python-pptx、pandas、openpyxl、Pillow。

3. 配置 — LLM 客户端与模型

关键约束:插件本身不读任何 API key——它从 MarkItDown(llm_client=…, llm_model=…, llm_prompt=…) 拿客户端与模型,认证完全由客户端负责(走其自身的环境变量/凭据链)。

3.1 OpenAI(默认)
export OPENAI_API_KEY=sk-...
from openai import OpenAI
client = OpenAI()  # 自动读 OPENAI_API_KEY
3.2 Azure OpenAI
from openai import AzureOpenAI

client = AzureOpenAI(
    api_key=os.environ["AZURE_OPENAI_API_KEY"],    # 或读其它环境变量
    azure_endpoint="https://<res>.openai.azure.com/",
    api_version="2024-02-01",
)
3.3 其它 OpenAI 兼容服务(Gemini / Ollama / vLLM / LM Studio / DeepSeek-VL 等)

任何实现了 client.chat.completions.create(model=…, messages=[…]) 接口的对象都能传进去,前提是它支持 vision 输入。示例:

import openai
client = openai.OpenAI(
    base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
    api_key=os.environ["GOOGLE_API_KEY"],
)
# 之后正常使用,llm_model="gemini-2.0-flash" 等

更完整的兼容客户端矩阵见 backends/compatible-clients.md;实战脚本见 examples/backends/azure-and-local.md。

3.4 缺少 llm_client 时的行为

_plugin.py::register_converters 中:

if llm_client and llm_model:
    ocr_service = LLMVisionOCRService(client=…, model=…, default_prompt=…)

如果 llm_client 或 llm_model 缺失,插件仍然注册(注册的是无 OCR service 的版本),但实际转换时静默跳过 OCR,回退到内置转换器的行为。验证插件存在:

markitdown --list-plugins
# 应当看到: ocr   (package: markitdown_ocr)

4. Python API — 三种典型用法

4.1 最简(OpenAI + gpt-4o)
from markitdown import MarkItDown
from openai import OpenAI

md = MarkItDown(
    enable_plugins=True,        # ← 必须
    llm_client=OpenAI(),        # ← 必须
    llm_model="gpt-4o",         # ← 必须
)
result = md.convert("document_with_images.pdf")
print(result.markdown)
4.2 Azure OpenAI
from markitdown import MarkItDown
from openai import AzureOpenAI

md = MarkItDown(
    enable_plugins=True,
    llm_client=AzureOpenAI(
        api_key=os.environ["AZURE_OPENAI_API_KEY"],
        azure_endpoint="https://<res>.openai.azure.com/",
        api_version="2024-02-01",
    ),
    llm_model="gpt-4o",
)
print(md.convert("report.docx").markdown)
4.3 自定义 Prompt
md = MarkItDown(
    enable_plugins=True,
    llm_client=OpenAI(),
    llm_model="gpt-4o",
    llm_prompt="Extract all text from this image, preserving table structure.",
)

5. CLI — 当前没有原生 --llm-client / --llm-model

⚠️ 重要:markitdown 当前 CLI(__main__.py)未注册 --llm-client / --llm-model。要通过命令行启用 OCR,用 Python 写一个 3 行包装即可。

5.1 推荐做法:shell 包装

写一个小文件 mdocr:

#!/usr/bin/env python3
# mdocr — 命令行包装 markitdown-ocr
import os, sys, argparse
from markitdown import MarkItDown

ap = argparse.ArgumentParser()
ap.add_argument("filename")
ap.add_argument("-o", "--output")
ap.add_argument("--model", default=os.environ.get("MD_OCR_MODEL", "gpt-4o"))
ap.add_argument("--prompt", default=None)
args = ap.parse_args()

client = OpenAI()  # ← 替换为你要用的客户端构造
md = MarkItDown(
    enable_plugins=True,
    llm_client=client,
    llm_model=args.model,
    llm_prompt=args.prompt,
)
# 注意:请在环境变量 OPENAI_API_KEY / AZURE_OPENAI_API_KEY / OLLAMA_HOST 等中配置凭据
# 切勿把真实 key 写进源代码或 commit。
result = md.convert(args.filename)
sys.stdout.write(result.markdown)
if args.output:
    with open(args.output, "w", encoding="utf-8") as f:
        f.write(result.markdown)
chmod +x mdocr
./mdocr scan.pdf -o scan.md --model gpt-4o
5.2 一行 python -c(临时用)
python -c "
from markitdown import MarkItDown
from openai import OpenAI
import sys
md = MarkItDown(enable_plugins=True, llm_client=OpenAI(), llm_model='gpt-4o')
sys.stdout.write(md.convert(sys.argv[1]).markdown)
" scan.pdf > scan.md

6. フォーマットごとの動作の違い(OCR 結果の挿入方法)

フォーマットOCR ブロックの挿入位置説明
PDFインライン(周囲のテキストに挿入)、上から下への垂直方向の読み順で挿入。スキャンページはページ全体を LLM に送信埋め込み画像は page.images / ページ XObject から抽出。malformed PDF は自動的に PyMuPDF によるページ全体のレンダリングに切り替え
DOCXOCR は「DOCX→HTML→Markdown」パイプラインの前に実行。ドキュメントの構造(見出し/段落/表)は 100% 保持doc.part.rels を使って画像の関連付けを抽出
PPTXスライド内の「上から左」の読み順で挿入。LLM が「画像の説明」を返した場合は説明を優先し、OCR はフォールバックとしてのみ使用Picture shape、placeholder shape、グループ内の画像に対応
XLSX各ワークシートの画像をデータ表の後にまとめて追加し、### Images in this sheet: とラベル付け画像のアンカーから列のアルファベット/行番号を算出。位置情報は失われます(ほかの 3 形式とは異なります)

OCR 出力形式:後処理で識別しやすいよう、各ブロックを Markdown の強調記法で囲みます。

*[Image OCR]
<抽取到的文字>
[End OCR]*

OCR ブロックをまとめて削除し、「本文のみ」の要約を作成するには、次の 1 行の sed コマンドを使えます。

sed -e '/^\*\[Image OCR\]$/,/^\[End OCR\]\*$/d' input.md > cleaned.md

7. 制限事項とコスト(デプロイ前に必ずお読みください)

項目説明
画像ごとに LLM を 1 回呼び出し画像 100 枚の場合、vision 呼び出しは 100 回となり、コストは画像数に比例して増加します
スキャン PDF はより高コストスキャンページは 300 DPI でページ全体を LLM に送信するため、「埋め込み小画像」よりも多くのトークンを消費します
LLM のエラーは通知されません「LLM 呼び出しが失敗しても、その画像のテキストなしで変換を続行します」——失敗は握りつぶされるため、監視が必要です
PPTX では説明を優先LLM が「画像の説明」を返した場合、OCR はフォールバックとしてのみ使われ、最終テキストには元の文字ではなく説明が含まれます
XLSX では位置情報が失われます画像は表の後に追加されるため、元のセルの近くには表示されません
画像 MIMEOCR サービスは stream_info.mimetype または PIL で検出します。どちらでも判別できない場合は image/png として扱います

8. トラブルシューティング早見表

現象確認方法
OCR ブロックがまったく表示されないmarkitdown --list-plugins で ocr が含まれているか確認します。enable_plugins=True と llm_client + llm_model を渡したことも確認してください
ModuleNotFoundError: markitdown_ocr が発生するpip install markitdown-ocr または pip install -e packages/markitdown-ocr を実行します
ModuleNotFoundError: openai が発生するpip install openai を実行するか、別の OpenAI 互換 SDK に切り替えます
一部の画像で OCR が欠落するその LLM 呼び出しの失敗が握りつぶされています。ログ/再試行を追加するか、より安定したモデルに切り替えます
BadRequestError: image_url invalid が発生するクライアント/MIME が認識されていません。_ocr_service.py で content_type が正しく推定されているか確認するか、クライアントを変更します
Azure OpenAI の認証に失敗するapi_version が該当 deployment でサポートされているバージョン(例:2024-02-01)であること、および azure_endpoint の末尾に / がないことを確認します
出力から data:image がすべて消えるこれは MarkItDown 本体の動作であり、OCR とは無関係です。--keep-data-uris(CLI)を追加するか、Python API で keep_data_uris=True を渡します

9. テスト/二次開発

# 跑插件自带的测试套件
cd packages/markitdown-ocr
pytest tests/ -v

# 本地装好后做最小冒烟
python -c "
from markitdown import MarkItDown
from openai import OpenAI
print(MarkItDown(enable_plugins=True, llm_client=OpenAI(), llm_model='gpt-4o').convert('sample.pdf').markdown[:500])
"

プラグインの内部メカニズム(登録フロー、OCRService の実装詳細、各コンバーターの違い)については、plugin/internals.md を参照してください。

10. 関連 Skill に切り替えるタイミング

ユーザーの質問切り替え先
「MarkItDown とは何ですか?どのフォーマットに対応していますか?」markitdown-awesome
「markitdown コマンドの使い方や、引数の渡し方を教えてください」markitdown-cli
「Azure Document Intelligence / Content Understanding を使っています。OCR プラグインは不要です」markitdown-cli の「Azure バックエンド」セクション

11. プライバシーポリシー

この Skill はローカルのドキュメントとサンプルコードを提供し、ユーザーデータを収集、保存、送信することはありません。実際の OCR 呼び出しでは、渡した画像の内容(機密情報を含む可能性があります)が選択した LLM プロバイダーに送信されます。該当プロバイダーのプライバシー条項と、ユーザーの居住地域の法令を遵守してください。本番環境へのデプロイでは、次の対応を推奨します。

  • 高機密文書にはプライベート環境の LLM(ローカルの vLLM / Ollama + OpenAI 互換プロトコルなど)を使用する
  • リクエストログ/一時監査を無効にする

12. 参考リンク

コメント