Automatically convert and resize images to modern formats (WebP, AVIF, PNG, JPEG, TIFF) with real-time file watching and flexible resize options.
v3.0.0 β breaking config/path fixes vs 2.2.x. See Breaking changes and CHANGELOG.md.
π Convert images to WebP, AVIF, PNG, JPEG, or TIFF
π Resize inside convert (needResize) and/or via a separate resize command (same format, dimensions only)
πΎ needResizeOriginal β also save the resized file in the source format
π Per-command paths β separate dir / removeOriginal / outputDir for convert and resize
π Watch convert + watch resize β process new files as they arrive (FTP/drop folders friendly)
β‘ Parallel workers via concurrency
ποΈ flat / mirror output layout
βοΈ Easy configuration via image-converter.config.mjs (fully commented sample in the repo)
npm install auto-image-converter --save-devOr develop in this repo:
npm install
npm run convert
npm run watch
npm run resize
npm run resize:watchOr use locally via npm link:
cd auto-image-converter
npm link
cd ../your-project
npm link auto-image-converterCreate image-converter.config.mjs in the project root (same folder you run npm scripts from β cwd):
export default {
// Shared
recursive: true, // walk subfolders under each command's dir
concurrency: 4, // parallel workers
ignoreOnStart: true, // watch: skip files that already exist on startup
// --- convert + watch (auto-convert-images / auto-convert-images-watch) ---
convertation: {
dir: "./public/original", // where to look for sources (cwd-relative or absolute)
removeOriginal: true, // delete source from convertation.dir after success
converted: "png,jpg,jpeg,tiff", // source formats (comma-separated)
format: "webp", // output codec: webp | avif | png | jpg | jpeg | tiff
quality: 80, // 0β100
outputDir: "./public/converted", // null = next to source
outputDirMode: "flat", // flat | mirror (mirror keeps subfolders from dir)
needResize: true, // resize once, then encode β outputDir
needResizeOriginal: false, // also write resized SOURCE format β resize.outputDir
},
// --- resize geometry + resize / resize:watch (no format change) ---
resize: {
dir: "./public/converted", // scan folder for resize CLI / resize:watch
removeOriginal: false, // independent from convertation.removeOriginal
width: 1920, // or null if only height
height: null, // or null if only width
fit: "cover", // cover | contain | fill | inside | outside
position: "center",
withoutEnlargement: true, // don't upscale smaller images
targetFormat: "webp", // which files to resize: "webp" | "png,jpg" | null β convertation.format
outputDir: "./public/resized", // null + removeOriginal true β overwrite; false β -1920w suffix
outputDirMode: "flat",
},
};The same file in this repo has longer English comments on every field.
convert / watch |
resize / resize:watch |
|
|---|---|---|
| Scan folder | convertation.dir |
resize.dir |
| Delete source | convertation.removeOriginal |
resize.removeOriginal |
| Output folder | convertation.outputDir |
resize.outputDir |
| Format change | yes β convertation.format |
no β same extension |
| Which files | convertation.converted |
resize.targetFormat |
Top-level dir / removeOriginal / needResize still work with a deprecation warning; prefer per-section fields.
| Value | Meaning |
|---|---|
Relative (./public/original) |
From cwd |
| Absolute | Used as-is |
outputDir: null |
Next to the source file |
On Windows prefer ./public/.... A path like /public is absolute from the drive root.
outputDirMode
flat(default) βoriginal/tests/cat.pngβconverted/cat.webpmirrorβ keep subfolders fromdirβconverted/tests/cat.webp
Same style everywhere β comma-separated extensions (no *.{β¦} required):
converted: "png"
converted: "png,jpg,jpeg,tiff"
targetFormat: "webp"
targetFormat: "png,jpg,webp"
targetFormat: null // β convertation.formatLegacy *.{png,jpg} still works if you already have it in a config.
needResize: trueβ resize once in memory, then encode toformatβconvertation.outputDirneedResizeOriginal: trueβ also write resized source-format file βresize.outputDir
(requiresneedResize+resize.outputDir)
resize:watch on the same files if convert already resized them β youβll resize twice.
- By width only:
width: 1920, height: null - By height only:
width: null, height: 1080 - To a box:
width: 1920, height: 1080(usesfit)
withoutEnlargement: true β never upscale; only shrink larger images.
coverβ fill size, crop excess (default)containβ fit inside, may padfillβ stretchinsideβ fit inside, no enlargeoutsideβ cover size, may enlarge
# One-time convert (+ optional needResize in the same pass)
npx auto-convert-images
npm run convert
# Watch convert β convertation.dir
npx auto-convert-images-watch
npm run watch
# One-time resize (same format, dimensions only)
npx auto-convert-images-resize
npm run resize
# Watch resize β resize.dir
npx auto-convert-images-resize-watch
npm run resize:watch{
"scripts": {
"convert": "auto-convert-images",
"watch": "auto-convert-images-watch",
"resize": "auto-convert-images-resize",
"resize:watch": "auto-convert-images-resize-watch"
}
}npm install concurrently --save-dev{
"scripts": {
"dev": "concurrently \"npm run watch\" \"next dev\""
}
}Add resize:watch only if you use a separate resize stage.
convertation.dir = ./public/original
convertation.outputDir = ./public/converted
convertation.needResize = true
npm run convert # or npm run watch
FTP β convertation.dir
npm run watch
Watch waits for a stable file size before processing.
# convert with needResize: false
convertation.dir β convertation.outputDir
# then
resize.dir = ./public/converted
resize.targetFormat = "webp"
resize.outputDir = ./public/resized
npm run resize # or npm run resize:watch
resize.removeOriginal: false+outputDir: nullβ size suffix (image-1920w.webp)resize.removeOriginal: true+outputDir: nullβ overwrite source
resize.dir = ./public/original
resize.targetFormat = "png,jpg"
npm run resize
- Pipeline β queue + workers (convert or resize mode)
- ResizeImages / ConvertImages β Sharp wrappers
- FileManager β path resolution (
flat/mirror, cwd-relative) - globPattern β strict
*.{β¦}parsing
- Relative
outputDir/dirresolve from cwd (2.2.x relativeoutputDirwas from the source file folder) - Absolute
outputDiris flat (2.2.x added a per-file name subfolder) - Prefer
convertation.dir/resize.dirand per-sectionremoveOriginal needResize/needResizeOriginalunderconvertation- Prefer
converted/targetFormatas"png,jpg"(legacy*.{β¦}still ok) - Resize CLI uses
resize.dir+targetFormat(still no format conversion β same as 2.2.x intent) - New:
auto-convert-images-resize-watch
Full details: CHANGELOG.md.
Report issues on GitHub Issues. Include description, steps, expected/actual behavior, config, Node.js version, and OS.
MIT β free to use, modify, and distribute with proper attribution.