Skip to main content
Version: 2.x.x

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 the Participant class, 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 a base64 string.
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 ?​

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_CAPTURE pubsub topic is used.
  • Also, you will be using the sendOnly property of the PubSubPublishOptions class. 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 the captureImage() method of the Participant class.
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 the Room class. This operation returns a unique fileUrl of 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 fileUrl is sent back to the participant who initiated the request using the IMAGE_TRANSFER topic.
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 the IMAGE_TRANSFER topic to receive the fileUrl associated with the captured image.

  • Once the fileUrl is obtained, use the fetchBase64File() method from the Room class to retrieve the file in base64 format 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 base64 data in hand. we can convert it into Uint8List using Dart's base64Decode() method. This Uint8List can then be used to render the image on the screen using Image.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..."),
),
);
}
}
note

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