pptx2md.py テクニカルドキュメント


プログラムの動作

pptx2md.py は、Microsoft PowerPoint (.pptx) ファイルからテキスト、数式、および画像を抽出し、それらを構造化されたMarkdownドキュメントに変換するPythonスクリプトです。このプログラムは、PowerPointプレゼンテーションの内容を、再利用しやすく、編集しやすいテキストベースの形式(MarkdownとLaTeX)に変換することを目的としています。

主な機能:

  • コンテンツ抽出: 各スライドからタイトル、本文テキスト、数式、埋め込み画像を抽出します。

  • 数式変換: PowerPointのOMML (Office Math Markup Language) 形式で記述された数式を、LaTeX形式に変換します。これにより、数式をMarkdownドキュメント内で直接レンダリングできるようになります。複数行のOMML数式は、個別のLaTeXブロック数式として出力されます。

  • 画像抽出とリンク: スライドに埋め込まれた画像を抽出し、指定されたディレクトリにファイルとして保存します。その後、Markdownファイル内でこれらの画像へのリンクを生成します。

  • Markdown出力: 抽出されたコンテンツは、スライドごとのセクション、テキスト、数式、画像の順序で整形され、Markdownファイルとして出力されます。スライドのタイトルはMarkdownのセクション見出しとして利用されます。

  • OMML XML出力(オプション): 必要に応じて、変換されたLaTeX数式の隣に元のOMML XMLコードブロックを出力できます。

  • Unicode数学記号の変換: 特殊なUnicode数学記号(例:イタリック体アルファベット、ギリシャ文字、特定の演算子)を、対応するASCIIまたはLaTeX表現に変換します。

解決する課題:

  • PowerPointプレゼンテーションの内容を手動でMarkdownやLaTeXに変換する手間を削減します。

  • OMML形式の数式を、広くサポートされているLaTeX形式に自動変換することで、再利用性を高めます。

  • プレゼンテーションの内容を構造化されたテキスト形式に変換し、ドキュメント作成やコンテンツ管理のワークフローを効率化します。


原理

pptx2md.py は、主に python-pptxlxml の二つのライブラリを活用して、PowerPointファイルの内部構造を解析し、コンテンツを変換します。

1. PowerPointファイルの解析

  • python-pptx ライブラリを使用して、.pptx ファイルを読み込みます。.pptx ファイルは実際にはZIPアーカイブであり、内部にXMLファイル群が含まれるOpen XML形式です。python-pptx はこのXML構造への高レベルなアクセスを提供します。

  • プログラムはプレゼンテーション内の各スライドを順に処理します。

2. テキストの抽出

  • スライドのタイトルは、プレースホルダーの種類がタイトル (placeholder_format.type == 1) であるシェイプから優先的に抽出されます。それ以外の場合は、最初のテキストフレームの最初の行がタイトルとして採用されます。

  • スライド内のすべてのテキストは、スライドの生XMLからXPath (//a:t) を使用して抽出されます。

3. 画像の抽出と保存

  • スライドの生XMLから、埋め込み画像を参照する a:blip 要素を検索します。この要素は r:embed 属性を持ち、画像データへのリレーションシップIDを含んでいます。

  • リレーションシップID (r_id) を使用して、slide.part.rels から対応する画像パート (target_part) を取得します。

  • 画像パートのバイナリデータ (blob) を読み込み、指定された画像ディレクトリ (--imagedir) に保存します。ファイル名は slideN_imageM.ext の形式で、拡張子 (.ext) は画像のコンテンツタイプから決定されます。

  • Markdown出力には、保存された画像ファイルへの相対パスを含む画像リンク ![]() が追加されます。

4. 数式のOMMLからLaTeXへの変換

数式変換は、lxml ライブラリによるXML解析と、omml_to_latex 関数による再帰的な変換ロジックが中心となります。

  • OMML要素の特定: スライドの生XMLから、数式を表す <m:oMathPara> または <m:oMath> 要素をXPathを使用して特定します。<m:oMathPara> は数式の段落を、<m:oMath> は単独の数式ブロックを表します。重複を避けるため、<m:oMathPara> 内の <m:oMath> は優先的に処理され、<m:oMathPara> の外部にある単独の <m:oMath> も処理されます。

  • omml_to_latex 関数: この関数は、OMMLのXML要素を再帰的に走査し、対応するLaTeX文字列を生成します。

    • 要素ごとの変換規則:

      • <m:oMath>, <m:oMathPara>: 子要素を結合。

      • <m:f> (Fraction - 分数): \frac{numerator}{denominator} 形式。

      • <m:rad> (Radical - 根号): \sqrt[degree]{expression} または \sqrt{expression} 形式。

      • <m:sSup> (Superscript - 上付き文字): base^{superscript} 形式。

      • <m:sSub> (Subscript - 下付き文字): base_{subscript} 形式。

      • <m:sSubSup> (Subscript and Superscript - 上下付き文字): base_{subscript}^{superscript} 形式。

      • <m:d> (Delimiter - 区切り文字): beg_char content end_char 形式(例: (content))。

      • <m:limLow>, <m:limUpp> (Limit - 限界): base_{lower_limit} または base^{upper_limit} 形式。

      • <m:int>, <m:nary> (Integral/N-ary - 積分/総和・総乗など): \int_{lower}^{upper} {body}\sum_{lower}^{upper} {body} などの形式。演算子文字 (, , など) は _detect_nary_op_char 関数で特定され、NARY_TO_LATEX マップを用いて対応するLaTeXコマンドに変換されます。

      • <m:r> (Run - テキストラン), <m:t> (Text - テキスト): テキスト内容を抽出します。

    • Unicode数学記号の置換: _safe_text_replace_math_unicode 関数と MATH_UNICODE_MAP 辞書を用いて、抽出されたテキスト内のUnicode数学記号(例: 𝒙x に、\sum に、\int に)を、ASCII文字または対応するLaTeXコマンドに変換します。これにより、PowerPointで表現されるイタリック体や特殊記号がLaTeXで正しく解釈されるようになります。

    • 微分記号 d の体裁: LaTeXに変換後、\mathrm{d} が続く場合には、\frac{∂L}{∂x} = 0 \\ \frac{∂L}{\partial y} = 0 のように、微分記号の前に小さなスペース \, を挿入して体裁を整えます(例: \int x \, \mathrm{d}x)。

  • 複数行の数式処理: split_latex_blocks 関数は、LaTeX文字列内の \\ (改行記号) を検出し、一つの大きな数式ブロックを複数の独立したブロック数式 $${...}$$ に分割します。これにより、Markdownパーサー(特にPandocなど)で複数行の数式が正しくレンダリングされるようにします。

5. Markdown出力

  • 各スライドのコンテンツは、# スライド N タイトル の大見出しで始まり、その後に ## テキスト## 数式## のサブセクションが続きます。

  • 数式は、前後に空行を挟んだ $${...}$$ のブロック数式として出力されます。

  • オプションで --xml フラグが指定された場合、変換されたLaTeX数式の直後に、元のOMML XMLがコードブロックで挿入されます。

これらの手順を通じて、pptx2md.py はPowerPointの視覚的なプレゼンテーションコンテンツを、構造的で再利用可能なMarkdownとLaTeXの形式に変換します。


必要な非標準ライブラリとインストール方法

pptx2md.py の実行には、以下のPython非標準ライブラリが必要です。

  • python-pptx: PowerPointファイル (.pptx) の読み込みと操作に使用します。

  • lxml: PowerPointファイル内のOMML (Office Math Markup Language) 数式をXMLとして解析するために使用します。

これらのライブラリは、Pythonのパッケージインストーラー pip を使用してインストールできます。

pip install python-pptx lxml

必要な入力ファイル

本プログラムが期待する入力ファイルは以下の通りです。

  • PowerPointプレゼンテーションファイル:

    • 拡張子は .pptx である必要があります。

    • Microsoft Office Open XML形式のファイルであることが前提です。

    • ファイル名とパスは、コマンドライン引数 -i または --input で指定します。

例: my_presentation.pptx

ファイルが存在しない場合、プログラムはエラーメッセージを表示して終了します。


生成される出力ファイル

プログラムの実行により、以下のファイルが生成されます。

  1. Markdownファイル:

    • 指定した -o または --output 引数で指定されたファイル名(例: output.md)で保存されます。

    • 内容:

      • 各スライドはMarkdownの大見出し # スライド N タイトル で始まり、その後に --- 区切り線が続きます。

      • スライド内のテキストは ## テキスト の下に出力されます。

      • スライド内の数式は ## 数式 の下に出力されます。数式はLaTeX形式に変換され、前後に空行を挟んだ以下の形式のブロック数式として記述されます。 $\(\int_{a}^{b} f(x) \, \mathrm{d}x = F(b) - F(a)\)$ 複数行のOMML数式は、Markdown上でそれぞれの行が独立したブロック数式として出力されます。

      • --xml オプションが指定された場合、各ブロック数式の直後に、元のOMML XMLが以下の形式のコードブロックで挿入されます。

        <m:oMathPara>...</m:oMathPara>
        
      • スライド内の画像は ## の下に出力されます。画像はMarkdownの画像リンク ![キャプション](画像ファイルパス) の形式で記述されます。画像ファイルパスは、Markdownファイルからの相対パスとなります。

  2. 画像ファイル:

    • 指定した --imagedir 引数で指定されたディレクトリ(デフォルトは images)内に保存されます。

    • 内容: 各スライドから抽出された埋め込み画像が、バイナリ形式で元の拡張子(例: .png, .jpeg)を保持して保存されます。

    • ファイル名: slideN_imageM.ext の形式になります(例: slide1_image1.png, slide2_image1.jpeg)。ここで N はスライド番号、M はスライド内の画像番号、ext は画像の拡張子です。


コマンドラインでの使用例 (Usage)

pptx2md.py は、以下の書式でコマンドラインから実行します。

python pptx2md.py -i <入力PowerPointファイル> -o <出力Markdownファイル> [--imagedir <画像ディレクトリ>] [--xml] [--pause <0|1>]

引数:

  • -i, --input <入力PowerPointファイル> (必須):

    • 変換元となるPowerPointプレゼンテーションファイル (.pptx) のパスを指定します。

  • -o, --output <出力Markdownファイル> (必須):

    • 変換結果を保存するMarkdownファイル (.md) のパスとファイル名を指定します。

  • --imagedir <画像ディレクトリ> (任意):

    • 抽出された画像ファイルを保存するディレクトリのパスを指定します。

    • 指定しない場合、デフォルトで ./images ディレクトリが使用されます。

    • 指定されたディレクトリが存在しない場合、自動的に作成されます。

  • --xml (任意):

    • このフラグを指定すると、Markdownファイル内の各数式のLaTeX変換結果に加えて、その数式の元のOMML XMLコードブロックも出力されます。

  • --pause <0|1> (任意):

    • プログラム終了時にENTERキーの入力を要求するかどうかを制御します。

    • 1 を指定すると、プログラムは終了する前に一時停止し、ユーザーの入力待ちになります。

    • 0 を指定した場合(デフォルト)、プログラムは完了後すぐに終了します。


コマンドラインでの具体的な使用例

1. 基本的な変換

my_presentation.pptx という名前のPowerPointファイルを output.md というMarkdownファイルに変換します。画像はデフォルトの images/ ディレクトリに保存されます。

python pptx2md.py -i my_presentation.pptx -o output.md

実行結果の説明:

my_presentation.pptx の内容が解析され、output.md というMarkdownファイルが生成されます。このファイルには、スライドごとのテキストとLaTeX形式の数式、そして画像へのリンクが含まれます。画像ファイル自体は、output.md と同じディレクトリに作成された images/ フォルダ内に保存されます。

2. 画像ディレクトリを指定して変換

report.pptxfinal_report.md に変換し、画像を report_assets/ というディレクトリに保存します。

python pptx2md.py -i report.pptx -o final_report.md --imagedir report_assets

実行結果の説明:

report.pptx のコンテンツが final_report.md に出力されます。画像は report_assets/ ディレクトリに抽出・保存され、final_report.md 内の画像リンクは report_assets/ ディレクトリ内のファイルを指します。

3. 数式の元のOMML XMLも出力

equation_slides.pptxequations.md に変換し、各数式のLaTeX表現に加えて、対応するOMML XMLも出力します。

python pptx2md.py -i equation_slides.pptx -o equations.md --xml

実行結果の説明:

equation_slides.pptx 内のすべての数式がLaTeX形式で equations.md に出力されます。さらに、それぞれのLaTeX数式の直下には、その数式を構成する元のOMML (Office Math Markup Language) のXML構造がコードブロックとして記述されます。

4. 終了時に一時停止を有効にする

presentation.pptxdocument.md に変換し、プログラムの処理が完了した後、ユーザーがEnterキーを押すまでターミナルウィンドウを閉じずに待機するように設定します。

python pptx2md.py -i presentation.pptx -o document.md --pause 1

実行結果の説明:

変換処理が完了すると、コンソールに「抽出が完了しました。結果は 'document.md' に保存されました。」というメッセージと、「Press ENTER to terminate」というプロンプトが表示されます。ユーザーがEnterキーを押すまでプログラムは終了しません。これは、スクリプトをGUI環境や自動化ツールから実行する際に、完了メッセージを確認するために便利です。