stable-diffusion-cpp-node-api
v0.9.3
Published
Node.js N-API bindings for stable-diffusion.cpp — run Stable Diffusion, SDXL, SD3, FLUX, and Wan video models natively
Downloads
408
Maintainers
Readme
node-stable-diffusion-cpp
WARNING: This library was vibe coded. The entire codebase — C++ bindings, JS wrappers, build system, and documentation — was generated by an AI assistant in a single session. It compiles, passes basic smoke tests, and the API surface matches the upstream C library. However, it has not been battle-tested in production. Edge cases, memory leaks under unusual error paths, and platform-specific build quirks may exist. Use at your own risk, report issues, and read the source before shipping anything important.
Native Node.js bindings for stable-diffusion.cpp — a pure C/C++ implementation of Stable Diffusion, SDXL, SD3, FLUX, Wan video, and more. Built on N-API for ABI stability across Node.js versions. All heavy operations (model loading, image/video generation, upscaling) run on background threads and return Promises.
Features
- Image generation — txt2img, img2img, inpainting, ControlNet, PhotoMaker, LoRA
- Video generation — Wan2.1/2.2 text-to-video and image-to-video
- Upscaling — ESRGAN-based super resolution
- Model conversion — safetensors/ckpt to GGUF quantized formats
- GPU auto-detection — Metal (macOS), CUDA (Linux/Windows), Vulkan
- Async everything — context creation, generation, upscaling all return Promises
- Callbacks — log, progress, and preview callbacks bridged to the JS event loop
- Electron-ready — N-API v8 targets Node.js 18+ / Electron 22+
- TypeScript — full type declarations included
Requirements
- Node.js >= 18
- CMake >= 3.15
- C++17 compiler (Xcode, GCC 9+, MSVC 2019+)
- Platform SDK for GPU backend (Xcode for Metal, CUDA Toolkit for NVIDIA, Vulkan SDK)
Installation
git clone --recursive <your-repo-url>
cd node-stable-diffusion-cpp
npm installThe npm install step compiles the native module. On macOS it automatically enables Metal; on systems with CUDA or Vulkan SDKs installed, those backends are enabled too.
Manual build
npm run build # Release build
npm run build:debug # Debug build
npm run rebuild # Clean + rebuild
npm run clean # Remove build artifactsQuick start
const sd = require('node-stable-diffusion-cpp');
const fs = require('fs');
// Optional: log what the library is doing
sd.setLogCallback(({ level, text }) => {
if (level >= 1) process.stderr.write(text);
});
// Optional: track generation progress
sd.setProgressCallback(({ step, steps, time }) => {
process.stderr.write(`\rStep ${step}/${steps} (${time.toFixed(1)}s)`);
});
(async () => {
// Load a model (runs on background thread)
// Use modelPath for single-file models (ckpt, safetensors, full gguf).
// Use diffusionModelPath only for standalone diffusion-only component files.
const ctx = await sd.StableDiffusionContext.create({
modelPath: 'path/to/model.gguf',
});
// Generate an image
const images = await ctx.generateImage({
prompt: 'a photo of an astronaut riding a horse on mars',
width: 512,
height: 512,
sampleParams: {
sampleSteps: 20,
guidance: { txtCfg: 7.0 },
},
});
// Save raw RGB pixels (use stb_image or sharp to encode to PNG)
const img = images[0];
console.log(`\nGenerated ${img.width}x${img.height} image (${img.data.length} bytes)`);
fs.writeFileSync('output.raw', img.data);
ctx.close();
})();Smoke test
A ready-made script is included:
node smoke.js path/to/model.ggufEdit the constants at the top of smoke.js to change prompt, dimensions, steps, etc.
API overview
| Function / Class | Description |
|---|---|
| StableDiffusionContext.create(opts) | Load a model, returns Promise<StableDiffusionContext> |
| ctx.generateImage(opts) | Text/image to image, returns Promise<SdImage[]> |
| ctx.generateVideo(opts) | Text/image to video frames, returns Promise<SdImage[]> |
| ctx.getDefaultSampleMethod() | Default sampler for loaded model |
| ctx.getDefaultScheduler(method?) | Default scheduler for sampler |
| ctx.close() | Free native resources |
| UpscalerContext.create(opts) | Load ESRGAN model, returns Promise<UpscalerContext> |
| upscaler.upscale(image, factor?) | Upscale an image, returns Promise<SdImage> |
| convert(opts) | Convert model format, returns Promise<boolean> |
| preprocessCanny(image, opts?) | Canny edge detection (sync, in-place) |
| setLogCallback(fn) | Set/clear log callback |
| setProgressCallback(fn) | Set/clear progress callback |
| setPreviewCallback(fn, opts?) | Set/clear preview callback |
| getSystemInfo() | Backend/hardware info string |
| getNumPhysicalCores() | CPU core count |
| version() / commit() | Library version and git commit |
See docs/API.md for the full API reference with all options, types, and examples.
Supported models
Anything stable-diffusion.cpp supports:
- Stable Diffusion 1.x, 2.x
- SDXL, SDXL Turbo
- SD3, SD3.5
- FLUX.1 (dev, schnell)
- Wan2.1, Wan2.2 (video)
- Chroma, Qwen-Image
- LoRA, ControlNet, PhotoMaker
- GGUF quantized models (Q4_0, Q5_0, Q8_0, F16, etc.)
Image data format
All images are plain objects with raw pixel data:
interface SdImage {
width: number; // pixels
height: number; // pixels
channel: number; // 3 for RGB
data: Buffer; // raw RGB bytes, length = width * height * channel
}To save as PNG, use a library like sharp:
const sharp = require('sharp');
await sharp(img.data, { raw: { width: img.width, height: img.height, channels: img.channel } })
.png()
.toFile('output.png');License
MIT. See LICENSE.
stable-diffusion.cpp is also MIT licensed. GGML is MIT licensed.
