PowerPoint (PPTX) to PDF in Node.js: The LibreOffice Hang, Font Drift, and When to Just Call an API

Search "pptx to pdf node.js" and you will find Aspose marketing posts and narrow Stack Overflow fixes, but almost nothing about the production failure modes. A…

Search "pptx to pdf node.js" and you will find Aspose marketing posts and narrow Stack Overflow fixes, but almost nothing about the production failure modes. A June 2025 r/node thread shows the gap clearly: a developer convinced their bosses to allow Node.js for the conversion, then got pushed toward paid APIs after discovering LibreOffice's headaches [1].

Why the search results send you into a trap

Aspose publishes a Node.js PPTX-to-PDF tutorial built on aspose.slides.via.java, installed with npm install aspose.slides.via.java. They offer a free temporary license and an online converter as a free tool alongside the paid API. What none of the ranked results mention: the self-hosted failure modes that appear only under load. No post connects the community debate to PPTX-specific problems like font substitution reflowing text off slides, or the operational reality that a single LibreOffice instance handles one conversion at a time.

The developer wanted to skip LibreOffice completely and asked the community for a solution that avoids it [1].

Fidelity pitfalls that only matter for slide decks

A reflowed paragraph in a Word file is annoying; a reflowed bullet point on a slide is a corrupted layout.

Font substitution is the worst offender. When Calibri or Cambria are missing on a Linux server, LibreOffice uses fontconfig to pick a substitute and marks the font name in italics without revealing which substitute was used [2]. Missing fonts have caused slide text to overflow page margins in reported Impress bugs [2]. You will not catch this in unit tests unless you test on the exact same OS image.

Other PPTX-specific losses:

  • Speaker notes are lost unless the export filter is configured to include notes pages
  • Hidden slides are silently dropped unless exportHiddenSlides is configured
  • Animations and video are lost, which is expected but should be documented
  • Slide transitions are lost on PDF export [3]
  • LibreOffice has known PPTX rendering bugs

The DOCX-to-PDF post from October 7, 2026 covers shared LibreOffice mechanics [4].

The LibreOffice hang tax in Node.js

A single soffice instance handles one conversion at a time. Two processes sharing a user profile will conflict. Parallel requests need N instances each with its own -env:UserInstallation profile.

Conversions that work when run directly on the command line can hang when spawned as a Node.js child process [5]. A Stack Overflow user saw CPU spike to 100% under many requests, fixed only by upgrading LibreOffice versions [6]. A Gotenberg issue documents that concurrent conversion requests must poll and wait for the single instance [7].

Conversions take seconds per deck, and Docker images are large. Version upgrades cause output drift that becomes a visual-regression event. Wrap every invocation in timeout-and-kill.

When to self-host and when to call an API

Keep libreoffice-convert for low-volume batch on servers you already run. The operational cost is manageable when conversion is off the request path, when you control the input decks, and when occasional font drift is acceptable.

Call an API when conversion sits on the request path of a user-facing SaaS feature where users upload decks. Call an API when you need concurrency without becoming a process supervisor.

Node.js walkthrough: libreoffice-convert first

Install the wrapper or spawn soffice directly:

const { exec } = require('child_process');
const util = require('util');
const execAsync = util.promisify(exec);

async function convertWithLibreOffice(inputPath, outputDir) {
  const command = `soffice --headless --convert-to pdf --outdir ${outputDir} ${inputPath}`;
  
  // Wrap in timeout-and-kill for production safety
  const { stdout, stderr } = await execAsync(command, {
    timeout: 30000,
    killSignal: 'SIGKILL'
  });
  
  return `${outputDir}/${path.basename(inputPath, '.pptx')}.pdf`;
}

Handle the single-instance limit with a queue or multiple -env:UserInstallation profiles:

const profileDir = `/tmp/libreoffice-profile-${process.pid}-${Date.now()}`;
const command = `soffice -env:UserInstallation=file://${profileDir} --headless --convert-to pdf --outdir ${outputDir} ${inputPath}`;

Map the fidelity options manually. The wrapper doesn't expose notes or hidden-slide options, so you must construct the full command string yourself.

Node.js walkthrough: MarkupGo Office-to-PDF API

Install the client [8]:

npm install markupgo-node

Initialize with your API key [8]:

import MarkupGo from "markupgo-node";

const markupgo = new MarkupGo({
  API_KEY: process.env.MARKUPGO_API_KEY,
});

Convert a single PPTX with slide-deck-specific options [9][8]:

import fs from "fs";

const buffer = fs.readFileSync("./presentation.pptx");

const files = [
  {
    data: buffer,
    ext: "pptx",
  }
];

const options = {
  properties: {
    exportNotesPages: true,
    exportHiddenSlides: true,
    landscape: false,
    nativePageRanges: { from: 1, to: 10 }
  }
};

markupgo.office.convert(files, options).buffer().then((buffer) => {
  fs.writeFileSync("output.pdf", Buffer.from(buffer));
});

Merge multiple decks into one PDF [9]:

const files = [
  { data: fs.readFileSync("./deck1.pptx"), ext: "pptx" },
  { data: fs.readFileSync("./deck2.pptx"), ext: "pptx" }
];

const options = {
  merge: true,
  properties: {
    exportNotesPages: true
  }
};

markupgo.office.convert(files, options).buffer().then((buffer) => {
  fs.writeFileSync("combined.pdf", Buffer.from(buffer));
});

The markupgo-node client returns a buffer directly via .buffer() or a task object via .json() [8]. The raw API returns a task object by default; append /buffer to the endpoint path to receive the PDF directly as a buffer instead [9].

Respect the limits: 5MB per document and 10 files per request [9]. The API converts over 130 formats and is currently in BETA [9]. Pricing runs Lite at $29/month for 2,000 credits, Plus at $49/month for 10,000 credits, Pro at $99/month for 20,000 credits, with 100 free credits per month to start [10].

What to do next

If you are also converting DOCX, read the sibling post on headless LibreOffice hangs for shared mechanics [4]. Audit your current PPTX pipeline against the fidelity checklist: fonts, notes, hidden slides, transitions, formulas, tables. Test MarkupGo with the 100 free credits if conversion is on your user-facing request path [10].

Sources

  1. r/node on Reddit: PPTX/PPT TO PDF (reddit.com)
  2. askubuntu.com
  3. askubuntu.com
  4. markupgo.com
  5. stackoverflow.com
  6. stackoverflow.com
  7. Libreoffice Concurrence · Issue #94 · gotenberg/gotenberg (github.com)
  8. markupgo.com
  9. markupgo.com
  10. markupgo.com