Skip to content

Repository files navigation

pptx-thumbnailer

Slide thumbnails (PNG/JPEG) from PowerPoint .pptx files via headless LibreOffice — usable as a library, a CLI, or a tiny HTTP microservice (Docker).

Why a microservice? LibreOffice adds hundreds of MB to an application image. Running it once, in its own small static container, keeps your app image slim and your CI fast — your app just POSTs the pptx and gets images back.

Pipeline: soffice --headless renders the pptx to a temporary PDF, then poppler's pdftocairo rasterizes each page (aspect-ratio-preserving scaling built in — no ImageMagick needed). Concurrent conversions are safe: every call gets an isolated LibreOffice user profile, and the server queues requests beyond a configurable concurrency limit.

Run the service (Docker)

docker build -t pptx-thumbnailer .
docker run --rm -p 3000:3000 pptx-thumbnailer
# or: docker compose up -d

HTTP API

The request body is the pptx file — no multipart forms.

# All slides as JSON (base64-encoded images)
curl --data-binary @deck.pptx 'http://localhost:3000/thumbnails?width=400'

# All slides as a zip of slide-<n>.png
curl --data-binary @deck.pptx -H 'Accept: application/zip' \
  'http://localhost:3000/thumbnails?width=400' -o slides.zip

# One slide as a plain PNG
curl --data-binary @deck.pptx \
  'http://localhost:3000/thumbnails?slide=1&as=image' -o slide-1.png

# Health (checks that soffice + pdftocairo are present)
curl http://localhost:3000/healthz
Query param Default Meaning
width 400 Target width in px (aspect ratio preserved)
dpi – Render at a fixed dpi instead of a fixed width
slide – Only convert slide n (1-based)
format png png or jpeg
as json json, zip or image (single slide)

JSON response shape:

{
  "slideCount": 12,
  "format": "png",
  "slides": [
    { "index": 1, "file": "slide-1.png", "data": "<base64>" }
  ]
}

Errors: 400 bad request, 413 upload too large, 422 conversion failed, 503 (healthz) tools missing.

Fonts

Faithful rendering (line breaks, text overflow) depends on the fonts a deck uses being available — LibreOffice silently substitutes missing ones, and a substitute with different glyph widths wraps text differently. The image ships metric-compatible replacements for the common Office fonts: Liberation (Arial/Times New Roman/Courier New) and Carlito/Caladea (Calibri/Cambria).

For customer-specific fonts (e.g. licensed corporate fonts, which cannot be distributed with the image), mount them into the container — fontconfig scans /usr/local/share/fonts automatically, no rebuild or extra configuration needed:

docker run --rm -p 3000:3000 \
  -v ./customer-fonts:/usr/local/share/fonts/custom:ro \
  pptx-thumbnailer

(or uncomment the volumes section in docker-compose.yml). Any .ttf/.otf files in the mounted directory are picked up on the next conversion. Alternatively, decks saved in PowerPoint with "Embed fonts in the file" enabled render correctly without any server-side setup, since LibreOffice uses the embedded fonts.

Environment variables

Variable Default Meaning
PORT / HOST 3000 / 0.0.0.0 Listen address
THUMBNAILER_CONCURRENCY 1 Parallel LibreOffice conversions
MAX_UPLOAD_MB 100 Reject larger uploads (413)
TIMEOUT_MS 120000 Per-tool timeout
SOFFICE_BIN soffice LibreOffice binary
PDFTOCAIRO_BIN pdftocairo poppler binary

Use the client (no LibreOffice needed)

npm install pptx-thumbnailer
import { ThumbnailerClient } from 'pptx-thumbnailer';

const client = new ThumbnailerClient('http://thumbnailer:3000');

// In-memory
const slides = await client.thumbnails('deck.pptx', { width: 400 });
// slides: [{ index: 1, file: 'slide-1.png', data: <Buffer> }, ...]

// Or straight to disk: writes slide-1.png, slide-2.png, ...
await client.thumbnailsToDir(buffer, './out/slides/42', { width: 400 });

Use as a library (LibreOffice installed locally)

Requires libreoffice (impress) and poppler-utils on the host:

import { convertPptxToImages } from 'pptx-thumbnailer';

const slides = await convertPptxToImages('deck.pptx', { width: 400 });

CLI

npx pptx-thumbnailer deck.pptx -o ./thumbs --width 400   # local conversion
npx pptx-thumbnailer serve --port 3000                   # run the service

License

MIT

About

Create png images from pptx files using headless libreoffice

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages