nsfw_detect library
Privacy-friendly, on-device NSFW detection for Flutter apps.
Import this library to access the headless scan APIs, configuration types, result models, permission helpers, and ready-to-use widgets exposed by the package.
Classes
- BackgroundSweepOptions
- Options for NsfwDetector.scheduleBackgroundSweep.
- BlockPerceptualHash
-
Crop-resistant perceptual hash. Divides the image into an N×N grid (default
4×4 = 16 blocks) and computes an 8×8 dHash per block. Two images that
share content survive cropping that removes up to (
N²-minMatchingBlocks) blocks of either side — at the default 6-of-16 threshold this tolerates losing roughly 60% of the original frame. - BodyPartDetection
- One body-part detection produced by an object-detection model (NudeNet-style). The raw label is the verbatim class name from the model — see BodyPartDetection.aggregateCategoryFromLabel for the canonical NsfwCategory mapping the detector applied at scan time.
- BoundingBox
-
Axis-aligned, normalised bounding box. All values are in
[0, 1]with origin top-left, matching CoreML/Vision and TFLite SSD-style detectors (after the y-flip iOS performs internally).widthandheightare the box extents — NOT the (right, bottom) corner. - CameraConfiguration
- Configuration for a live camera scan session.
- CameraFrameResult
- Classification result for a single camera frame.
- CameraScanSession
- Live camera scan session.
- CropResistantCache
- LRU cache keyed by BlockPerceptualHash. Same shape as PerceptualCache but resilient to crops — ideal for forwarded-image moderation where the same content reappears with different framing.
- DecisionChange
-
(localId, decision)change notification emitted by DecisionStore.changes. - DecisionStore
-
Persistent map of moderator overrides keyed by an asset's
localIdentifier. - EnsembleStrategy
-
How NsfwDetector reconciles results from multiple classifier models
when
ScanConfiguration.ensembleis set. - FrameStreamScanner
-
Adapter that turns an arbitrary
Stream<Uint8List>of encoded image frames (JPEG / PNG / WebP — anything Flutter's image codecs can decode) into a throttledStream<ScanResult>. - InMemoryDecisionStore
- Volatile in-memory DecisionStore. Lost on process restart — good enough for tests and the small-library cases where the host app already persists its own decision state out of band.
- MajorityEnsemble
- Majority vote with confidence-band borderline rescue.
- MediaItem
- ModelDescriptor
- ModelDownloadProgress
- Typed download-progress event emitted by NsfwDetector.downloadProgress. Native sends one of these per chunk while a model download is in flight.
- ModelIds
- ModelRegistration
- Runtime registration payload for a custom on-device model.
- ModelStateSnapshot
- Immutable snapshot of one model's current state.
- NsfwAnimations
- Animation curve / duration tokens. Use the named values rather than hard-coding milliseconds so the plugin can tune motion globally.
- NsfwBulkAction
-
A bulk action consumers can register on NsfwGalleryView when
enableSelection: true. The plugin renders the action chip; the consumer performs the work in onInvoke. - NsfwCameraHud
- Heads-up display for NsfwCameraView (Phase 04 / WIDGET-02).
- NsfwCameraView
- Live camera preview with an on-device NSFW classification overlay.
- NsfwDetectionOverlay
-
Paints NudeNet-style bounding boxes (and optional labels) on top of a
thumbnail. Pure
CustomPainter; place inside aStackover your image, matched to the sameBoxFitso the normalised box coordinates land on the right pixels. - NsfwDetector
- Main entry point for on-device NSFW scanning.
- NsfwElevation
- Elevation / shadow tokens.
- NsfwFilterBar
- Horizontal pill row letting users edit a NsfwGalleryFilter. Each pill opens a small picker (modal bottom sheet) to mutate one facet. The bar is presentation-only — it never touches scan data; pass the new value back via onChanged.
- NsfwGalleryFilter
- View-only filter for NsfwGalleryView. Original scan data is never mutated — items hidden by the filter remain in the underlying buffer.
- NsfwGalleryTheme
-
Legacy theme container for the gallery widgets. Still works as before, but
new widgets should consume NsfwTheme which carries a full token set.
NsfwGalleryThemeis preserved for backwards compatibility — every existing constructor argument and field name is intact. - NsfwGalleryView
- Pre-built photo-library scan UI backed by a NsfwScanController.
- NsfwInitOptions
- Options consumed by NsfwDetector.init.
- NsfwInitReport
- Aggregated result returned by NsfwDetector.init.
- NsfwLabel
- NsfwLabelBar
- Animated horizontal bar showing the confidence of one NsfwLabel. Suitable as a building block for custom detail layouts.
- NsfwLocalizations
-
Bundle of localized strings used by
nsfw_detect's non-widget helpers (PhotoLibraryPermissionStatus.userMessage,NsfwCategory.displayName,ScanResult.confidenceDescription,NsfwSafetyProfile.ageRating). - NsfwLocalizationsDe
-
German (
de). - NsfwLocalizationsEn
- English (default).
- NsfwLocalizationsEs
-
Spanish (
es). - NsfwLocalizationsFr
-
French (
fr). - NsfwLocalizationsJa
-
Japanese (
ja). - NsfwMediaTile
- NsfwModel
-
Marks a
static const Stringfield (or a class) as a registered NSFW model. - NsfwModelManager
- High-level model lifecycle facade. Wraps the bare per-method APIs on NsfwPlatformInterface with batch-preload, ensure-ready (download-then- load), and a tracked state machine you can subscribe to from UI.
- NsfwModerationGate
- Drop-in moderation gate. Scans the configured media source (bytes, file path, or photo-library asset id) and decides whether to render child or a blocked / blurred fallback.
- NsfwPermissionsView
- Reusable permission panel for NSFW scanning features.
- NsfwPickerButton
-
One-shot pick-and-scan trigger. Renders a
FilledButton.iconthat opens the native picker, scans the selection, and hands back a ScanSession via onSession. The button shows a small loading indicator while the picker is open and the scan is starting. - NsfwPickMediaButton
- Convenience wrapper around NsfwDetector.pickMedia that exposes a button returning the picked items without scanning them. Pair with NsfwDetector.scanAsset for on-demand classification.
- NsfwResultBadge
- NsfwResultDetailView
-
Detailed read-only view of a single ScanResult. Renders a square
thumbnail, a detailed badge, the per-label confidence bars, and a metadata
card. Photo-library agnostic — supply thumbnailBuilder to inject your own
image widget (e.g. via
photo_manager). - NsfwResultRedactor
- Renders child with NSFW content redacted based on a ScanResult.
- NsfwScanController
- State holder for an interactive photo-library NSFW scan flow.
- NsfwScanControls
- NsfwScanProgressBar
- NsfwScanSummarySheet
-
Bottom-sheet body summarising a completed scan. Show via
showModalBottomSheet. Counter values animate from 0 to their final value using a TweenAnimationBuilder so the sheet feels alive when it appears. - NsfwSearchField
- A debounced text input. Emits trimmed lower-case query strings via onChanged after the user pauses typing for debounce. Designed for inline use in the gallery — but generic enough to drop anywhere.
- NsfwSelectionToolbar
- Toolbar shown when NsfwGalleryView enters selection mode. Renders one button per NsfwBulkAction plus a counter and a close affordance.
- NsfwSettingsPanel
-
Reusable settings panel that exposes the most common
ScanConfiguration knobs (model picker, scan options, maintenance
actions). Drop into any host scaffold — the widget is a
Columnof sections, not a screen. - NsfwSkeletonGrid
- Convenience grid of skeleton tiles. Drop in while permission is pending or before the first result reaches the UI.
- NsfwSkeletonTile
- Animated placeholder tile shown in the gallery before any results stream in. Uses a slow opacity pulse — light enough not to be distracting on a dense grid, but enough to signal that content is loading.
- NsfwSpacing
-
Spacing scale used across the plugin's widgets. The numbers are powers-of-2
up to 16, then jumps of 8. Pass these to
Padding,SizedBox,gapetc. - NsfwTheme
- Full design-token bundle consumed by the next-generation plugin widgets (summary sheet, detail view, settings panel, picker button, skeleton tile, etc.). Wraps the legacy NsfwGalleryTheme so every widget that already accepts the legacy theme keeps working.
- NsfwTypography
-
Typography ramp. Each role is nullable so callers can pull from
Theme.of(context).textThemeand only override the slots they need. - NsfwUninitializedPlatform
- Exposed so NsfwDetector can detect the uninitialized state.
- PerceptualCache
-
LRU cache mapping PerceptualHashes to ScanResults. Useful as a
pre-check before paying the cost of
scanBytes— if you've already classified a near-duplicate, you can reuse the previous label. - PerceptualHash
-
64-bit perceptual hash of an image. Computed from a 9x8 grayscale
downsample using the difference-hash (dHash) algorithm — each of
the 64 bits encodes whether pixel
(x, y)is brighter than(x+1, y). - PickedMedia
- One item returned by NsfwDetector.pickMedia.
- PlatformSetupReport
-
Snapshot of host-app platform setup. Returned by
NsfwDetector.instance.checkPlatformSetup()so apps can verify theirInfo.plist(iOS) /AndroidManifest.xmldeclarations are in place before invoking any media API — the alternative on iOS is SIGABRT the first time the OS sees a missingNSPhotoLibraryUsageDescription. - ScanConfiguration
- Immutable options for a photo-library NSFW scan.
- ScanProgress
- ScanRegion
-
A rectangular sub-region of an image, expressed in normalized coordinates
in
[0, 1]with origin top-left. Matches the convention used byBoundingBoxand the native detectors. - ScanResult
- Classification or detection result for one photo-library asset, file, or byte-buffer scan.
- ScanSession
- Running photo-library or picker scan.
- ScanSummary
-
Persistent DecisionStore backed by
shared_preferences. - TelemetryEvent
-
Structured event emitted to
NsfwDetector.onTelemetryEvent. - WeightedEnsemble
- Weighted average of per-category confidences.
Enums
- AndroidDelegate
-
Android TFLite delegate preference.
null= CPU (default). - BadgeStyle
- CameraResolution
- Resolution preset for the live camera feed.
- IosComputeUnits
-
iOS Core ML compute-unit preference. Mirrors
MLComputeUnits. - MediaPickerType
- Filter passed to NsfwDetector.pickMedia. Determines whether the native picker shows images, videos, or both.
- MediaType
- ModelKind
- Identifies which inference path consumes a custom-registered model.
- ModelStatus
- Lifecycle states a model can be in.
- NsfwCategory
- NsfwGallerySort
- Sorting options for NsfwGalleryFilter — applied AFTER filtering.
- NsfwRedactionStyle
- Strategy used to obscure flagged regions.
- NsfwSafetyProfile
- Pre-tuned safety profiles bundling a recommended NSFW confidence threshold with a short age-rating label. Use these as a starting point when wiring a moderation gate so you don't have to invent thresholds from scratch.
- PermissionKind
- Identifies which permission a row in NsfwPermissionsView represents.
- PermissionStatus
- Aggregate permission status the widget renders.
- PhotoLibraryPermissionStatus
- ProgressBarStyle
- RedactionMode
- How NsfwDetector.redactBytes / NsfwDetector.redactFile should obscure flagged regions of an image.
- ScanDecision
- User override applied to a scan result.
- ScanMode
- Scan mode determines which kind of ML pipeline runs natively for each asset.
- ScanStatus
- Terminal status for scanning a single media item.
- TelemetryEventType
- Discriminator for TelemetryEvent. New variants may be added in a minor release; callers should treat unknown enum entries as ignorable rather than throwing.
Extensions
- PhotoLibraryPermissionStatusMapping on PhotoLibraryPermissionStatus
-
ScanResultListConvenience
on List<
ScanResult> -
Convenience aggregations and diffs over
List<ScanResult>.
Functions
-
confidenceBucketOf(
double? confidence) → int? -
Buckets a
[0.0, 1.0]confidence into a decile (0..9). Returnsnullfor negative or non-finite inputs so callers can carry through "no score". -
defaultEtaLabel(
Duration remaining) → String -
Default formatter used when NsfwScanProgressBar.etaFormatter is null.
Conservative: hides the ETA for the first ~3s (
Duration < 2sreads as "0s remaining" otherwise), rounds to seconds under a minute, minutes thereafter.
Typedefs
- CameraErrorCallback = void Function(Object error)
- CameraResultCallback = void Function(CameraFrameResult result)
- DecisionLookup = ScanDecision? Function(String? localId)
-
Synchronous lookup signature for
(localId) → ScanDecision?used by ScanSession to attach moderator overrides to results without an async dispatch per emission. - NsfwMediaTileBuilder = Widget Function(BuildContext context, MediaItem item, ScanResult? result, Widget thumbnail)
- PermissionChangedCallback = void Function(PermissionKind kind, PermissionStatus status)
- PermissionLabelBuilder = String Function(PermissionKind kind, PermissionStatus status, BuildContext context)
- TelemetryHandler = void Function(TelemetryEvent event)
-
Signature for the telemetry sink installed on
NsfwDetector.onTelemetryEvent. Handlers MUST be fast and MUST NOT throw — the detector swallows exceptions but a slow handler will back up the scan pipeline.
Exceptions / Errors
- Thrown by NsfwDetector.scheduleBackgroundSweep when the host app hasn't completed the platform integration described in BackgroundSweepOptions's doc.
- CameraErrorException
- Exception thrown when a camera error occurs.
- CameraPermissionDeniedException
- Exception thrown when camera permission is denied.