WolfSDKWolfXLWolfPPTWolfDocx

WolfPPT - PPTX to PDF

Convert PPTX to PDF in Python without PowerPoint or LibreOffice

Render a .pptx deck to a PDF, or to one image per slide, with a single command and a receipt for every file. The wolf command lays out the slides with its own engine, so a server needs no Microsoft PowerPoint and no LibreOffice install, and a render report names each omission and font substitution it finds.

Render one deck

wolf render monthly_review.pptx --to pdf --outdir out
wolf render monthly_review.pptx --to png --outdir out
# out/monthly_review.pdf, or out/monthly_review-1.png and out/monthly_review-2.png,
# plus out/render-report.json; the receipt (JSON) goes to standard output

A PDF holds one page per slide. A PNG, SVG, JPEG, TIFF, or BMP target writes one file per slide, named <stem>-<n> with the slide number. Useful options: --pages 1-3 renders a slide range, --dpi sets the raster resolution for image targets only (a PDF target with --dpi is a usage error, exit code 2), --font-dir <dir> (repeatable) adds font folders, and --timeout-ms and --max-pages cap the work for untrusted files.

The exit code tells a script what happened. 0 means every output was written with no error-level loss. 1 means the output was written and the render report holds at least one error-level omission or approximation. 3 means the input is missing or is not a valid deck, and nothing is written.

Call it from Python

import json
import subprocess
from pathlib import Path


def render_to_pdf(source: str, outdir: str) -> tuple[Path, str, dict]:
    outdir = Path(outdir).resolve()
    run = subprocess.run(
        ["wolf", "render", source, "--to", "pdf", "--outdir", str(outdir)],
        capture_output=True,
        text=True,
    )
    receipt = json.loads(run.stdout)
    if receipt["status"] == "failed":
        raise RuntimeError(receipt["errors"])
    report = json.loads(Path(receipt["render_report"]["path"]).read_text())
    return Path(receipt["outputs"][0]["path"]), receipt["status"], report["summary"]


pdf, status, summary = render_to_pdf("monthly_review.pptx", "pdf-out")
print(pdf.name, status, summary["pages"], summary["omissions"]["total"])
# monthly_review.pdf succeeded 2 0

The receipt carries the input and output digests, the status, and the path of the render report. The render report lists each page's size, and each omission, approximation, and font substitution with a location, a reason, and a severity. Review that list before a deck goes to a customer.

To edit first and render second, change the deck with WolfPPT text edits, table updates, or chart data updates, then pass the saved file to render_to_pdf.

Fidelity limits

  • The layout is the wolf engine's own. Text wrapping, chart drawing, and effects can differ from Microsoft PowerPoint's, and the output carries no promise of matching PowerPoint pixel for pixel.
  • The command uses a bundled set of metric-compatible fonts plus any --font-dir folders, and leaves installed fonts off unless you pass --system-fonts. A font outside those sources is substituted and named in the render report. Supply the deck's own font files for the closest match.
  • Content the engine cannot draw is named as an omission with a location, for example a shape on a slide. An error-level omission makes the run partial, exit code 1, so a script can refuse the output.
  • On a frozen corpus of 51 PPTX test files, Wolf's page count matched Microsoft Office's on all 51, and 18 of the files ended partial with an error-level omission. The corpus is a regression benchmark and no blind test has been run, so test your own decks. The rendering results describe the method.

Where WolfPPT fits

This page covers the wolf command. The WolfPPT Python package on this site covers editing, as in the python-pptx comparison. The WolfPPT home page lists every task.

Get the wolf command

The wolf command ships with Wolf Runtime, which is licensed under a written Order. There is no pip package for it. The Wolf Runtime page lists the integration steps: select the build, install the shims or call the command directly, and run your own documents while you check the receipts, omissions, and refusals.