@betagram/censor (0.1.2)
Installation
@betagram:registry=npm install @betagram/censor@0.1.2"@betagram/censor": "0.1.2"About this package
censorlib
NSFW detection and censoring library powered by NudeNet (YOLOv8) + sharp.
Installation
npm install censorlib
Requires Node.js 18+ and the following peer dependencies:
sharp(image processing)onnxruntime-web(WASM-based ONNX inference — works in serverless)opentype.js(text overlay rendering)
Quick Start
import { censor } from 'censorlib';
import fs from 'fs';
const image = fs.readFileSync('photo.jpg');
const result = await censor(image);
if (result.censored) {
fs.writeFileSync('censored.jpg', result.image);
console.log(`Censored ${result.detections.length} regions`);
} else {
console.log('No NSFW content detected');
}
API Reference
detect(imageBuffer, options?)
Run NudeNet detection on an image buffer.
import { detect } from 'censorlib';
const detections = await detect(imageBuffer, {
scoreThreshold: 0.25, // minimum confidence (default: 0.25)
modelDir: './models', // custom model directory (default: bundled)
});
Returns Detection[]:
type Detection = {
class: NudeNetClass; // e.g. "FEMALE_BREAST_EXPOSED"
score: number; // confidence 0-1
box: [x, y, w, h]; // fractional coordinates 0-1
};
applyCensoring(imageBuffer, detections, options?)
Apply censoring to pre-detected regions.
import { detect, applyCensoring } from 'censorlib';
const detections = await detect(imageBuffer);
const result = await applyCensoring(imageBuffer, detections, {
classes: ['FEMALE_BREAST_EXPOSED', 'BUTTOCKS_EXPOSED'],
style: 'blur',
inverted: false,
});
censor(imageBuffer, options?)
All-in-one: detect + censor in a single call.
import { censor } from 'censorlib';
const result = await censor(imageBuffer, {
style: 'pixel', // 'pixel' | 'blur' | 'bar' | 'noise'
inverted: true, // censor everything EXCEPT detected regions
});
Options
| Option | Type | Default | Description |
|---|---|---|---|
scoreThreshold |
number |
0.25 |
Minimum detection confidence |
modelDir |
string |
bundled | Path to ONNX model files |
classes |
NudeNetClass[] |
DEFAULT_CENSOR_CLASSES |
Which classes to censor |
style |
CensorStyle |
'pixel' |
Visual effect style |
inverted |
boolean |
false |
Invert censor (reveal only matched regions) |
textOverlay |
TextOverlayConfig | false |
false |
Text overlay configuration |
Censor Styles
pixel— Mosaic/pixelation effectblur— Gaussian blur (sigma 30)bar— Solid black rectanglesnoise— Random static noise
Presets
Betagram
Full pipeline: mosaic base + reveal faces/feet + black boxes on exposed regions + gradient text overlays.
import { presets } from 'censorlib';
const censored = await presets.betagram(imageBuffer);
// With pre-computed detections (avoids re-detecting):
const censored = await presets.betagram(imageBuffer, { detections });
Simple
Detect + apply a single effect. Wraps censor() with sensible defaults.
import { presets } from 'censorlib';
const result = await presets.simple(imageBuffer, { style: 'blur' });
Advanced: Individual Effects
For custom pipelines, use the individual effect functions directly:
import { pixelEffect, blurEffect, barEffect, noiseEffect } from 'censorlib';
import type { PixelBox } from 'censorlib';
const boxes: PixelBox[] = [
{ x: 100, y: 200, width: 150, height: 150 },
];
const result = await pixelEffect(imageBuffer, boxes);
Full-image effects (for inverted mode base layers):
import { fullPixel, fullBlur, fullBar, fullNoise, lightMosaic } from 'censorlib';
const mosaic = await lightMosaic(imageBuffer, 24); // custom block size
const pixelated = await fullPixel(imageBuffer); // default block size
Text Overlays
import { generateTextOverlay } from 'censorlib';
import type { TextOverlayConfig, PixelBox } from 'censorlib';
const config: TextOverlayConfig = {
phrases: ['censored', 'not for you'],
fonts: [{ fontPath: 'Bellota-Bold.ttf', fontFamily: 'Bellota' }],
fontSize: 96,
color: '#FF1493',
strokeColor: '#FFFFFF',
};
const overlay = await generateTextOverlay(1024, 768, config, anchorBoxes);
NudeNet Classes
All 18 detection classes:
FEMALE_GENITALIA_COVERED, FACE_FEMALE, BUTTOCKS_EXPOSED,
FEMALE_BREAST_EXPOSED, FEMALE_GENITALIA_EXPOSED, MALE_BREAST_EXPOSED,
ANUS_EXPOSED, FEET_EXPOSED, BELLY_COVERED, FEET_COVERED,
ARMPITS_COVERED, ARMPITS_EXPOSED, FACE_MALE, BELLY_EXPOSED,
MALE_GENITALIA_EXPOSED, ANUS_COVERED, FEMALE_BREAST_COVERED,
BUTTOCKS_COVERED
Default censor classes: FEMALE_BREAST_EXPOSED, FEMALE_BREAST_COVERED, FEMALE_GENITALIA_EXPOSED, FEMALE_GENITALIA_COVERED, MALE_GENITALIA_EXPOSED, BUTTOCKS_EXPOSED, BUTTOCKS_COVERED, ANUS_EXPOSED, ANUS_COVERED.
Model Files
The library bundles two ONNX models in the models/ directory:
320n.onnx— YOLOv8n NudeNet detector (320x320 input)nms-yolov8.onnx— Non-maximum suppression post-processor
Models use onnxruntime-web (WASM backend) — no native binaries needed. Works in serverless environments (Vercel, AWS Lambda, etc.).
Serverless Compatibility
- Uses WASM-based ONNX runtime (no native
.nodebinaries) - Font rendering via opentype.js path conversion (no system fonts needed)
- All assets resolve from the package directory, not
process.cwd()
Dependencies
Dependencies
| ID | Version |
|---|---|
| onnxruntime-web | ^1.24.1 |
| opentype.js | ^1.3.4 |
| sharp | ^0.34.1 |
Development Dependencies
| ID | Version |
|---|---|
| @types/node | ^22.10.2 |
| tsx | ^4.19.0 |
| typescript | ^5.7.2 |