RAG や AI エージェントの開発に携わったことのある人なら、誰もが経験したことがあるあの絶望——
業務部門から圧縮ファイルを投げつけられ、中には Word、PPT、Excel、PDF とあらゆる形式が混在している。あなたの任務は、それらをすべてクリーンな Markdown に変換して LLM に食わせること。LibreOffice で開けば1文書の変換に1秒以上待たされ、Pandoc は速めだが対応形式はわずか5種類。結局、形式ごとに個別のパースロジックを書く羽目になり、メンテナンスコストは人生を疑いたくなるほど高くつく。
最近オープンソースコミュニティに登場したこのプロジェクトが、この状況を根本から変えるかもしれない。
■ 一、これは何?
anydoc は Firecrawl チームがオープンソースとして公開したドキュメント変換ライブラリで、純粋な Rust 実装により、14種類のオフィス文書形式をクリーンな GitHub Flavored Markdown に変換できる。
対応形式一覧:
Word:.doc、.docx、.docm
PowerPoint:.ppt、.pps、.pot、.pptx、.pptm、.ppsx、.ppsm
Excel:.xls、.xlsx、.xlsm、.xlsb
OpenDocument:.odt、.ods、.odp
RTF、EPUB、CSV、PDF
その背後には Firecrawl——ウェブサイトを Markdown に変換する API で知られるあの企業だ。anydoc はすでに長期間プロダクション環境で稼働しており、Firecrawl Parse のドキュメント解析の基盤もこれである。
プロジェクトは MIT ライセンスを採用し、コードは GitHub 上で完全に公開されている。
■ 二、最も核心的な設計:1つのモデル、統一された出力
ここが anydoc とすべての競合製品を分ける最も本質的な違いだ。
ほとんどの変換ツールは「形式ごとに専用パーサーを書き、直接 Markdown を出力する」方式を採っている。docx はこのロジック、pptx は別のロジック、rtf はまた別のロジックという具合で、出力品質はまちまち。ある形式のバグを修正しても、他の形式の問題はそのまま残ってしまう。
anydoc のアプローチはまったく異なる:
「各形式のパーサーはまず文書を共通の中間表現(Document Model)にパースし、その後すべての形式が同一の Markdown シリアライザーを共有する。」
アーキテクチャの全体像:
文書バイト
│
├─► 形式検出(コンテンツの特徴に基づく判定で、拡張子には依存しない)
│
├─► 形式パーサー(doc/docx/ppt/pptx/xls/xlsx/odt/ods/odp/rtf/epub/csv)
│ │
│ └─► Document Model(統一された中間表現:ブロック、インライン要素、表、脚注、リソース)
│ │
│ └─► GFM シリアライザー → Markdown
│
└─► PDF → pdf-inspector → Markdown へ直接変換
これはどういうことか。「1つの表エスケープルールの修正が、docx、rtf、odt などすべての形式の出力修正に同時につながる」のだ。出力の一貫性が保証され、メンテナンスコストも最小限に抑えられる。
Document Model に保持される情報はかなり網羅的だ:
アンカー付きの見出し階層
太字、斜体、取り消し線
インラインコードとコードブロック
リンクと内部相互参照
元の番号を保持した箇条書きリスト、番号付きリスト、ネストしたリスト、タスクリスト
結合セルとヘッダー行を備えた表
ブロック引用、脚注、文末脚注
スピーカーノート
埋め込みリソースもきれいに処理される。画像は Markdown の alt テキストとしてレンダリングされ、「元のバイト列は media type のタグ付きで Document Model 内に保持される」ため、後続の処理は自由に行える。
■ 三、形式検出:拡張子ではなく、中身を見る
多くの変換ツールはファイル拡張子で形式を判断する。しかし現実には拡張子が誤って変更されていることがよくある——明らかに PDF なのに .doc に書き換えられている、といった具合だ。
anydoc の形式検出は、ファイルの内容から直接特徴を読み取る:
PDF:PDF ヘッダーを読む
RTF:RTF の開始マーカーを読む
OLE 形式(.doc、.ppt、.xls):OLE ストリーム名を読む
ZIP パッケージ形式(.docx、.pptx、.xlsx):ZIP パッケージの mimetype と content types を読む
CSV のように埋め込みマーカーを持たない形式のみ、拡張子か形式パラメータを明示的に指定する必要がある。
Rust、Node.js、Python のいずれにも、format_from_bytes、format_from_extension、format_from_path の3つの API が用意されている。
■ 四、パフォーマンス:見せかけではなく、圧倒的な実力
まずはデータを見てほしい。
anydoc の公式チームはベンチマークを実施し、100件の実際の文書を使って6つの類似ツールと比較した。スコアリングは Claude Sonnet 5 によるブラインドテストで行われ、完全性、構造の保持、書式の忠実度、出力の清潔さの4つの観点から採点。位置バイアスを排除するため各ペアの出力の提示順序を入れ替えて2回判定し、合計481回の判定が行われた。
総合スコア(0〜100):
・anydoc:対応形式 14/14|中央値処理時間 4.4 ms|総合スコア 81
・libreoffice:対応形式 12/14|中央値処理時間 1129.5 ms|総合スコア 39
・unstructured:対応形式 8/14|中央値処理時間 572.9 ms|総合スコア 62
・markitdown:対応形式 6/14|中央値処理時間 134.8 ms|総合スコア 64
・pandoc:対応形式 5/14|中央値処理時間 102.1 ms|総合スコア 56
・docling:対応形式 4/14|中央値処理時間 513.6 ms|総合スコア 57
・mammoth:対応形式 1/14|中央値処理時間 52.5 ms|総合スコア 69
中央値の処理時間は4.4ミリ秒で、2位の pandoc(102ms)を一桁引き離している。この速度なら、500個の DOCX ファイルを約2.2秒で処理し切れる計算だ。
形式別の比較(スコアが高いほど優秀。順序は anydoc / libreoffice / unstructured / markitdown / pandoc / docling / mammoth の順):
・doc:87|57|67|−|−|−|−
・docm:85|45|−|−|−|−|−
・docx:86|54|53|73|67|71|69
・epub:77|−|72|72|52|−|−
・odp:86|23|−|−|−|−|−
・ods:82|38|−|−|−|−|−
・odt:80|52|68|−|60|−|−
・ppt:80|26|−|−|−|−|−
・pptx:75|24|−|61|−|52|−
・rtf:88|54|45|−|44|−|−
・xls:80|38|66|62|−|−|−
・xlsm:76|32|−|−|−|−|−
・xlsx:72|30|66|55|−|47|−
「anydoc は全14形式をカバーした唯一のツールであり、比較可能なすべての形式で最高スコアを獲得した。」
速度テスト環境:Ryzen 9 9950X3D、Windows 11、メモリ64GB DDR5-6400。anydoc と Python ライブラリの計測ではプロセス起動のオーバーヘッドを除外し、CLI ツールについては実際の使用形態であるためプロセス起動時間を含めている。
■ 五、PDF 対応:OCR サービスに頼らない
anydoc はテキスト型 PDF を内蔵の pdf-inspector で直接変換でき、外部の OCR サービスを一切呼び出す必要がない。
市場に出回る PDF の約54%は純粋なテキスト型だ。この部分はローカルで直接変換できるため、ネットワーク遅延ゼロ、API 費用ゼロで済む。
スキャン版 PDF や画像型 PDF の場合(anydoc は Unsupported エラーを返す)、選択肢は2つある:
先に他の OCR ツールで処理し、そのテキストを anydoc に渡す
OCR モデルを内蔵した Firecrawl のマネージド API 版を利用する
■ 六、多言語バインディング:Node.js、Python、ブラウザ、Rust
anydoc は Rust ライブラリにとどまらず、完全なクロス言語サポートも提供している。
CLI(コマンド1行で完了):
npx @firecrawl/anydoc report.docx
npx @firecrawl/anydoc slides.pptx -o slides.md
npx @firecrawl/anydoc - --format csv < data.csv # 標準入力から読み込む
標準入力(stdin)からの読み込みにも対応。
初回実行時にプリコンパイル済みバイナリが自動でダウンロードされ、グローバルインストールは npm install -g @firecrawl/anydoc で行える。
Node.js(変換はスレッドプール上で実行され、イベントループをブロックしない):
import { toMarkdown } from '@firecrawl/anydoc';
const markdown = await toMarkdown('report.docx');
Python(変換時には GIL が解放され、他のスレッドは処理を続行できる):
import anydoc
markdown = anydoc.to_markdown("report.docx")
ブラウザ(WebAssembly)版(ファイルはローカルで変換され、サーバーには一切アップロードされない):
import init, { toMarkdownBytes } from '@firecrawl/anydoc-wasm';
await init();
const markdown = toMarkdownBytes(bytes);
公式ではオンラインデモも公開されており、ブラウザ内で直接 WASM が動くため、ファイルがマシンの外に出ることはない。
Rust(crate を直接組み込む):
let markdown = anydoc::to_markdown("report.docx")?;
■ 七、Agent Skill:AI コーディングアシスタントがドキュメントを直接読める
anydoc は Agent Skill サポートも内蔵している:
npx skills add firecrawl/anydoc
このコマンド1つで、Claude Code、Codex、Cursor、OpenCode といった AI コーディングアシスタントが、anydoc を使ったドキュメントの読み方を習得する。エージェントが Word や PDF ファイルに遭遇した際、anydoc を直接呼び出して Markdown に変換してから処理できるのだ。
■ 八、エラー処理:きめ細かな失敗分類
anydoc の変換失敗は細かく分類されている:
・Unsupported:未知の形式、または変換不可能(画像型 PDF など)
・Malformed:構造が破損しており、意味のある内容を抽出できない
・Encrypted:暗号化またはパスワード保護されている
・ResourceLimit:安全制限の超過(解凍、ネスト深度、ノード数)
・MissingPart:必要なパーツが欠落している
・Io:ファイルの読み取りに失敗
Node.js と WASM では error.code でエラー種別が判別でき、Python では対応する anydoc.ConvertError のサブクラスが送出される。
このきめ細かなエラー分類は、本番のパイプラインで非常に役立つ——エラーの種類に応じて異なる処理を行える。たとえば暗号化ファイルだけを個別に記録し、パイプライン全体のクラッシュを防ぐ、といった具合だ。
■ 九、適用シーン
anydoc が最も輝くのは「形式の混在した文書を大量に処理する必要があるパイプライン」だ:
RAG システムのドキュメント前処理
AI エージェントのファイル読み取り機能
社内ドキュメントのインデックス構築
オフィス文書を LLM の入力に変換する必要のあるあらゆる場面
プロジェクトのページ:github.com/firecrawl/anydoc