Normalize images into fixed, transparent canvases locally via a deterministic pipeline. Provides a CLI and a programmatic ESM API.
npm install media-normalizerRequires Node.js 24+.
- Semantic versioning driven by conventional commits
media-normalizer --input <path|url> --output <path> --preset square-1024
# Batch example
media-normalizer --input-dir ./photos --output-dir ./normalized --preset square-1024 --recursive trueCommon flags:
--input <path|url>: Source image (file path or HTTP/HTTPS URL). Supports common formats (jpg/jpeg/png/webp/...).--output <path>: Destination path (default format webp).- Batch:
--input-dir <dir>plus--output-dir <dir>to process a directory (use--recursive true|false,--glob <pattern>). --preset <name>: Use a preset JSON (bundled or via--presets-dir).--width <px> --height <px>: Canvas size (required when no preset).--object-scale <0-1>: Scale relative to canvas height.--background r,g,b[,a]: Background color; alpha 0–1 (default transparent).--format <png|webp>: Output format (default webp).- Size targeting: encoders adaptively compress (near-lossless + tuned quality/effort) to stay sharp while reducing file size.
--list-presets: List available presets.--help: Show full help.
import {
normalizeImage,
loadPreset,
applyPresetOverrides,
listAvailablePresets,
detectAlphaBoundingBox,
classifyShape,
classifyShapeDebug,
processBatch,
} from "media-normalizer";
import { promises as fs } from "node:fs";
const preset = await loadPreset("square-1024");
const options = applyPresetOverrides(preset, { objectScale: 0.95, format: "webp" });
const result = await normalizeImage("input.jpg", options);
// buffer is WebP by default; set format: "png" for PNG
await fs.writeFile("output.webp", result.buffer);
// Batch processing example
const batchResult = await processBatch({
inputs: ["one.jpg", "two.png"],
outputDir: "./out",
normalization: options,
});
console.log(batchResult.results);Key behaviors:
- Loads from file paths or HTTP(S) URLs (common formats like jpg/png/webp and more).
- Ensures alpha, strips backgrounds (alpha-aware with flat background keying), places the object on a fixed canvas, and preserves transparency.
- Uses deterministic shape classification (bottle, box, tube, generic) to adjust scaling and centering.
- Adaptive compression tunes quality/effort and performs a size-aware pass (WebP aims for ~50% of input or 100 KB target when possible).
classifyShapeDebugreturns{ shape, confidence }for debugging without affecting classification results.
Presets are external JSON files (see presets/ for examples). Shape:
{
"name": "square-1024",
"width": 1024,
"height": 1024,
"objectScale": 0.9,
"background": { "r": 0, "g": 0, "b": 0, "alpha": 0 }
}Included presets:
square-1024instagram-square-1080instagram-portrait-1080x1350instagram-story-1080x1920social-cover-1200x628blog-9x16-1080x1920twitter-post-1200x675twitter-header-1500x500
List available presets via CLI:
media-normalizer --list-presetsLoad custom presets by pointing --presets-dir to your folder.
MIT
npm testAdd tests under src/ or alongside features using Node’s built-in test runner.
Run tests with coverage by passing Node’s experimental flag:
npm test -- --experimental-test-coverageCoverage reports will be emitted by Node; no external tooling is required.
- Install dependencies:
npm install - Build:
npm run build - Test:
npm test - For coverage, use the flag above.