Image Capturer - React Native
This guide provides instructions on capturing images of participants from a video stream.
Use it in Video KYC, for example to capture an image of a user holding up their ID for verification.
This page uses the following asynchronous methods. Refer to their API reference for the errors each Promise may reject with, and handle these rejections appropriately based on your use case.
captureImage()
- By using the
captureImage()function of theuseParticipanthook, you can capture image of a local participant from their video stream. - You have the option to specify the desired height and width in the
captureImage()function; however, these parameters are optional. They set the largest size of the image: the image keeps its aspect ratio and is never enlarged. If not provided, the image has the size of the local participant's camera. - The
captureImage()function returns the image in the form of abase64string. It is a JPEG image, without adata:prefix. - The camera must be on. If it is off,
captureImage()rejects with3062ERROR_WEBCAM_NOT_ENABLED. If the capture fails, it rejects with3069ERROR_CAPTURE_IMAGE_FAILED, which is also reported ononError.
import { useRoom, useParticipant } from '@videosdk.live/react-native-sdk';
const {localParticipant} = useRoom()
const { webcamStream, webcamOn, captureImage } = useParticipant(localParticipant.id);
async function imageCapture() {
if (webcamOn && webcamStream) {
let base64;
try {
base64 = await captureImage({height:400,width:400}); // captureImage will return base64 string
} catch (err) {
console.error("captureImage failed:", err);
return;
}
console.log("base64",base64);
} else {
console.error("Camera must be on to capture an image");
}
}
Capture with flash
- Pass
flash: "ON"(Constants.CaptureFlash.ON) to light the scene before the image is captured. The SDK uses the camera's torch, or the screen on a front camera. This adds about half a second. - The default is
"OFF". - Flash works for the local participant only. For a remote participant, the call rejects with
3069ERROR_CAPTURE_IMAGE_FAILED. - To decide up front how a front camera is lit, call
setScreenFlash(true). It turns on the SDK's built-in white screen overlay for front-camera captures. CallsetScreenFlash(null)to clear it. ImportsetScreenFlash()from@videosdk.live/react-native-sdk; it is not returned byuseParticipant().
import { Constants, setScreenFlash } from "@videosdk.live/react-native-sdk";
// Once, for example when the camera screen opens
await setScreenFlash(true);
const base64 = await captureImage({
height: 400,
width: 400,
flash: Constants.CaptureFlash.ON,
});
// When the camera screen closes
await setScreenFlash(null);
You can only capture an image of the local participant. If you want to capture an image of a remote participant, check the documentation below.
How to capture image of remote participant ?
-
This feature uses VideoSDK's temporary file storage system and the underlying pubsub mechanism.
-
Here's a breakdown of the steps, using the names Participant A and Participant B for clarity:
Step 1 : Initiate Image Capture Request
- In this step, you have to first send a request to Participant B, whose image you want to capture, using pubsub.
- In order to do that, you have to create a pubsub topic called
IMAGE_CAPTUREin theParticipantViewComponent. - Here, you will be using the
sendOnlyproperty of thepublish()method. Therefore, the request will be sent to that participant only.
import {usePubSub} from '@videosdk.live/react-native-sdk';
import {
TouchableOpacity,
Text
} from 'react-native';
function ParticipantView({ participantId }) {
// create pubsub topic to send Request
const { publish } = usePubSub('IMAGE_CAPTURE');
// send Request to participant
async function sendRequest() {
// Pass the participantId of the participant whose image you want to capture
// Here, it will be Participant B's id, as you want to capture the image of Participant B
try {
await publish("Sending request to capture image", { persist: false, sendOnly: [participantId] });
} catch (error) {
console.log("Error while publishing:", error);
}
};
return <>
{/* other components */}
<TouchableOpacity style={{ width: 80, height : 45, backgroundColor: 'red', position: 'absolute', top: 10 }} onPress={() => {
sendRequest()
}}>
<Text style={{ fontSize: 15, color: 'white', left:10 }}>
Capture Image
</Text>
</TouchableOpacity>
</>;
}
Step 2 : Capture and Upload File
- To capture image from remote participant [Participant B], we've created the
CaptureImageListenercomponent. When a participant receives an image capture request, this component uses thecaptureImagefunction ofuseParticipanthook to capture the image.
import {
useFile,
usePubSub,
useParticipant
} from '@videosdk.live/react-native-sdk';
const CaptureImageListner = ({ localParticipantId }) => {
const { captureImage } = useParticipant(localParticipantId);
// subscribe to receive request
usePubSub('IMAGE_CAPTURE', {
onMessageReceived: (message) => {
_handleOnImageCaptureMessageReceived(message);
},
});
const _handleOnImageCaptureMessageReceived = (message) => {
try {
if (message.senderId !== localParticipantId) {
// capture and store image when message received
captureAndStoreImage({ senderId: message.senderId });
}
} catch (err) {
console.log("error on image capture", err);
}
};
async function captureAndStoreImage({ senderId }) {
// capture image
let base64Data;
try {
base64Data = await captureImage({height:400,width:400});
} catch (err) {
console.error("captureImage failed:", err);
return;
}
console.log('base64Data',base64Data);
}
return <></>;
};
export default CaptureImageListner;
- The captured image is then stored in the VideoSDK's temporary file storage system using the
uploadBase64File()function of theuseFilehook. This operation returns a uniquefileUrlof the stored image.
const CaptureImageListner = ({ localParticipantId }) => {
const { uploadBase64File } = useFile();
async function captureAndStoreImage({ senderId }) {
// capture image
let base64Data;
try {
base64Data = await captureImage({height:400,width:400});
} catch (err) {
console.error("captureImage failed:", err);
return;
}
const token = "<YOUR-TOKEN>";
const fileName = "myCapture.jpeg"; // specify a name for image file with extension
// upload image to videosdk storage system
let fileUrl;
try {
fileUrl = await uploadBase64File({base64Data,token,fileName});
} catch (err) {
console.error("uploadBase64File failed:", err);
return;
}
console.log('fileUrl',fileUrl)
}
//...
}
- Next, the
fileUrlis sent back to the participant who initiated the request using theIMAGE_TRANSFERtopic.
const CaptureImageListner = ({ localParticipantId }) => {
//...
// publish image Transfer
const { publish: imageTransferPublish } = usePubSub('IMAGE_TRANSFER');
async function captureAndStoreImage({ senderId }) {
//...
let fileUrl;
try {
fileUrl = await uploadBase64File({base64Data,token,fileName});
} catch (err) {
console.error("uploadBase64File failed:", err);
return;
}
try {
await imageTransferPublish(fileUrl, { persist: false , sendOnly: [senderId] });
} catch (error) {
console.log("Error while publishing:", error);
}
}
//...
}
- Then the
CaptureImageListenercomponent has to be rendered within theRoomViewcomponent.
import CaptureImageListner from './captureImageListner';
import {useRoom} from '@videosdk.live/react-native-sdk';
import {View} from 'react-native';
function RoomView() {
//...
// Get `localParticipant` from useRoom Hook
const {localParticipant } = useRoom({});
return (
<View>
{/* other components */}
<CaptureImageListner localParticipantId={localParticipant?.id} />
</View>
);
}
Step 3 : Fetch and Display Image
-
To display a captured image, the
ShowImagecomponent is used. Here's how it works: -
Within
ShowImage, you need to subscribe to theIMAGE_TRANSFERtopic, receiving thefileUrlassociated with the captured image. Then use thefetchBase64File()function from theuseFilehook to retrieve the file inbase64format from VideoSDK's temporary storage.
import { useState } from 'react';
import {
useRoom,
useFile,
usePubSub,
} from '@videosdk.live/react-native-sdk';
function ShowImage() {
const mRoom = useRoom();
const { fetchBase64File } = useFile();
const topicTransfer = "IMAGE_TRANSFER";
const [bitMapImg, setbitMapImg] = useState(null);
usePubSub(topicTransfer, {
onMessageReceived: (message) => {
if (message.senderId !== mRoom.localParticipant.id) {
fetchFile({ url: message.message }); // pass fileUrl to fetch the file
}
}
});
async function fetchFile({ url }) {
const token = "<YOUR-TOKEN>";
let base64;
try {
base64 = await fetchBase64File({ url, token });
} catch (err) {
console.error("fetchBase64File failed:", err);
return;
}
console.log("base64",base64); // here is your image in a form of base64
setbitMapImg(base64);
}
}
- With the
base64data in hand, you can now display the image in a modal. The modal is part of theRoomViewcomponent.
import {
Image,
Modal,
Pressable,
Text,
View
} from 'react-native';
function ShowImage() {
//...
return <>
{bitMapImg ? (
<View>
<Modal animationType={"slide"} transparent={false} >
<View style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center'
}}>
<View>
<Image
style={{ height: 400, width: 300, objectFit: "contain" }}
source={{ uri: `data:image/jpeg;base64,${bitMapImg}` }}
/>
<Pressable
onPress={() => setbitMapImg(null)}>
<Text style={{color:"black"}}>Close Dialog</Text>
</Pressable>
</View>
</View>
</Modal>
</View>
) : null}
</>;
}
function RoomView() {
// ...
return (
<View>
{/* other components */}
<CaptureImageListner localParticipantId={localParticipant?.id} />
<ShowImage />
</View>
);
}
The file stored in the VideoSDK's temporary file storage system will be automatically deleted once the current room comes to an end.
API Reference
The API references for all the methods utilized in this guide are provided below.
Got a Question? Ask us on discord

