Skip to content

marcelfortmann/media-normalizer

Repository files navigation

Media Normalizer

Normalize images into fixed, transparent canvases locally via a deterministic pipeline. Provides a CLI and a programmatic ESM API.

Install

npm install media-normalizer

Requires Node.js 24+.

Release & Versioning

  • Semantic versioning driven by conventional commits

CLI

media-normalizer --input <path|url> --output <path> --preset square-1024
# Batch example
media-normalizer --input-dir ./photos --output-dir ./normalized --preset square-1024 --recursive true

Common 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.

Programmatic API (ESM)

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).
  • classifyShapeDebug returns { shape, confidence } for debugging without affecting classification results.

Presets

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-1024
  • instagram-square-1080
  • instagram-portrait-1080x1350
  • instagram-story-1080x1920
  • social-cover-1200x628
  • blog-9x16-1080x1920
  • twitter-post-1200x675
  • twitter-header-1500x500

List available presets via CLI:

media-normalizer --list-presets

Load custom presets by pointing --presets-dir to your folder.

License

MIT

Tests

npm test

Add tests under src/ or alongside features using Node’s built-in test runner.

Test coverage flag

Run tests with coverage by passing Node’s experimental flag:

npm test -- --experimental-test-coverage

Coverage reports will be emitted by Node; no external tooling is required.

Contribution

  1. Install dependencies: npm install
  2. Build: npm run build
  3. Test: npm test
  4. For coverage, use the flag above.

About

Normalize media into consistent canvases

Resources

License

Stars

Watchers

Forks

Packages

No packages published