Custom capture UI
Use MBCaptureSessionView when your application must own the surrounding controls and layout. The SDK still manages camera capture and validation; your component renders the guidance, progress, and buttons around the camera preview.
The capture starts when the view mounts and stops when it unmounts.
Request camera permission
On Android, the custom view does not request camera access for you. Request it before rendering the view:
import { PermissionsAndroid, Platform } from "react-native";
async function hasCameraPermission(): Promise<boolean> {
if (Platform.OS !== "android") {
return true;
}
const result = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA);
return result === PermissionsAndroid.RESULTS.GRANTED;
}
On iOS, include NSCameraUsageDescription in Info.plist; iOS asks the user the first time the camera starts.
Add the capture view
import { useState } from "react";
import { StyleSheet, Text, View } from "react-native";
import {
MBCaptureSessionView,
setCaptureSessionOptions,
MBCaptureConstraints,
MBImageQualityLevel,
type MBCaptureSessionResult,
} from "@mobaibio/mobai-biometric";
const options = setCaptureSessionOptions({
videoCaptureDuration: 2000,
captureConstrains: MBCaptureConstraints.V3,
imageQualityLevel: MBImageQualityLevel.LEVEL_2,
sessionId: sessionId,
});
export function CustomCaptureScreen() {
const [feedback, setFeedback] = useState("");
const [progress, setProgress] = useState(0);
const [countdown, setCountdown] = useState("");
return (
<View style={styles.screen}>
<MBCaptureSessionView
options={options}
onFaceBoundingBoxValidating={(poses, distance, positions, lighting, isValid) =>
setFeedback(feedbackText(poses, distance, positions, lighting, isValid))
}
onFaceCaptureCountDown={setCountdown}
onFaceCaptureStarted={() => setFeedback("Hold still")}
onFaceCaptureProgress={setProgress}
onFaceCaptureSuccess={(result: MBCaptureSessionResult) => upload(result)}
onFaceCaptureFailed={(message: string) => showRetry(message)}
style={styles.camera}
/>
<Text style={styles.feedback}>{countdown || feedback}</Text>
</View>
);
}
const styles = StyleSheet.create({
screen: { flex: 1 },
camera: { flex: 1 },
feedback: { fontSize: 18, textAlign: "center", padding: 16 },
});
Unmount MBCaptureSessionView when the screen is no longer visible so the camera stops. Mount it again to start another capture.
Options
Pass the options through setCaptureSessionOptions():
| Option | Default | Purpose |
|---|---|---|
numberOfFrameToCollect | 3 | Number of frames sampled from the video interval. |
videoCaptureDuration | 1000 | Video duration in milliseconds, clamped to 1000–3000. |
timeBeforeAutomaticCapture | 1 | Countdown duration in seconds. |
captureConstrains | MBCaptureConstraints.V1 | Selects the V1, V2, or V3 validation pipeline. |
imageQualityLevel | MBImageQualityLevel.LEVEL_3 | Selects V3 lighting strictness. It has no effect on V1 or V2. |
sessionId | — | Key for the authenticated sessionMetadata and sessionVideoMetadata. |
targetResolution | TargetResolution.HD_720 | Capture resolution: HD_720, HD_1080, or HD_4K. QHD is deprecated and falls back to HD_720. |
previewScaleType | PreviewScaleType.fill | fill covers the view and crops the preview; fit shows the full camera frame. Captured images are not affected. |
isDebugging | false | Enables SDK diagnostics. |
payloadOptimization | false | Enables biometric payload-size optimization. |
Handle session events
| Prop | Signature | Called when |
|---|---|---|
onFaceCaptureSuccess | (result: MBCaptureSessionResult) => void | The capture finished. See Capture results. |
onFaceCaptureFailed | (message: string) => void | The capture could not be completed. |
onFaceCaptureStarted | () => void | Frame collection started after the countdown. |
Show V3 feedback
V2 and V3 call onFaceBoundingBoxValidating while the user positions their face. With V3, the fourth argument reports the lighting status:
import {
FaceDistance,
FacePosition,
MBImageQualityStatus,
type FacePose,
} from "@mobaibio/mobai-biometric";
function feedbackText(
poses: FacePose[] | null,
distance: FaceDistance | null,
positions: FacePosition[] | null,
lighting: MBImageQualityStatus | null,
isValid: boolean
): string {
if (isValid) return "Hold still";
if (positions?.[0] === FacePosition.not_found) return "Face not found";
if (distance === FaceDistance.too_close) return "Move farther away";
if (distance === FaceDistance.too_far_away) return "Move closer";
if (positions?.length) return "Center your face";
if (poses?.length) return "Look straight at the camera";
if (lighting === MBImageQualityStatus.INSUFFICIENT_LIGHT) return "Move to a brighter area";
if (lighting === MBImageQualityStatus.UNEVEN_LIGHTING) return "Use more even lighting";
if (lighting === MBImageQualityStatus.CHECKING) return "Checking the light";
return "";
}
Check geometry before lighting so the user receives one clear instruction at a time. See Capture constraints and image quality for the status values.
Show progress and countdown
| Prop | Signature | Purpose |
|---|---|---|
onFaceCaptureCountDown | (downCounter: string) => void | Remaining countdown seconds before frame collection starts. |
onFaceCaptureProgress | (captureProgress: number) => void | Capture progress from 0 to 1. |
If the face becomes invalid during the countdown or capture, the SDK starts again from validation.