cloud-convert-private-malcolm
v3.0.0
Published
Local file conversion with chainable TypeScript classes. Conversion uses installed command-line tools; `new Convert()` does not install or run anything.
Readme
Cloud Convert
Local file conversion with chainable TypeScript classes. Conversion uses installed command-line tools; new Convert() does not install or run anything.
import Convert, { ImageFormat } from './index.js';
const result = await new Convert()
.Image('photo.png', ImageFormat.PNG, { width: 1200 })
.To('photo.webp', 'webp', { quality: 85 });
// Infer both types from filename extensions.
await new Convert().Image('photo.png', { width: 800 }).To('photo.jpg');
await new Convert().From('photo.png').To('photo.webp', { quality: 80 });
// Explicit types also work for paths without a matching extension.
await new Convert().Image('upload', 'png').To('download', 'webp');
// Reusable source settings; From returns a new independent chain.
const image = new Convert().Image('first.png', { width: 400 });
await image.To('first.webp');
await image.From('second.png', { width: 600 }).To('second.jpg');.Image, .Audio, .Video, .Archive, .Document, .Font, .Model, and .Pdf accept (inputPath, optionalType, options) or (inputPath, options). .From selects a category from the source extension or explicit type. .To accepts the same argument shapes for the destination and executes the conversion, returning Promise<ConversionResult> with buffer, filename, and mime. The destination path is required and the result is also written there. Destination options override source options with the same key. An existing destination is replaced after the backend succeeds; an input cannot also be its destination.
Type strings and the exported format enums are accepted. Compound extensions such as tar.gz are recognized. Explicit types override extensions. For ambiguous formats, automatic selection treats PDF as the PDF chain, and SVG/GIF as images. Use .Document, .Image, .Font, or .Video explicitly to choose another backend. Types must belong to the selected category; actual format support also depends on the installed backend and its codecs or delegates. .Pdf takes a PDF source and covers OCR, page rendering, text extraction, optimization, and structural edits; .Image('scan.pdf') still routes a PDF through ImageMagick where supported.
const convert = new Convert();
await convert.Audio('recording.wav', { rate: 44100 }).To('recording.flac');
await convert.Video('clip.mp4', { width: 1280 }).To('clip.mkv');
await convert.Document('notes.md').To('notes.html');
await convert.Document('report.docx').To('report.pdf'); // LibreOffice
await convert.Document('sheet.xlsx').To('sheet.csv'); // LibreOffice
await convert.Document('book.epub').To('book.mobi'); // Calibre
await convert.Archive('bundle.zip').To('bundle.7z');
await convert.Font('font.ttf').To('font.woff');
await convert.Model('mesh.obj').To('mesh.stl');
await convert.Pdf('scan.pdf', { language: 'eng', deskew: true }).To('searchable.pdf');
await convert.Pdf('scan.pdf').To('page.png', { dpi: 300, page: 1 }); // Poppler
await convert.Pdf('scan.pdf').To('scan.txt'); // Poppler
await convert.Pdf('scan.pdf').To('small.pdf', { compress: 'screen' }); // Ghostscript
await convert.Pdf('scan.pdf').To('web.pdf', { linearize: true }); // QPDF
await convert.Font('brand.ttf').To('brand.woff2'); // WOFF2
await convert.Merge.Images(['one.png', 'two.png'], { direction: 'vertical' }).To('combined.png');
await convert.Merge.Videos(['one.mp4', 'two.mp4']).To('combined.mp4');
await convert.Merge.Pdfs(['one.pdf', 'two.pdf']).To('combined.pdf');
const status = await convert.Tools.Check();
// Explicitly install missing tools via Homebrew when needed:
// await convert.Tools.InstallMissing();The API returns a single output file. Split archives and PDF merge page numbering are rejected. Backends that produce multiple files or sidecar assets require a separate workflow. The audio converter selects FFmpeg when options such as audio_codec, sample_rate, or strip_metadata require it; select engine: 'sox' or engine: 'ffmpeg' explicitly when needed. Image compress selects lossless/lossy WebP output. Video uses container-aware defaults for MP4, MOV, MKV, WebM, and OGV. Other formats use FFmpeg defaults. Hard subtitles require an FFmpeg build with the subtitles filter (libass).
Layout
index.ts public entry point
convert/ the Convert factory and one chain class per category
engines/ backend classes that run the external tools
abstract/ shared conversion, staging, cleanup, and merge bases
capabilities/ registry of the routes the engines implement
constants/ formats.ts, mime.ts, matrices.ts, aliases.ts, routing.ts, tools.ts
interfaces/ conversion results, options, and contracts
installer.ts tool availability checks and Homebrew installation
bin/ install-tools CLI
scripts/ documentation coverage check
tests/ integration checks against the real toolsconstants/matrices.ts holds the format lists each backend reads and writes; constants/routing.ts turns those into the backend a route uses. Both the engines and capabilities/ read from them, so the registry cannot claim a route the engines will not run.
This class API replaces the original default object of convert_image, convert_audio, and other functions. Import ConversionResult for the old buffer/filename/MIME result shape; Convert now names the factory class.
Development
npm install
npm run typecheck
npm run docs:check
npm test
npm run check-toolsnpm test builds the package and exercises real conversions with ImageMagick, SoX, FFmpeg, Pandoc, LibreOffice, 7-Zip, Assimp, FontForge, WOFF2, OCRmyPDF, Poppler, QPDF, and Ghostscript. Tests whose backend is absent skip rather than fail. Install these tools before running the integration tests. npm run install-tools explicitly installs missing tools via Homebrew. For plain Node.js use the compiled entry point dist/index.js after npm run build; TypeScript consumers can use the source entry point.
Local capabilities
Every conversion runs a command on this machine. The package contains no API client, no API-key configuration, no uploads, and no remote fallback.
Capabilities reports what the engines actually implement, computed from the same backend matrices and routing policy the engines use — 2,395 routes across 135 formats and 14 local backends. Route(input, output) returns the backend a conversion will use; List(filter) and Options(input, output) describe the registry.
const convert = new Convert();
convert.Capabilities.Supports('docx', 'pdf'); // true
convert.Capabilities.Route('docx', 'pdf').backend; // 'libreoffice'
convert.Capabilities.Route('pdf', 'png').backend; // 'poppler'
convert.Capabilities.List({ backend: 'calibre' }); // ebook routes
await convert.Image('photo.png').To('photo.jpg', { fit: 'crop', width: 800, height: 800 });Backends by category:
| Category | Backends | Notes |
| --- | --- | --- |
| Image | ImageMagick | Also rasterizes PDF, EPS, and PS sources. |
| Audio | SoX, FFmpeg | SoX handles its own formats; options such as codecs or metadata stripping select FFmpeg. |
| Video | FFmpeg | Container-aware defaults; hard subtitles need a libass build. |
| Archive | 7-Zip | Writable formats are listed in ARCHIVE_WRITABLE_FORMATS. |
| Document | Pandoc, LibreOffice, Calibre | Markup uses Pandoc; office and spreadsheet formats use LibreOffice; MOBI and AZW3 use Calibre. |
| Font | FontForge, WOFF2 | WOFF2 packing and unpacking use woff2_compress and woff2_decompress, bridged by FontForge. |
| Model | Assimp | Mesh conversion. |
| PDF | OCRmyPDF, Poppler, Ghostscript, QPDF | OCR, page rendering and text extraction, optimization, and structural edits. |
PDF output selects its backend from the options supplied: compress uses Ghostscript, page selection, rotation, encryption, and linearization use QPDF, and OCR settings use OCRmyPDF. Name one explicitly with backend. Document routes pick their backend from the format pair, overridable the same way. Calibre is optional; routes needing it report the missing executable rather than failing silently.
