MarkItDownを使うと、ExcelやパワーポイントなどさまざまなファイルをMarkdown形式に変換できる。パワーポイントの場合、LLMを渡すことで画像のキャプションを生成できて便利なのだが、残念ながら生成時に並行処理を利用していないので、画像が多数含まれる場合に処理時間が長くなるという問題がある。そこで、画像だけを抽出してみたというのがこの記事の話。
結論
- MarkItDownで変換する際に
keep_data_uris=Trueを指定する - 変換結果のMarkdownから正規表現でBase64画像を抜き出す
- 必要に応じてPillowで形式をPNGなどに変換する
準備
パッケージをインストールしておく。
pip install -q markitdown[pptx]
pptxの用意
デジタル庁の公開している「オープンデータ官民ラウンドテーブル」を例として使う。もちろん画像を含むpptxであれば他のものでも問題ない。以下に示すように、1ページ目から画像が含まれている。

画像の抽出
MarkItDownをインスタンス化して、convertメソッドにkeep_data_uris=Trueを渡す。そうすると、変換結果のMarkdownにBase64でエンコードされた画像が埋め込まれる。
from markitdown import MarkItDown filepath = "20210118_resources_data_round_table_05.pptx" md = MarkItDown() result = md.convert(filepath, keep_data_uris=True) print(result.markdown)
<!-- Slide number: 1 -->  # はじめてみよう! 地方版 オープンデータ官民ラウンドテーブル 【オープンデータ広報用キャラクター】 パッカーンくん 内閣官房 情報通信技術(IT)総合戦略室  本書は、クリエイティブ・コモンズ 表示4.0 国際 (CC BY 4.0) にしたがって利用いただけます。 (http://creativecommons.org/licenses/by/4.0/legalcode.ja)
あとは、正規表現を使ってMarkdownからエンコードされた画像の文字列を抽出すれば良い。このままLLMに渡してキャプションを生成してもいいが、LLMがサポートしていない画像形式の場合もあり得るので、以下ではPillowを使ってPNGに変換している。
import base64 import io import re from PIL import Image # エンコードされた画像を抽出 pattern = re.compile(r"\!\[\]\(data:image/.+?;base64,(.+?)\)") base64_str = pattern.search(result.markdown).group(1) img_bytes = base64.b64decode(base64_str) # PNGに変換 img = Image.open(io.BytesIO(img_bytes)) buffer = io.BytesIO() img.save(buffer, format="PNG") png_bytes = buffer.getvalue() base64_str = base64.b64encode(png_bytes).decode("utf-8") print(base64_str[:30]) # 先頭30文字だけ表示
元はJPEG形式だったが、PNGをBase64でエンコードした形式になっていることがわかる。
iVBORw0KGgoAAAANSUhEUgAAAOEAAA
これで、パワーポイント内の画像を取り出し、文字列として再利用できるようになった。あとは、LLMに投げる部分をasyncioを使って並行処理することで処理時間を短縮できる。ちなみに、Wordのファイルに対しても、同様の方法で画像を抽出できる。