Image Capturer - Flutter
This guide provides instructions on capturing images of participants from a video stream.
This capability proves particularly valuable in Video KYC scenarios, enabling the capture of images where users can hold up their identity for verification.
captureImage()
- By using the
captureImage()method of theParticipantclass, 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()method; however, these parameters are optional. If not provided, the VideoSDK will automatically use the dimensions of the local participant's webcamStream. - The
captureImage()function returns the image in the form of abase64string.
void imageCapture() async {
// captureImage will return base64 string
String? base64 = await room.localParticipant.captureImage(
height: 400,
width: 400,
);
print("Base64 Image captured $base64Image");
}
How to capture image of a remote participant ?
-
Before proceeding, it's crucial to understand VideoSDK's temporary file storage system and the underlying pubsub mechanism.
-
Here's a break down 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 publish a message. Here,
IMAGE_CAPTUREpubsub topic is used. - Also, you will be using the
sendOnlyproperty of thePubSubPublishOptionsclass. Therefore, the request will be sent to that participant only.
class MeetingScreen extends StatefulWidget {
const MeetingScreen({Key? key}) : super(key: key);
@override
_MeetingScreenState createState() => _MeetingScreenState();
}
class _MeetingScreenState extends State<MeetingScreen> {
late Room _room;
// send Request to participant
void sendRequest(String participantId) {
// 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 the image of Participant B
if (participantId != meeting.localParticipant.id) {
var publishOptions = PubSubPublishOptions(
persist: false,
sendOnly: [participantId],
);
// create pubsub topic to send Request
_room.pubSub.publish(
"IMAGE_CAPTURE",
"Sending request to capture image",
publishOptions,
);
}
}
@override
Widget build(BuildContext context) {
return Column(children: [
ElevatedButton(
onPressed: () {
sendRequest("enter the participant ID to send image capture request");
},
child: Text("Capture Image"),
),
]);
}
}
Step 2 : Capture and Upload File
- To capture an image from a remote participant [Participant B] . you need to subscribe to a topic called
IMAGE_CAPTURE. When you receive an image capture request, you will capture the image using thecaptureImage()method of theParticipantclass.
class MeetingScreen extends StatefulWidget {
const MeetingScreen({Key? key}) : super(key: key);
@override
_MeetingScreenState createState() => _MeetingScreenState();
}
class _MeetingScreenState extends State<MeetingScreen> {
late Room _room;
void messageHandler(PubSubMessage message) {
if (message.senderId != _room.localParticipant.id) {
captureAndStoreImage(message.senderId);
}
}
// capture and store image when message received
void captureAndStoreImage(String senderId) async {
// capture image
String? base64Data = await _room.localParticipant.captureImage(
height: 400,
width: 400,
);
print("base64Data : $base64Data");
}
// subscribe to receive request
void registerMeetingEvents(Room _room) {
_room.on(
Events.roomJoined,
() async {
_room.pubSub.subscribe("IMAGE_CAPTURE", messageHandler);
},
);
}
}
- The captured image is then stored in VideoSDK's temporary file storage system using the
uploadBase64File()function of theRoomclass. This operation returns a uniquefileUrlof the stored image.
void captureAndStoreImage(String senderId) async {
// capture image
String? base64Data = await meeting.localParticipant.captureImage(
height: 400,
width: 400,
);
String token = "<VIDEOSDK_TOKEN>";
String fileName = "myCapture.jpeg"; // specify a name for image file with extension
// upload image to videosdk storage system
String? url = await meeting.uploadBase64File(
base64Data: base64Data!,
token: token,
fileName: fileName,
);
print("Image URL: $url");
}
- Next, the
fileUrlis sent back to the participant who initiated the request using theIMAGE_TRANSFERtopic.
void captureAndStoreImage(String senderId) async {
String? base64Data = await meeting.localParticipant.captureImage(
height: 400,
width: 400,
);
String token = "<VIDEOSDK_TOKEN>";
String fileName = "myCapture.jpeg";
String? url = await meeting.uploadBase64File(
base64Data: base64Data!,
token: token,
fileName: fileName,
);
// publish image Transfer
PubSubPublishOptions options = PubSubPublishOptions(
persist: false,
sendOnly: [senderId],
);
meeting.pubSub.publish(
"IMAGE_TRANSFER",
url!,
options,
);
}
Step 3 : Fetch and Display Image
-
To display a captured image, the
showCapturedImage()method is used. Here's how it works: -
Within the
showCapturedImage()method, subscribe to theIMAGE_TRANSFERtopic to receive thefileUrlassociated with the captured image. -
Once the
fileUrlis obtained, use thefetchBase64File()method from theRoomclass to retrieve the file inbase64format from VideoSDK's temporary storage.
void showCapturedImage() async {
PubSubMessages messages = await meeting.pubSub.subscribe(
"IMAGE_TRANSFER",
(PubSubMessage message) async {
if (message.senderId != meeting.localParticipant.id) {
String url = message.message;
String token = "<VIDEOSDK_TOKEN>";
String? base64 = await meeting.fetchBase64File(
url: url, // pass fileUrl to fetch the file
token: token,
);
print("base64 $base64"); // here is your image in the form of base64
}
},
);
}
- With the
base64data in hand. we can convert it intoUint8Listusing Dart'sbase64Decode()method. ThisUint8Listcan then be used to render the image on the screen usingImage.memory()widget.
class MeetingScreen extends StatefulWidget {
const MeetingScreen({Key? key}) : super(key: key);
@override
_MeetingScreenState createState() => _MeetingScreenState();
}
class _MeetingScreenState extends State<MeetingScreen> {
Uint8List? _capturedImage;
void showCapturedImage() async {
PubSubMessages messages = await meeting.pubSub.subscribe(
"IMAGE_TRANSFER",
(PubSubMessage message) async {
if (message.senderId != meeting.localParticipant.id) {
String url = message.message;
String token = "<VIDEOSDK_TOKEN>";
String? base64 = await meeting.fetchBase64File(
url: url, // pass fileUrl to fetch the file
token: token,
);
// set state to set _capturedImage to the obtain base64 string
setState(() {
_capturedImage = base64Decode(base64!);
});
}
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Captured Image")),
body: Center(
// Display the image
child: _capturedImage != null
? Image.memory(_capturedImage!)
: const Text("Waiting for image..."),
),
);
}
}
The file stored in the system will be automatically deleted once the current room/meeting 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

