https://unpkg.com/@tsocial/[email protected]/examples/index.html
<script src="https://unpkg.com/@tsocial/tvweb-sdk@<VERSION>/build/tvweb-sdk.standalone.min.js"></script>
npm install @tsocial/tvweb-core @tsocial/tvweb-ui
# or
yarn add @tsocial/tvweb-core @tsocial/tvweb-ui
Or the library not React
npm install @tsocial/tvweb-sdk
# or
yarn add @tsocial/tvweb-sdk
const tv = new TVWebSDK.SDK({
container: document.getElementById("container"),
lang: "vi",
assetRoot: "https://unpkg.com/@tsocial/tvweb-sdk@<VERSION>/assets",
});
// Main functions:
tv.readIDCard({
frontCamera: false,
title: "Mặt trước CMND/CCCD",
titleIcon: "id_card_front.svg",
description: "Vui lòng đặt CMND mặt trước vào trong khung",
onSuccess: handleOnSuccess,
onError: handleOnError,
});
tv.livenessDetection({
mode: TVWebSDK.Constants.Mode.ACTIVE,
apiCheck: false,
// accessKey: "YOUR ACCESS KEY",
// secretKey: "YOUR SECRET KEY",
// apiUrl: "YOUR API ENDPOINT",
onLivenessDetectionDone: handleLivenessDetectionDone,
onError: (e) => alert(e.code),
});
tv.checkCamera({ frontCamera: true }).then((error) => console.log(error));
import { LivenessDetection, ReadIDCard } from "@tsocial/tvweb-ui";
import { Constants, SettingsContext } from '@tsocial/tvweb-core';
import TrustVisionAPI from '@tsocial/trustvision-sdk';
// get user agent metadata
const userAgentMetadata = UserAgentUtils.getUAMetadata();
// init apiClient for api call
// if you're calling api by yourself, ignore this apiClient
const apiClient = new TrustVisionAPI(accessKey, secretKey, apiUrl, { httpHeaders: userAgentMetadata });
// Liveness Detection component
<SettingsContext.SDKSettingsProvider
value={{
lang: "vi",
assetRoot: "https://unpkg.com/@tsocial/tvweb-sdk@latest/assets",
apiClient,
}}
>
<LivenessDetection
mode={Constants.Mode.ACTIVE}
onLivenessDetectionDone={(output) => console.log(output)}
onError={(e) => console.log(e)}
captureFrameData
onProcessing={() => console.log('on processing')}
/>
</SettingsContext.SDKSettingsProvider>
// Read ID Card component
<SettingsContext.SDKSettingsProvider
value={{
lang: "vi",
assetRoot: "https://unpkg.com/@tsocial/tvweb-sdk@latest/assets",
apiClient,
}}
>
<ReadIDCard
cardSide={Constants.IDCardSide.FRONT}
enableRecording
title="Mặt trước CMND/CCCD"
description="Vui lòng đặt CMND mặt trước vào trong khung"
frontCamera={false}
onError={(e) => console.log(e)}
onSuccess={(output) => console.log(output)}
/>
</SettingsContext.SDKSettingsProvider>
// config
// in angular.json, add this to script
"scripts": [
...
"node_modules/@tsocial/tvweb-sdk/build/tvweb-sdk.standalone.min.js"
...
]
// usage
declare var TVWebSDK: any;
// the rest example code the same to VanillaJS above
import * as TVWebSDK from "@tsocial/tvweb-sdk";
// the rest example code the same to VanillaJS above
This function extracts ID card info.
Params: a single object with these properties
Required | Description | Type | Default | |
---|---|---|---|---|
apiCheck | no | If true, sdk will call APIs itself (accessKey, secretKey, apiUrl are needed). | boolean | false |
accessKey, secretKey, apiUrl | no | Keys to make api calls | string | "" |
frontCamera | no | To select front camera or back camera | boolean | true |
enableRecording | no | If enabled, recordedVideos (in onSuccess result) will contain at least 1 video | boolean | false |
cardSide | no | Side of ID card | string (one of [TVWebSDK.Constants.IDCardSide.FRONT , TVWebSDK.Constants.IDCardSide.BACK ] | TVWebSDK.Constants.IDCardSide.FRONT |
frontCardId | no* | The id of the front card image returns from onSuccess. This is required when reading back side of ID card (apiCheck is true) | string | "" |
title | no | Title to display | string | "" |
description | no | Description to display | string | "" |
onSuccess | no | Callback when the process finishes successfully. This object will be returned { image, recordedVideos, apiResult } in which image is the image blob (always returned), recordedVideos is an array of recorded videos ([] or [{ id, frames: [image's base64,...]},...] if enableRecording is true) and apiResult ({ sanityResult, tamperingInfo, cardInfo }) will be returned if apiCheck is true. - cardInfo: kindly check response.data here - tamperingInfo: kindly check response.data here - sanityResult: kindly check response.data here | function | Empty function |
onError | no | Callback when errors happen. An error object will be returned. | function | Empty function |
Sample code:
tv.readIDCard({
apiCheck: apiCheck,
accessKey: "YOUR ACCESS KEY",
secretKey: "YOUR SECRET KEY",
apiUrl: "YOUR API ENDPOINT",
frontCamera: false,
enableRecording: true,
cardSide: TVWebSDK.Constants.IDCardSide.FRONT,
frontCardId: inputFrontIdEl.value,
title:
cardSide === TVWebSDK.Constants.IDCardSide.FRONT
? "Mặt trước CMND/CCCD"
: "Mặt sau CMND/CCCD",
description:
cardSide === TVWebSDK.Constants.IDCardSide.FRONT
? "Căn mặt trước CMND/CCCD vào khung"
: "Căn mặt sau CMND/CCCD vào khung",
onSuccess: handleReadIDCardResult,
onError: (e) => {
resultExtractIdInfoEl.appendChild(
document.createTextNode(`${JSON.stringify(e, null, 2)}`)
);
tv.destroyView();
readIdCardLoadingEl.style.display = "none";
},
});
function handleReadIDCardResult({ image, recordedVideos, apiResult }) {
const apiCheck = selectApiCheckEl.value === "true";
const imgEl = document.createElement("img");
imgEl.width = "200";
imgEl.src = URL.createObjectURL(image);
resultExtractIdInfoEl.appendChild(imgEl);
resultExtractIdInfoEl.appendChild(document.createElement("br"));
resultExtractIdInfoEl.appendChild(
document.createTextNode(`Recorded videos: ${recordedVideos.length}\n`)
);
if (apiCheck) {
resultExtractIdInfoEl.appendChild(document.createTextNode("API Result:\n"));
resultExtractIdInfoEl.appendChild(
document.createTextNode(`${JSON.stringify(apiResult, null, 2)}`)
);
const cardSide = selectCardSideEl.value;
if (cardSide === TVWebSDK.Constants.IDCardSide.FRONT) {
const frontCardId = apiResult.cardInfo.image1.id;
inputFrontIdEl.value = frontCardId;
}
}
tv.destroyView();
readIdCardLoadingEl.style.display = "none";
}
This function starts liveness detection flow.
Params: a single object with these properties
Required | Description | Type | Default | |
---|---|---|---|---|
apiCheck | no | If true , sdk will call APIs itself (accessKey, secretKey, apiUrl are needed). | boolean | false |
mode | yes | Mode to operate | string (one of [TVWebSDK.livenessDetectionMode.ACTIVE, TVWebSDK.livenessDetectionMode.PASSIVE] ) | |
accessKey, secretKey, apiUrl | no | Keys to make api calls | string | "" |
onLivenessDetectionDone | yes | Callback when liveness detection flow is done. This object { frontalFaces, apiCheckPassed, steps, capturedFrames } will be returned. - steps: all face gestures captured. - frontalFaces: random frontal faces captured in the background. - apiCheckPassed: whether all liveness checks passed, appears only when apiCheck is enabled. - capturedFrames: frames list record liveness process, if captureFrameData not enabled, this returns an empty array. | function | |
onError | no | Callback when errors happen. An error object will be returned. | function | Empty function |
onProcessing | no | Available from v4.3.0. From v4.3.0, SDK will resize output images to 400x400 before return. So this is the callback when SDK start resize images. Use to close camera or show loading. The resize process complete on onLivenessDetectionDone .If apiCheck is enable, this callback also includes api call time. | function | Empty function |
captureFrameData | no | Available from v3.9.3. Whether to record the liveness process or not. | boolean | false |
customErrors | no | Available from v3.10.1. Custom the errors show on SDK. See example below. | object | null |
framesIntervalTime | no | Available from v4.0.2. Adjust frames capture per second in captureFrameData mode. Only capture 1 frame in framesIntervalTime . When set to 0, SDK will capture full potential of device can handle. | number (millisecond) | 180 |
livenessSettings | no | Available from v4.2.1. This settings come from TS server and depend on your accessKey and secretKey .When apiCheck enable, this setting will be automated get from TS server and bind to SDK. Anything pass to this props will overwrite settings come with apiCheck .When you call api by your self, use this api to get client settings, and pass response.data.settings.sdk_settings.active_liveness_settings to this props. | object | null |
Sample code:
tv.livenessDetection({
apiCheck: apiCheck,
mode: livenessDetectionMode,
accessKey: "YOUR ACCESS KEY",
secretKey: "YOUR SECRET KEY",
apiUrl: "YOUR API ENDPOINT",
onLivenessDetectionDone: handleLivenessDetectionDone,
onError: (e) => alert(e.code),
});
function handleLivenessDetectionDone(result) {
const { frontalFaces, apiCheckPassed, steps } = result;
const apiCheck = selectApiCheckEl.value === "true";
resultLivenessDetectionEl.innerHTML = "";
if (apiCheck === false) {
setTimeout(function () {
tv.destroyView();
resultLivenessDetectionEl.appendChild(
document.createTextNode("Random frontal faces detected: ")
);
frontalFaces.forEach((blob) => {
const imgEl = document.createElement("img");
imgEl.width = "200";
imgEl.style.marginRight = "5px";
imgEl.src = URL.createObjectURL(blob);
resultLivenessDetectionEl.appendChild(imgEl);
});
resultLivenessDetectionEl.appendChild(document.createElement("br"));
resultLivenessDetectionEl.appendChild(document.createElement("br"));
resultLivenessDetectionEl.appendChild(
document.createTextNode("Directional faces:")
);
steps.forEach((s) => {
const imgEl = document.createElement("img");
imgEl.width = "200";
imgEl.style.marginRight = "5px";
imgEl.src = URL.createObjectURL(s.image.blob);
resultLivenessDetectionEl.appendChild(imgEl);
});
}, 500);
} else {
tv.destroyView();
resultLivenessDetectionEl.appendChild(
document.createTextNode(`apiCheckPassed: ${apiCheckPassed}`)
);
}
}
Custom Errors:
tv.livenessDetection({
apiCheck: apiCheck,
mode: livenessDetectionMode,
accessKey: 'YOUR ACCESS KEY',
secretKey: 'YOUR SECRET KEY',
apiUrl: 'YOUR API ENDPOINT',
onLivenessDetectionDone: handleLivenessDetectionDone,
onError: e => alert(e.code),
customErrors={{
face_too_small: {
code: 'face_too_small',
msg: {
en: 'Face too small',
vi: 'Đưa camera lại gần',
},
},
face_too_large: {
code: 'face_too_large',
msg: {
en: 'Face too large',
vi: 'Đưa camera ra xa',
},
},
}}
})
List errors can custom:
no_face: {
code: 'no_face',
msg: {
en: 'Face not found',
vi: 'Không tìm thấy khuôn mặt',
},
},
partial_face: {
code: 'partial_face',
msg: {
en: 'Face out of the box',
vi: 'Không tìm thấy toàn bộ khuôn mặt',
},
},
multiple_faces: {
code: 'multiple_faces',
msg: {
en: 'Too many faces',
vi: 'Quá nhiều khuôn mặt',
},
},
face_too_small: {
code: 'face_too_small',
msg: {
en: 'Face too small',
vi: 'Khuôn mặt quá nhỏ',
},
},
face_too_large: {
code: 'face_too_large',
msg: {
en: 'Face too large',
vi: 'Khuôn mặt quá to',
},
},
face_out_of_box: {
code: 'face_out_of_box',
msg: {
en: 'Face is out of box',
vi: 'Khuôn mặt không nằm trọn vẹn trong khung ảnh',
},
},
Compare face from readIDCard result & livenessDetection result.
Params: a single object with these properties
Required | Description | Type | Default | |
---|---|---|---|---|
accessKey, secretKey, apiUrl | yes | Keys to make api calls | string | |
image1 | yes | The id of the front card image returns from onSuccess in readIDCard method. | string | |
image2 | yes | The id of the first image returns from onLivenessDetectionDone (verifyFaceLivenessResult) in livenessDetection method. | string | |
onSuccess | yes | Success callback | function | |
onError | yes | Error callback | function |
Sample code:
tv.compareFaces({
accessKey: "e576a662-a94a-4012-9d64-c6f6e81fb711",
secretKey: "6Z6jgTQSqkwRvpN2n4fzm9Wo3vDAFS2q",
apiUrl: "https://tv-staging.trustingsocial.com/api",
image1: "2383fdbe-70aa-470f-9469-96cac7f61ea1",
image2: "784e8cb3-eb58-497b-aaa9-c02be8b77cf7",
onSuccess: (rs) => console.log(rs),
onError: (e) => console.log(e),
});
Stop the camera immediately
Sample code:
tv.destroyView();
Check the ability to open the camera of the current device.
Params: a single object with these properties
Required | Description | Type | Default | |
---|---|---|---|---|
frontCamera | no | Whether to check the front camera or the back camera | boolean | true |
Return value: a Promise
whose fulfillment handler receives an error object when the camera can’t be opened properly or null
if no issues occur.
Sample code:
tv.checkCamera();
SDK works best on major browser (Chrome, Firefox, Safari):
IE | Edge | Firefox | Chrome | Safari | Opera |
---|---|---|---|---|---|
>11 | >79 | >36 | >53 | >11 | >40 |
iOS Safari | Facbook Web Browser in iOS | Facbook Web Browser in Android | Opera mini | Opera Mobile | Chrome for Android | Firefox for Android | UC Browser for Android |
---|---|---|---|---|---|---|---|
>11 | not supported | not supported | not supported | works, but there are some unexpected behaviors (browser ask to choose Front/Back camera) | >85 | >79 | not supported |
Please refer Browser compatibility on https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia for more information
To make Web SDK work on a WebView, the WebView implementer must supports getUserMedia API and handle camera permission requests correctly.
For Android WebView, the implementer also needs to set the setMediaPlaybackRequiresUserGesture config to false
. Otherwise, the camera video cannot be autoplay (the WebView requires a user gesture to play media).
For iOS WebView, there is a known issue which tracked here. You should take a look at that issue before you implement your WebView on iOS.
{
code: 'not_supported',
msg: {
en: 'Camera is not well-supported on this device/browser. Please try another one.',
vi: 'Camera không được hỗ trợ. Vui lòng thử trình duyệt hoặc thiết bị khác.',
},
},
{
code: 'camera_timeout',
msg: {
en: `Can't access camera. Please check camera permission, try again or try another browser/device`,
vi:
'Không thể truy cập camera trong thời gian cho phép. Vui lòng kiểm tra quyền truy cập camera, thử lại hoặc thử trên trình duyệt/thiết bị khác.',
},
},
{
code: 'no_permission',
msg: {
en: 'Please grant the permission to access the camera.',
vi: 'Vui lòng cấp quyền để truy cập camera.',
},
},
{
code: 'unable_to_load_model',
msg: {
en: `Unable to load model on this device/browser. Please try another one.`,
vi: 'Không thể load model. Vui lòng thử trình duyệt hoặc thiết bị khác.',
},
},
{
code: < DOMException > // refer: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#Exceptions
}