• Joined on 2026-01-12

@betagram/censor (0.1.1)

Published 2026-02-21 09:58:18 -08:00 by jesse

Installation

@betagram:registry=
npm install @betagram/censor@0.1.1
"@betagram/censor": "0.1.1"

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 effect
  • blur — Gaussian blur (sigma 30)
  • bar — Solid black rectangles
  • noise — 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 .node binaries)
  • 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
Details
npm
2026-02-21 09:58:18 -08:00
0
11 MiB
Assets (1)
Versions (3) View all
0.1.2 2026-02-21
0.1.1 2026-02-21
0.1.0 2026-02-21