WebAssembly Tools for File Conversion in the p2r3/convert Project
The p2r3/convert project leverages seven distinct WebAssembly modules—Pandoc, libopenmpt, SQLite-Wasm, FFmpeg, ImageMagick, and Reflo—to execute client-side file conversions without server-side dependencies.
The convert repository by p2r3 is a browser-based file conversion tool that relies entirely on WebAssembly tools to process documents, media, databases, and images locally. By compiling established C/C++ and Haskell libraries to Wasm, the project eliminates server-side processing while maintaining support for complex formats like Markdown, tracker modules, and video codecs.
Pandoc WebAssembly for Document Conversion
The src/handlers/pandoc.ts handler wraps the Pandoc WebAssembly module (pandoc.wasm) to convert between document formats. This compiled Haskell binary handles Markdown, HTML, LaTeX, DOCX, and other text-based formats.
The handler imports ./pandoc/pandoc.js, which fetches /convert/wasm/pandoc.wasm at runtime and executes the compiled code. Below is a minimal example of initializing the handler and converting Markdown to HTML:
import pandocHandler from "./handlers/pandoc.ts";
const pandoc = new pandocHandler();
await pandoc.init(); // loads pandoc.wasm + JS glue
const input = [{ name: "sample.md", bytes: new Uint8Array(mdData) }];
const out = await pandoc.doConvert(
input,
{ internal: "markdown", extension: "md", mime: "text/markdown", ... },
{ internal: "html", extension: "html", mime: "text/html", ... }
);
// out[0].bytes contains the produced HTML
libopenmpt WebAssembly for Audio Module Rendering
For converting tracker music formats (MOD, XM, IT, S3M) to WAV, src/handlers/libopenmpt.ts utilizes the libopenmpt WebAssembly module. The handler pre-fetches the binary with fetch("/convert/wasm/libopenmpt.wasm"), injects it into a global libopenmpt object, then loads the companion script /convert/wasm/libopenmpt.js.
import libopenmptHandler from "./handlers/libopenmpt.ts";
const opener = new libopenmptHandler();
await opener.init(); // fetches libopenmpt.wasm, loads libopenmpt.js
const modFile = [{ name: "track.mod", bytes: new Uint8Array(modData) }];
const wavs = await opener.doConvert(modFile, /* unused */ null, null);
// wavs[0].bytes is a Uint8Array containing a WAV file
SQLite-Wasm for Database Extraction
The src/handlers/sqlite.ts handler imports sqlite3InitModule from the npm package @sqlite.org/sqlite-wasm to read SQLite databases and extract tables as CSV files. The underlying Wasm binary is bundled by the package and instantiated on demand, eliminating the need for manual fetching.
import sqlite3Handler from "./handlers/sqlite.ts";
const sqlite = new sqlite3Handler();
await sqlite.init(); // registers SQLite-Wasm
const dbFile = [{ name: "my.db", bytes: new Uint8Array(dbData) }];
const csvs = await sqlite.doConvert(
dbFile,
{ internal: "sqlite3", extension: "db", mime: "application/vnd.sqlite3", ... },
{ internal: "csv", extension: "csv", mime: "text/csv", ... }
);
// each table becomes a separate CSV file in `csvs`
FFmpeg WebAssembly for Media Transcoding
For video and audio transcoding (MP4, MP3, OGG, etc.), src/handlers/FFmpeg.ts drives the FFmpeg WebAssembly core. The handler calls ffmpeg.load({ coreURL: "/convert/wasm/ffmpeg-core.js" }), which internally pulls the ffmpeg-core.wasm binary.
import ffmpegHandler from "./handlers/FFmpeg.ts";
const ff = new ffmpegHandler();
await ff.init(); // loads ffmpeg-core.wasm
const mp4 = [{ name: "video.mp4", bytes: new Uint8Array(mp4Data) }];
const mp3 = await ff.doConvert(
mp4,
{ internal: "mp4", extension: "mp4", mime: "video/mp4", ... },
{ internal: "mp3", extension: "mp3", mime: "audio/mpeg", ... }
);
// mp3[0].bytes is the transcoded MP3 data
ImageMagick WebAssembly for Image Conversion
The src/handlers/ImageMagick.ts handler utilizes ImageMagick compiled to WebAssembly (magick.wasm) for converting between image formats like PNG, JPEG, and GIF. The handler fetches the binary via fetch("/convert/wasm/magick.wasm"), then passes the bytes to initializeImageMagick.
import imageMagickHandler from "./handlers/ImageMagick.ts";
const im = new imageMagickHandler();
await im.init(); // fetches magick.wasm
const png = [{ name: "photo.png", bytes: new Uint8Array(pngData) }];
const jpg = await im.doConvert(
png,
{ internal: "png", extension: "png", mime: "image/png", ... },
{ internal: "jpeg", extension: "jpg", mime: "image/jpeg", ... }
);
// jpg[0].bytes holds the JPEG image
Reflo WebAssembly for Audio Processing
Inside src/handlers/flo.worker.ts, the Reflo WebAssembly module (reflo_bg.wasm) handles specialized audio rendering for the flo pipeline. Running inside a Web Worker, the helper initReflo('/convert/wasm/reflo_bg.wasm') loads the Wasm module to apply audio filters and processing steps that complement the main conversion workflow.
How WebAssembly Modules Are Loaded in convert
All WebAssembly assets are managed by a custom build step defined in vite.config.js. The copyWasm plugin configuration copies compiled binaries into the public wasm/ folder, ensuring they are reachable at runtime under the /convert/wasm/ URL namespace.
Each handler follows a consistent initialization pattern:
- Fetch the
.wasmbinary from the public path (or import from npm for SQLite-Wasm). - Instantiate the module using JavaScript glue code or dedicated initialization functions.
- Expose a
doConvertmethod that acceptsUint8Arrayinput and returns converted bytes.
This architecture keeps all conversion logic client-side, eliminating network latency and server costs while maintaining compatibility with complex legacy formats.
Summary
- The p2r3/convert project relies on seven core WebAssembly tools: Pandoc, libopenmpt, SQLite-Wasm, FFmpeg, ImageMagick, and Reflo.
- Each tool is wrapped by a TypeScript handler in
src/handlers/that implements theFormatHandlerinterface. - Wasm binaries are copied to
/convert/wasm/by thevite.config.jsbuild process and fetched at runtime. - All conversions run entirely in the browser, enabling offline-capable, privacy-preserving file transformation.
Frequently Asked Questions
What WebAssembly tools does the convert project use?
The convert project uses Pandoc for documents, libopenmpt for tracker music, SQLite-Wasm for databases, FFmpeg for video and audio, ImageMagick for images, and Reflo for advanced audio processing. Each module is compiled from C/C++ or Haskell to Wasm and wrapped by a TypeScript handler.
How does convert load WebAssembly modules in the browser?
Each handler fetches its corresponding .wasm file from the /convert/wasm/ path at runtime. The vite.config.js file includes a copyWasm plugin that moves compiled binaries into the public wasm/ folder during the build process. Some modules, like SQLite-Wasm, are imported directly from npm and instantiate their Wasm internally.
Why does convert use WebAssembly instead of server-side conversion?
WebAssembly enables client-side processing, which eliminates server costs, reduces network latency, and preserves user privacy by keeping files local. By compiling mature tools like FFmpeg and Pandoc to Wasm, convert can handle complex formats entirely within the browser without installing native software or uploading data to external servers.
Can I use these WebAssembly tools outside of the convert project?
Yes. Most of these WebAssembly modules are open-source projects compiled for the web. Pandoc-wasm, ffmpeg.wasm, @sqlite.org/sqlite-wasm, and @imagemagick/magick-wasm are available as standalone npm packages. You can instantiate them in any JavaScript or TypeScript project using similar fetch-and-initialize patterns shown in the convert handlers.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →