Skip to main content

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():

OptionDefaultPurpose
numberOfFrameToCollect3Number of frames sampled from the video interval.
videoCaptureDuration1000Video duration in milliseconds, clamped to 1000–3000.
timeBeforeAutomaticCapture1Countdown duration in seconds.
captureConstrainsMBCaptureConstraints.V1Selects the V1, V2, or V3 validation pipeline.
imageQualityLevelMBImageQualityLevel.LEVEL_3Selects V3 lighting strictness. It has no effect on V1 or V2.
sessionId—Key for the authenticated sessionMetadata and sessionVideoMetadata.
targetResolutionTargetResolution.HD_720Capture resolution: HD_720, HD_1080, or HD_4K. QHD is deprecated and falls back to HD_720.
previewScaleTypePreviewScaleType.fillfill covers the view and crops the preview; fit shows the full camera frame. Captured images are not affected.
isDebuggingfalseEnables SDK diagnostics.
payloadOptimizationfalseEnables biometric payload-size optimization.

Handle session events​

PropSignatureCalled when
onFaceCaptureSuccess(result: MBCaptureSessionResult) => voidThe capture finished. See Capture results.
onFaceCaptureFailed(message: string) => voidThe capture could not be completed.
onFaceCaptureStarted() => voidFrame 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​

PropSignaturePurpose
onFaceCaptureCountDown(downCounter: string) => voidRemaining countdown seconds before frame collection starts.
onFaceCaptureProgress(captureProgress: number) => voidCapture progress from 0 to 1.

If the face becomes invalid during the countdown or capture, the SDK starts again from validation.

Continue the integration​