React Advanced SDK
The React Advanced SDK is in early release.
The Berbix React Advanced SDK allows your developers to compose a Berbix ID verification flow using your own UI components. This is an alternative to our React SDK, which is a one-line solution to integrate Berbix ID verification).
Does your integration require custom UI?
If not, and you just need a drop-in ID verification flow, you may be better served by our standard React SDK. The React Advanced SDK enables use cases, such as custom UI or deeper integration into your app, that cannot be covered by the React SDK.
Getting started
This documentation assumes you are familiar with the Berbix API-Only verification flow. If you have not yet reviewed our API-Only Integration Guide, please do so now.
The React Advanced SDK can be found and installed from NPM as @berbix/react-advanced-sdk
.
Your app needs to be wrapped in a CameraProvider
to provide the appropriate context to the SDK's other components.
import { CameraProvider } from "@berbix/react-advanced-sdk";
export default function App({ children }) {
return (
<html>
<head>
<meta />
</head>
<body>
<CameraProvider>{children}</CameraProvider>
</body>
</html>
);
}
Learn more about CameraProvider
in its API docs.
Showing the stream from the camera
To render the output from the device's camera, use the CameraStream
component. This component is essentially a managed <video>
element; it takes care of permissions and selection of device cameras, as well as setting up and running real-time shape detection on the camera stream.
It also provides various callbacks that developers can use to detect or respond to various events. You can learn more about this in the CameraStream
API docs.
import { CameraStream } from "@berbix/react-advanced-sdk";
function MyPage() {
return (
<div>
<CameraStream
fit="cover"
onStreamStart={() => console.log("Stream started")}
onStreamEnd={() => console.log("Stream ended")}
/>
</div>
);
}
Laying out the camera stream
The pixel dimensions of the rendered <CameraStream>
element depend on the resolution of the device's camera. Often, this is much larger than the viewport size, leading to scroll bars on the page if not sized correctly. As such, we recommend developers explicitly set the size of the element:
// Size the element to fully cover its parent container
style = { width: "100%", height: "100%" };
// Size the element to fully cover the viewport
style = { width: "100vw", height: "100vw" };
// Set a fixed size on the element
style = { width: "100px", height: "100px" };
<CameraStream style={style} />;
The CameraStream
component uses the object-fit
CSS property (aliased in the component as the fit
prop) to determine how to crop or scale the video stream to fit the dimensions of the element. By default, fit
is set to cover
, meaning that the video stream will be cropped to ensure that it fully covers the element. Below is an overview of how each fit
value behaves:
fit value | No cropping | No video bars | Preserve aspect ratio |
---|---|---|---|
cover | β | β | |
contain | β | β | |
fill | β | β |
The MDN docs on object-fit
has demos of these different values. You can read the docs here.
Adding shape detection
The CameraStream
component has the built-in ability to do real-time shape detection. You can do this as follows:
<CameraStream
shapeDetector="barcode"
shapeDetectorProps={{
active: true,
onDetect: () => console.log("Shape detected"),
}}
/>
You can read more about the various options for the shape detector in the shapeDetectorProps
section of the docs.
Controlling the camera output
We provide a useCamera
hook that gives you functions to control the CameraStream
component. You can read about the hook and its functions here.
Capturing camera frames
There are two ways to capture camera frames: either through the capture()
function in the useCamera
hook, or using shapeDetectorProps.autoCapture
. The former needs to be imperatively called; the latter will automatically trigger a capture if a shape is successfully detected.
In either case, it will fire the onCapture
callback in the CameraStream
component, passing in a Blob
of the captured image from the stream. You can add a handler to handle this:
const [active, setActive] = useState(true);
<CameraStream
onCapture={(blob, shapes) => {
setActive(false);
// Do some handling of the blob, e.g. send it to an API.
}}
shapeDetector="barcode"
shapeDetectorProps={{
active,
autoCapture: true,
}}
/>;
Components
CameraProvider
CameraProvider
This component performs the setup necessary for the camera stream to function; internally, it uses React context. It needs to be the parent of any CameraStream
elements and useCamera
calls, and there should only ever be a single CameraProvider
on a page.
We recommend that you put CameraProvider
as close to the root component as possible.
Examples
import { CameraProvider } from "@berbix/react-advanced-sdk";
function MyAppShell({ children }) {
return (
<>
<Head>
<meta name="viewport" content="initial-scale=1, width=device-width" />
</Head>
<CameraProvider>{children}</CameraProvider>
</>
);
}
CameraStream
CameraStream
This component renders a live stream from the device's camera. It is internally implemented as a <video>
element, and the CameraStream
component will pass any standard React HTML props (like children
, style
, className
, width
, height
etc.) to that element. As such, you have complete control over how it is laid out and styled in the DOM, as well as direct access to the underlying <video>
element via ref
, if necessary.
The size of the <video>
element in the page layout varies depending on the quality of the user's camera, but it may be up to 2048px
on either side. As such, any styling or layout should accommodate that possibility (e.g. by setting absolute widths on the component via width
or style
).
Note that the stream will start as soon as the component and camera are initialized.
Props
Name | Type | Default | Description |
---|---|---|---|
resolution | "normal" | "high" | "higher" | "normal" | Specify the resolution of the video stream from the camera. normal corresponds to approximately 720p resolution; high corresponds to approximately 2K resolution; higher corresponds to approximately 1440p resolution.Warning: increasing the resolution of the video stream may decrease how often the shape detection callbacks are called, due to the shape detectors having to process far larger image payloads. |
fit | "cover" | "contain" | "fill" | "none" | "cover" | Specify how to fit the camera stream into the <video> element. See the MDN docs on CSS object-fit (which this prop aliases) to see how these values differ in behavior. |
direction | "user" | "environment" | "environment" | Specify the direction of the camera to use. "user" is the front-facing camera on mobile devices, appropriate for capturing selfies. "environment" is the back-facing camera, appropriate for capturing IDs. |
onUnsupportedEnvironment | (message: string) => void | Callback fired when the browser or browsing environment does not support camera streaming or capture. This is typical in legacy browsers or some embedded web views in native mobile applications (e.g. WeChat, Instagram, etc.). The callback function is passed a human-readable error message. This is a terminal callback, so the component will no longer fire any callbacks after this. | |
onCameraUnavailable | (message: string) => void | Callback fired when no camera is available on the device, or if the available camera does not have the quality required for ID verification. The callback function is passed a human-readable error message. This is a terminal callback, so the component will no longer fire any callbacks after this. | |
onStreamDeny | (message: string) => void | Callback fired when the user denies access to the device's camera resource, or if the system automatically denies access to the resource. This is a terminal callback, so the component will no longer fire any callbacks after this. | |
onStreamFail | (message: string) => void | Callback fired when a hardware issue prevents the camera or camera stream from being accessed. This is a terminal callback, so the component will no longer fire any callbacks after this. | |
onStreamStart | (void) => void | Callback fired when the stream from the camera is started. This is typically called only once, when the component is mounted. For example, calling the resume() function in the hook will not fire this callback. | |
onStreamStop | (void) => void | Callback fired when the stream from the camera is stopped. This is typically called only once, when the component is unmounted. For example, calling the pause() function in the hook will not fire this callback. | |
onCapture | (blob: Blob, shapes?: ShapePayload[]) => void | Callback fired when a frame is successfully captured from the camera stream. This is caused either by a user action (e.g. a button press that calls the capture() method) or an auto-capture from the shape detector. The callback function is passed a Blob , which you can use to render into an <img> or post-process as necessary.If the capture was initiated automatically by the shape detector, it will also be passed a ShapePayload , which contains data about the detected shape. | |
shapeDetector | "barcode" | "selfie" | "id" | Set the type of shape detector to use on the camera stream. If left undefined , no shape detection will be run. | |
shapeDetectorProps | Defined below | {} |
shapeDetectorProps
props
shapeDetectorProps
propsName | Type | Default | Description |
---|---|---|---|
active | boolean | false | If true , the shape detector will run. Note that while active is true , the onDetect callback will continue to be fired. |
autoCapture | boolean | false | If true and active is also set to true , the shape detector will automatically fire the onCapture callback in the CameraStream component when a shape is detected. |
onDetect | (shapes?: ShapePayload[]) => void | Callback fired while the shape detector is active. This will continuously fire at roughly 500ms intervals. If a shape is detected, the callback will be passed an array of shape payloads that contain information about the detected shape(s). If no shape was detected, this value will be undefined .The DOMRect that is in ShapePayload has been transformed to overlay directly on the <video> element. |
ShapePayload
object
ShapePayload
objectWhen shapeDetector
is set to "barcode"
, the payload is an object with the following properties:
Name | Type | Default | Description |
---|---|---|---|
boundingBox | DOMRect | The bounds of the detected barcode. | |
format | "pdf417" | The format of the barcode. At the moment, the SDK only supports the detection of PDF417 barcodes. | |
rawValue | string | The string that is encoded in the barcode. |
When shapeDetector
is set to "id"
, the payload is an object with the following properties:
Name | Type | Default | Description |
---|---|---|---|
boundingBox | DOMRect | The bounds of the detected ID. | |
type | "card" | The type of the ID. The SDK may support different ID types in the future, but at the moment, it's statically set to "card" . |
When shapeDetector
is set to "selfie"
, the payload is an object with the following properties:
Name | Type | Default | Description |
---|---|---|---|
boundingBox | DOMRect | The bounds of the detected face. | |
type | "left" | "right" | "direct" | The direction that the selfie (read: face) is facing. |
Examples
Basic example
The following example implements a basic stream from the camera, with a simple console output when a
camera capture is invoked.
import { CameraStream } from "@berbix/react-advanced-sdk";
function CameraStreamScreen() {
return <CameraStream onCapture={(blob, shapes) => console.log("Captured!", blob, shapes)} />;
}
Advanced example
The next example implements a slightly more advanced live camera screen with shape detection.
It uses the payload from the onDetect
callback to appropriately position and size
a barcode overlay.
import { CameraStream } from "@berbix/react-advanced-sdk";
function BarcodeCaptureScreen() {
const [barcodeBbox, setBarcodeBbox] = useState<BoundingBox | null>(null);
const [detectorActive, setDetectorActive] = useState(true);
return (
<>
<CameraStream
onCapture={(blob, barcode) => {
setDetectorActive(false);
// Call out to an API
}}
shapeDetector={ShapeDetector.Barcode}
shapeDetectorProps={{
active: detectorActive,
autoCapture: true,
onDetect: (shapes) => {
if (shapes.length) setBarcodeBbox(shapes[0].boundingBox);
},
}}
/>
{/* Highlight an identified barcode using a red rect outline */}
<div
style={{
position: "absolute",
top: barcodeBbox.top,
left: barcodeBbox.left,
width: barcodeBbox.width,
height: barcodeBbox.height,
border: "1px solid red",
}}
>
</div>
</>
);
}
useCamera
hook
useCamera
hookThis React hook provides functions to fire callbacks on the camera components.
Props
Name | Type | Description |
---|---|---|
capture | () => void | Take a photo using the active camera. This will fire the onCapture callback in the CameraStream component. |
pause | () => void | Pause the camera stream from a playing state. If the stream is already paused, this will do nothing. |
resume | () => void | Resume the camera stream from a paused state. If the stream is already playing, this will do nothing. |
Examples
const { capture, pause, stopShapeDetector } = useCamera();
function MyComponent() {
return (
<>
<button onClick={() => pause()}>Pause camera</button>
<button onClick={() => capture()}>Take a picture</button>
</>
);
}
References
Updated 11 months ago