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 ( - 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). width and height are 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.ensemble is 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 throttled Stream<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 a Stack over your image, matched to the same BoxFit so 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. NsfwGalleryTheme is 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 String field (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.icon that 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 Column of 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, gap etc.
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).textTheme and 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 their Info.plist (iOS) / AndroidManifest.xml declarations are in place before invoking any media API — the alternative on iOS is SIGABRT the first time the OS sees a missing NSPhotoLibraryUsageDescription.
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 by BoundingBox and 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
SharedPreferencesDecisionStore
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). Returns null for 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 < 2s reads 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

BackgroundSweepUnavailableError
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.