Install
npm install @nosmai/moderation-react-native
The native SDK ships with the plugin:
- iOS: run
pod install. Requires iOS 14+. - Android: download
nosmai-detection.aarfrom the releases page intoandroid/app/libs/and reference it, withminSdk 24,arm64-v8a, and Kotlin 2.2.0+.
Requirements: React Native with the New Architecture enabled. For the live camera add NSCameraUsageDescription (iOS) and the CAMERA permission (Android); on iOS also set ITSAppUsesNonExemptEncryption to NO in Info.plist.
Initialize
Call once at startup with your license key and the models you need. Native inference runs off the JS thread.
import { NosmaiModeration } from '@nosmai/moderation-react-native';
const init = await NosmaiModeration.initialize('NOSMAI-XXXX', [
'objectDetection',
'nsfw',
'text',
]);
if (!init.success) console.warn('init failed:', init.error);
Moderate an image
Pass a file path (for example from react-native-image-picker; strip the file:// prefix).
const r = await NosmaiModeration.analyzeImage(filePath); // NosmaiResult
if (r.isUnsafe) {
// r.detections -> [{ category, confidence }], r.nsfw -> 'safe' | 'warn' | 'block'
}
Moderate a video
const v = await NosmaiModeration.analyzeVideo(filePath, 500); // frameIntervalMs
if (v.isUnsafe) {
// v.categories, v.framesAnalyzed, v.nsfw
}
Moderate text
Load the text model once (after initialize), then moderate messages.
await NosmaiModeration.initializeText();
const t = await NosmaiModeration.moderateText('some message');
if (t.blocked) {
// t.layer ('blocklist' | 'classifier'), t.category, t.matchedWord
}
Live camera
Render <NosmaiCameraPreview />. The native view owns the camera: it starts on mount and stops on unmount. Request camera permission before mounting it.
import { NosmaiCameraPreview } from '@nosmai/moderation-react-native';
<NosmaiCameraPreview
style={{ width: '100%', height: 320 }}
facing="back" // or "front"
onResult={(r) => {
// r.isUnsafe, r.nsfw, r.detections — one result per analyzed frame
}}
/>
On the live camera, a suggestive (warn) verdict that persists for several seconds is escalated to block, so sustained borderline content is treated as unsafe.
Thresholds
NosmaiModeration.setThreshold('weapon', 0.7);
NosmaiModeration.setNsfwThreshold('explicit', 0.45); // block
NosmaiModeration.setNsfwThreshold('sexy', 0.55); // warn
Cleanup
NosmaiModeration.shutdown();
[!NOTE] Enums cross the bridge as strings, so
category,nsfw,layerand the rest are plain string values you can compare directly.