UNPKG

@privateid/small-age-sdk-alpha

Version:
982 lines 51.9 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; /* eslint-disable default-param-last */ /* eslint-disable @typescript-eslint/ban-ts-comment */ import { detect } from 'detect-browser'; import { proxy } from 'comlink'; import { getIsSIMD, printLogs, getDebugType, setDefaultCameraDeviceId, getDefaultCameraDeviceId, iOS, multiframeLivenessAndAgePredict, prividDocumentMugshotFaceCompare, getFrontDocumentStatusMessage, scanDocument, isValidBarCode, createImages, isMobileFunc, frontDocumentOcr, } from './utils'; import { CameraFaceMode, DocType, FaceStatuses, ImageType, LOGTYPE } from './types'; import { facingMode } from './constants'; import { getCameraList, getVideoConstraints, isFaceTimeCamera, isMobileBackCameraPortrait } from './cameraUtils'; let isSimd = false; getIsSIMD().then((simd) => (isSimd = simd)); const debugType = getDebugType(); let privid_wasm_result = (operation, id, response_str) => { }; // camera configs let videoElement = null; let faceMode = CameraFaceMode.front; let mediaDevice = null; let mediaDevices = null; let mediaStream = null; const cameraHeight = 1440; const cameraWidth = 2560; const cameraLowResHeight = 1080; const cameraLowResWidth = 1920; const mobileCameraResWidth = 2560; const mobileCameraResHeight = 1440; const createCallbackMutiframeLivenessAndPredictAge = (callback, imageData) => (operation, id, response_str) => { var _a; const isResponse = response_str.length > 0; // console.log( // '================[JS RESPONSE]: response_str', // isResponse ? JSON.parse(response_str) : '', //, // //debugType, // //LOGTYPE.LOG, // ); // console.log('[JS RESPONSE]: operation', operation || 'null'); //debugType, LOGTYPE.LOG); // console.log('[JS RESPONSE]: id', id || 'null'); //debugType, LOGTYPE.LOG); if (isResponse) { const returnValue = JSON.parse(response_str); console.log("response:", JSON.parse(response_str)); const getResponse = (response) => { try { return JSON.parse(response); } catch (e) { return null; } }; const returnData = { call_status: returnValue.call_status.return_status, mf_token: returnValue.call_status.mf_token, face_validation_status: returnValue.estimate_age.face_validation_status, antispoof_status: returnValue.estimate_age.antispoofing_status, api_payload: returnValue.estimate_age.http_response_payload, remove_glasses: returnValue.estimate_age.young_with_eye_glasses, age_estimation: (_a = returnValue === null || returnValue === void 0 ? void 0 : returnValue.estimate_age) === null || _a === void 0 ? void 0 : _a.age_estimation }; if (operation === 'estimate_age') { callback({ status: FaceStatuses.WASM_RESPONSE, returnValue: returnData, portrait: imageData }); } } }; // Optimized Version const mfAgeCanvas = document.createElement('canvas'); export const multiframeLivenessAndAge = (callback, config) => __awaiter(void 0, void 0, void 0, function* () { privid_wasm_result = createCallbackMutiframeLivenessAndPredictAge(callback); if (!videoElement) { printLogs('capture need the video element id', '', debugType, LOGTYPE.ERROR); return { result: 'error' }; } const videoEl = document.getElementById(videoElement); printLogs('video element', videoEl, debugType); if (!videoEl) { printLogs('no video element found', '', debugType, LOGTYPE.ERROR); return { result: 'error' }; } const height = videoEl.videoHeight; const width = videoEl.videoWidth; if (width === 0) return { result: 'error' }; mfAgeCanvas.setAttribute('id', 'test-canvas'); mfAgeCanvas.setAttribute('height', `${height}`); mfAgeCanvas.setAttribute('width', `${width}`); // canvas.height = height; // canvas.width = width; const context = mfAgeCanvas.getContext('2d', { willReadFrequently: true }); context.drawImage(videoEl, 0, 0); const imageData = context.getImageData(0, 0, width, height); let finalConfig = { input_image_format: 'rgba', context_string: 'enroll', angle_rotation_left_threshold: 20.0, angle_rotation_right_threshold: 20.0, // preprocessing_margin_factor: 4, // antispoof_face_margin: 1.0, // gray_scale_variance_threshold: 100.0, // enroll_embeddings_compare: 1.9, threshold_high_vertical_enroll: -0.15, threshold_down_vertical_enroll: 0.15, // threshold_user_too_far: 0.15, threshold_user_right: 0.3, threshold_user_left: 0.7, threshold_user_up: 0.1, threshold_user_down: 0.9, // anti_spoofing_detect_document: true, threshold_profile_enroll: 0.65, threshold_user_too_close: 0.8, anti_spoofing_threshold: 0.8, // gray_scale_threshold: 14.0, threshold_doc_too_far: 40, conf_score_thr_doc: 0.9, }; const { os } = detect(); if (['iOS', 'android', 'Android OS'].includes(os)) { finalConfig = Object.assign(Object.assign({}, finalConfig), { // threshold_user_too_far: 0.1, threshold_user_right: 0.2, threshold_user_left: 0.8 }); } if (config) { finalConfig = Object.assign(Object.assign({}, finalConfig), config); } if (imageData) { privid_wasm_result = createCallbackMutiframeLivenessAndPredictAge(callback, imageData); const configString = JSON.stringify(finalConfig); console.log("Config before worker:", finalConfig); yield multiframeLivenessAndAgePredict(imageData.data, imageData.width, imageData.height, configString, proxy(privid_wasm_result)); } releaseCanvas(mfAgeCanvas); }); const openCameraMobile = (domElement, requestFaceMode = null, canvasResolution, requireHD = false, isDocumentScan) => __awaiter(void 0, void 0, void 0, function* () { try { let inCatchBlock = false; videoElement = domElement; printLogs('Opening Camera on Mobile', '', debugType); let devices = yield navigator.mediaDevices.enumerateDevices(); devices = devices.filter((d) => d.kind === 'videoinput'); devices = getDevicesWithCapabilities(devices); let stream; let hasError = true; while (hasError) { try { // @ts-ignore const videoConstraint = getVideoConstraints(yield getCameraList(faceMode === 'back'), // @ts-ignore facingMode[faceMode], requireHD, isDocumentScan, canvasResolution, inCatchBlock); // console.log('videoConstraint:', videoConstraint); stream = yield navigator.mediaDevices.getUserMedia( // @ts-ignore videoConstraint); hasError = false; } catch (e) { printLogs('openCameraMobile', e, debugType, LOGTYPE.ERROR); inCatchBlock = true; // hasError = false; } } const track = stream.getVideoTracks()[0]; const capabilities = track.getCapabilities(); const settings = track.getSettings(); const element = document.getElementById(domElement); element.srcObject = stream; element.play(); yield new Promise((resolve) => (element.onplaying = resolve)); mediaStream = stream; return { status: true, stream, devices, faceMode, settings, capabilities }; } catch (e) { printLogs('Error:', e, debugType, LOGTYPE.ERROR); return null; } }); /** * @ignore */ const openCameraMacSafari = (domElement, deviceId = null, canvasResolution = { width: cameraWidth, height: cameraHeight }, requireHD = false) => __awaiter(void 0, void 0, void 0, function* () { var _a, _b, _c, _d; try { videoElement = domElement; printLogs('Opening Camera on Mac Safari', '', debugType); let devices = yield navigator.mediaDevices.enumerateDevices(); devices = devices.filter((d) => d.kind === 'videoinput'); const defaultDeviceId = getDefaultCameraDeviceId(); const externalDeviceId = devices.length > 1 ? devices.find((device) => !device.label.includes('FaceTime')) : devices[0]; const isDefaultDeviceAvailable = devices.find((device) => defaultDeviceId === device.deviceId); mediaDevice = deviceId || (isDefaultDeviceAvailable ? defaultDeviceId : externalDeviceId.deviceId); setDefaultCameraDeviceId(mediaDevice); const deviceCapabilites = getDefaultDevice(devices, mediaDevice); const resolution = requireHD ? (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) || Math.min(((_b = (_a = deviceCapabilites[0]) === null || _a === void 0 ? void 0 : _a.width) === null || _b === void 0 ? void 0 : _b.max) || cameraWidth, cameraWidth) : (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) || Math.min(((_d = (_c = deviceCapabilites[0]) === null || _c === void 0 ? void 0 : _c.width) === null || _d === void 0 ? void 0 : _d.max) || cameraLowResWidth, cameraLowResWidth); const constraints = { audio: false, video: { deviceId: deviceCapabilites[0].deviceId, width: { ideal: resolution }, height: (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height) ? { ideal: canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height } : undefined, // advance: [{ width: { ideal: 2560 }, height: { ideal: 1440 } }], }, }; const stream = yield navigator.mediaDevices.getUserMedia(constraints); const track = stream.getVideoTracks()[0]; const capabilities = track.getCapabilities(); const settings = track.getSettings(); printLogs('capabilities: ', capabilities, debugType, LOGTYPE.LOG); printLogs('settings: ', settings, debugType, LOGTYPE.LOG); const element = document.getElementById(domElement); element.srcObject = stream; element.play(); yield new Promise((resolve) => (element.onplaying = resolve)); mediaStream = stream; return { status: true, stream, devices, faceMode, settings, capabilities }; } catch (e) { printLogs('Error while getAccessToCamera', e, debugType, LOGTYPE.ERROR); return null; } }); const openCameraFirefox = (domElement, canvasResolution = { width: cameraWidth, height: cameraHeight }, requireHD = false) => __awaiter(void 0, void 0, void 0, function* () { videoElement = domElement; yield navigator.mediaDevices.getUserMedia({ audio: false, video: true }); printLogs('Firefox function here.....', '', debugType); try { let devices = []; devices = yield navigator.mediaDevices.enumerateDevices(); devices = devices.filter((d) => d.kind === 'videoinput'); printLogs('=====> MY DEVICES??? ', devices, debugType); if (devices.length === 0) { printLogs('NO_CAMERA', '', debugType, LOGTYPE.ERROR); throw new Error('NO_CAMERA'); } const constraints = { audio: false, video: { width: { ideal: (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) || requireHD ? cameraWidth : cameraLowResWidth }, height: (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height) ? { ideal: canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height } : undefined, }, aspectRatio: 1.7777777778, focusMode: 'continuous', facingMode: facingMode[faceMode] || 'user', }; const stream = yield navigator.mediaDevices.getUserMedia(constraints); const track = stream.getVideoTracks()[0]; const settings = track.getSettings(); const capabilities = (track === null || track === void 0 ? void 0 : track.getCapabilities) ? track.getCapabilities() : stream; printLogs('settings: ', settings, debugType); const element = document.getElementById(domElement); element.srcObject = stream; element.play(); yield new Promise((resolve) => (element.onplaying = resolve)); mediaStream = stream; mediaDevices = devices; // @ts-ignore return { status: true, errorMessage: '', stream, devices, faceMode, settings, capabilities }; } catch (e) { if (parseInt(debugType, 10) >= 2) { printLogs('Error while getAccessToCamera', e, debugType, LOGTYPE.ERROR); } return null; } }); /** * This function open camera, and returns the stream, current faceMode and the list of available media devices * @category Face * @param domElement id of the video tag * @param requireHD * @param deviceId * @param requestFaceMode * @param canvasResolution * @param isDocumentScan */ export const openCamera = (domElement, requireHD, deviceId = null, requestFaceMode = null, canvasResolution, isDocumentScan) => __awaiter(void 0, void 0, void 0, function* () { var _e, _f, _g; videoElement = domElement; faceMode = requestFaceMode; const { name: browserName, os } = detect(); yield navigator.mediaDevices.getUserMedia({ video: true, audio: false }).then((mediaStream) => { const stream = mediaStream; const tracks = stream.getTracks(); tracks.forEach((track) => track.stop()); }); // Firefox if (browserName === 'firefox') { printLogs('==== Firefox open camera', '', debugType); return openCameraFirefox(domElement, canvasResolution, requireHD); } // Mobile if (iOS() || ['iOS', 'android', 'Android OS'].includes(os)) { printLogs('==== Mobile open camera!', '', debugType); return openCameraMobile(domElement, requestFaceMode, canvasResolution, requireHD, isDocumentScan); } // Mac Safari Browser if (os === 'Mac OS' && browserName === 'safari') { printLogs('==== Mac safari open camera!', '', debugType); return openCameraMacSafari(domElement, deviceId, canvasResolution, requireHD); } try { let devices = []; devices = yield navigator.mediaDevices.enumerateDevices(); devices = devices.filter((d) => d.kind === 'videoinput'); printLogs('=====> MY DEVICES??? ', devices, debugType); if (devices.length === 0) { printLogs('NO_CAMERA', '', debugType, LOGTYPE.ERROR); throw new Error('NO_CAMERA'); } let defaultDeviceId = getDefaultCameraDeviceId(); if (deviceId) { defaultDeviceId = deviceId; } if (!mediaDevice) { if (deviceId) { mediaDevice = deviceId; } else { const isDefaultDeviceAvailable = devices.find((device) => defaultDeviceId === device.deviceId); mediaDevice = isDefaultDeviceAvailable ? defaultDeviceId : devices[0].deviceId; } } const deviceCapabilites = getDefaultDevice(devices, mediaDevice); const isMacFaceTimeCamera = isFaceTimeCamera((_e = deviceCapabilites[0]) === null || _e === void 0 ? void 0 : _e.label, isDocumentScan); printLogs('========= Opens Camera ======== ', '', debugType); const getBestResolution = () => __awaiter(void 0, void 0, void 0, function* () { var _h, _j; let resolution = (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) || Math.min(((_j = (_h = deviceCapabilites[0]) === null || _h === void 0 ? void 0 : _h.width) === null || _j === void 0 ? void 0 : _j.max) || cameraWidth, cameraWidth); let hasError = true; let constraints = { audio: false, video: { deviceId: deviceCapabilites[0].deviceId, width: { ideal: resolution }, height: (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height) ? { ideal: canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height } : { ideal: cameraHeight }, aspectRatio: isMacFaceTimeCamera ? 1 : 1.777777778, resizeMode: 'none', }, }; let stream; while (hasError) { try { stream = yield navigator.mediaDevices.getUserMedia(constraints); if (stream) hasError = false; } catch (e) { resolution = getTheNextResolutionAvailable(resolution); constraints = Object.assign(Object.assign({}, constraints), { video: Object.assign(Object.assign({}, constraints.video), { width: { ideal: resolution } }) }); } } printLogs('bestconstraints: ', constraints, debugType); return stream; }); let stream; if (requireHD) { let hasError = true; let resolution = (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) || Math.min(((_g = (_f = deviceCapabilites[0]) === null || _f === void 0 ? void 0 : _f.width) === null || _g === void 0 ? void 0 : _g.max) || cameraWidth, cameraWidth); let constraints = { audio: false, deviceId: mediaDevice, video: { width: { min: resolution, max: resolution }, aspectRatio: isMacFaceTimeCamera ? 1 : 1.777777778, height: isMacFaceTimeCamera ? { min: cameraHeight, max: cameraHeight } : undefined, }, }; while (hasError) { try { stream = yield navigator.mediaDevices.getUserMedia(constraints); if (stream) hasError = false; } catch (e) { printLogs('require HD Error: ', e, debugType, LOGTYPE.ERROR); resolution = getTheNextResolutionAvailable(resolution); constraints = Object.assign(Object.assign({}, constraints), { video: Object.assign(Object.assign({}, constraints.video), { width: { min: resolution, max: resolution } }) }); } } } else { stream = yield getBestResolution(); } const track = stream.getVideoTracks()[0]; const capabilities = track.getCapabilities(); const settings = track.getSettings(); setDefaultCameraDeviceId(settings === null || settings === void 0 ? void 0 : settings.deviceId); printLogs('capabilities: ', capabilities, debugType); printLogs('settings: ', settings, debugType); const element = document.getElementById(domElement); element.srcObject = stream; element.play(); yield new Promise((resolve) => (element.onplaying = resolve)); mediaStream = stream; mediaDevices = devices; return { status: true, stream, devices, faceMode, settings, capabilities }; } catch (e) { printLogs('Error while getAccessToCamera', e, debugType, LOGTYPE.ERROR); return null; } }); /** * This function open camera, and returns the stream, current faceMode and the list of available media devices * @category Face * @param domElement id of the video tag */ export const closeCamera = (element) => __awaiter(void 0, void 0, void 0, function* () { try { const video = element || videoElement; const videoEl = document.getElementById(video); if (!videoEl) return; const stream = videoEl === null || videoEl === void 0 ? void 0 : videoEl.srcObject; if (stream) { const tracks = stream === null || stream === void 0 ? void 0 : stream.getTracks(); tracks === null || tracks === void 0 ? void 0 : tracks.forEach((track) => { track === null || track === void 0 ? void 0 : track.stop(); }); if (videoEl) { videoEl.srcObject = null; } } } catch (err) { printLogs('Close Camera', err, debugType, LOGTYPE.ERROR); } }); const getTheNextResolutionAvailable = (currentResolution) => { printLogs('getTheNextResolutionAvailable', currentResolution, debugType); const resolutions = [2560, 1920, 1600, 1552, 1440, 1280, 1024, 960, 800, 720, 704, 640].sort((a, b) => b - a); return resolutions.find((e) => e < currentResolution) || 640; }; /** * This function switch camera from front to back on mobile, and to another device on desktop * @category Face * @param selectedCamera Selected camera either front or back * @param device Selected camera ID * @param canvasResolution */ export const switchCamera = (selectedCamera, device, canvasResolution) => __awaiter(void 0, void 0, void 0, function* () { if (!videoElement) return; let devices = []; if (mediaStream) { mediaStream.getTracks().forEach((track) => track.stop()); } devices = yield navigator.mediaDevices.enumerateDevices(); devices = devices.filter((d) => d.kind === 'videoinput'); devices = getDevicesWithCapabilities(devices); const deviceCapabilites = getDefaultDevice(devices, device); if (selectedCamera) faceMode = selectedCamera; const getBestResolution = () => __awaiter(void 0, void 0, void 0, function* () { var _k, _l, _m, _o; let resolution = (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) || Math.min(((_l = (_k = deviceCapabilites[0]) === null || _k === void 0 ? void 0 : _k.width) === null || _l === void 0 ? void 0 : _l.max) || cameraWidth, cameraWidth); const isPortraitMobileCamera = isMobileBackCameraPortrait(deviceCapabilites[0]); console.log('switchCamera', { deviceCapabilites }); let hasError = true; const videoConstraints = { deviceId: deviceCapabilites[0].deviceId, width: { ideal: calculateWidth() }, height: { ideal: calculateHeight() }, facingMode: ((_o = (_m = deviceCapabilites[0]) === null || _m === void 0 ? void 0 : _m.facingMode) === null || _o === void 0 ? void 0 : _o[0]) || undefined, focusMode: 'continuous', aspectRatio: calculateAspectRatio(), resizeMode: 'none', }; const constraints = { audio: false, video: videoConstraints, // Apply video constraints }; function calculateWidth() { if (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) { return resolution; // Use the specified resolution if canvas width is available } else if (isPortraitMobileCamera) { return cameraHeight; // Use camera height for portrait mobile camera } else { return resolution; // Use the specified resolution for other cases } } function calculateHeight() { if (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height) { return canvasResolution.height; // Use the specified canvas height } else { return cameraHeight; // Use camera height if canvas height is not available } } function calculateAspectRatio() { if (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) { return 1.7777777778; // 16:9 aspect ratio if canvas width is available } else if (isPortraitMobileCamera) { return 1; // 1:1 aspect ratio for portrait mobile camera } else { return 1.7777777778; // 16:9 aspect ratio for other cases } } // console.log({ constraints }); let stream; while (hasError) { try { stream = yield navigator.mediaDevices.getUserMedia(constraints); hasError = false; } catch (e) { resolution = getTheNextResolutionAvailable(resolution); constraints.video = Object.assign(Object.assign({}, constraints.video), { width: { ideal: resolution } }); } } printLogs('bestconstraints: ', constraints, debugType); return stream; }); if (device) { mediaDevice = device; setDefaultCameraDeviceId(device); } if (selectedCamera && !device) { if (selectedCamera) { const regex = selectedCamera === CameraFaceMode.back ? /back/gi : /front/gi; devices = devices.filter((d) => regex.test(d.label)); } const getBestResolutionWithFacingMode = () => __awaiter(void 0, void 0, void 0, function* () { var _p, _q; const deviceCapabilites = getDefaultDevice(devices, devices[0].deviceId); const { name: browserName, os } = detect(); const resolutionWidth = (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.width) || (iOS() || ['iOS'].includes(os) ? cameraLowResWidth : cameraWidth); const resolutionHeight = (canvasResolution === null || canvasResolution === void 0 ? void 0 : canvasResolution.height) || (iOS() || ['iOS'].includes(os) ? cameraLowResHeight : cameraHeight); let hasError = true; const constraints = { audio: false, video: { // deviceId: deviceCapabilites[0].deviceId, width: { ideal: resolutionWidth }, facingMode: faceMode ? facingMode[faceMode] : 'user', height: { ideal: resolutionHeight }, resizeMode: 'none', }, advance: [ { focusMode: 'continuous', resizeMode: 'none', // @ts-ignore focusDistance: Math.min(((_q = (_p = deviceCapabilites[0]) === null || _p === void 0 ? void 0 : _p.focusDistance) === null || _q === void 0 ? void 0 : _q.max) || 100, 100), aspectRatio: 1.7777777778, }, ], }; let stream; while (hasError) { try { stream = yield navigator.mediaDevices.getUserMedia(constraints); hasError = false; } catch (e) { // } } printLogs('bestconstraints: ', constraints, debugType); return stream; }); try { // eslint-disable-next-line no-nested-ternary const stream = yield getBestResolutionWithFacingMode(); const element = document.getElementById(videoElement); element.srcObject = stream; mediaStream = stream; const track = stream.getVideoTracks()[0]; const capabilities = (track === null || track === void 0 ? void 0 : track.getCapabilities) ? track.getCapabilities() : null; const settings = track.getSettings(); printLogs('switch camera capabilities:', capabilities, debugType); printLogs('switch camera settings:', settings, debugType); // eslint-disable-next-line consistent-return return { capabilities, settings }; } catch (e) { printLogs('Error while getAccessToCamera', e, debugType, LOGTYPE.ERROR); yield switchCamera(null, devices[0].deviceId, canvasResolution); } } else { try { // eslint-disable-next-line no-nested-ternary const stream = yield getBestResolution(); const element = document.getElementById(videoElement); element.srcObject = stream; mediaStream = stream; const track = stream.getVideoTracks()[0]; const capabilities = (track === null || track === void 0 ? void 0 : track.getCapabilities) ? track.getCapabilities() : null; const settings = track.getSettings(); printLogs('switch camera capabilities:', capabilities, debugType); printLogs('switch camera settings:', settings, debugType); // eslint-disable-next-line consistent-return return { capabilities, settings }; } catch (e) { printLogs('Error while getAccessToCamera', e, debugType, LOGTYPE.ERROR); yield switchCamera(null, devices[0].deviceId, canvasResolution); } } }); const getDefaultDevice = (devices, device) => devices.reduce((acc, val) => { if (val.deviceId === device) { // @ts-ignore if (val === null || val === void 0 ? void 0 : val.getCapabilities) { // @ts-ignore acc.push(Object.assign(Object.assign({}, val.getCapabilities()), { label: val.label })); } else { acc.push(val); } } return acc; }, []); const getDevicesWithCapabilities = (devices) => devices.map((device) => { // Check if 'getCapabilities' exists on 'device' // @ts-ignore if (device.getCapabilities) { // Use 'device.getCapabilities()' directly without optional chaining // @ts-ignore const capabilities = device.getCapabilities(); // Return a new object with capabilities and label return Object.assign(Object.assign({}, capabilities), { label: device.label }); } return device; }); function releaseCanvas(canvas) { try { printLogs('---- STARTING TO RELEASE CANVAS -----', '', debugType); // eslint-disable-next-line no-param-reassign canvas.width = 1; // eslint-disable-next-line no-param-reassign canvas.height = 1; const ctx = canvas.getContext('2d', { willReadFrequently: true }); // eslint-disable-next-line no-unused-expressions ctx && ctx.clearRect(0, 0, 1, 1); // eslint-disable-next-line no-param-reassign canvas = null; printLogs('---- CANVAS RELEASED -----', '', debugType); } catch (e) { printLogs('____clearing canvas', e, debugType, LOGTYPE.ERROR); } } export const openFrontCameraOnly = (domElement, deviceId = null) => __awaiter(void 0, void 0, void 0, function* () { var _r; videoElement = domElement; yield navigator.mediaDevices.getUserMedia({ video: true, audio: false }).then((mediaStream) => { const stream = mediaStream; const tracks = stream.getTracks(); tracks.forEach((track) => track.stop()); }); try { let devices = []; devices = yield navigator.mediaDevices.enumerateDevices(); const frontRegex = /front/gi; devices = devices.filter((d) => d.kind === 'videoinput' && frontRegex.test(d.label)); printLogs('=====> MY DEVICES??? ', devices, debugType); if (devices.length === 0) { printLogs('No front camera available', '', debugType, LOGTYPE.ERROR); throw new Error('No front Camera available'); } let defaultDeviceId = getDefaultCameraDeviceId(); if (deviceId) { defaultDeviceId = deviceId; } if (!mediaDevice) { if (deviceId) { mediaDevice = deviceId; } else { const isDefaultDeviceAvailable = devices.find((device) => defaultDeviceId === device.deviceId); mediaDevice = isDefaultDeviceAvailable ? defaultDeviceId : devices[0].deviceId; } } const deviceCapabilites = getDefaultDevice(devices, mediaDevice); const isMacFaceTimeCamera = isFaceTimeCamera((_r = deviceCapabilites[0]) === null || _r === void 0 ? void 0 : _r.label, false); printLogs('========= Opens Camera ======== ', '', debugType); const getBestResolution = () => __awaiter(void 0, void 0, void 0, function* () { var _s, _t; let resolution = Math.min(((_t = (_s = deviceCapabilites[0]) === null || _s === void 0 ? void 0 : _s.width) === null || _t === void 0 ? void 0 : _t.max) || cameraWidth, cameraWidth); let hasError = true; let constraints = { audio: false, video: { deviceId: deviceCapabilites[0].deviceId, width: { ideal: 1920 }, height: { ideal: 1080 }, resizeMode: 'none', facingMode: 'user', }, }; let stream; while (hasError) { try { stream = yield navigator.mediaDevices.getUserMedia(constraints); if (stream) hasError = false; } catch (e) { resolution = getTheNextResolutionAvailable(resolution); constraints = Object.assign(Object.assign({}, constraints), { video: Object.assign(Object.assign({}, constraints.video), { width: { ideal: resolution } }) }); } } printLogs('bestconstraints: ', constraints, debugType); return stream; }); let stream; stream = yield getBestResolution(); const track = stream.getVideoTracks()[0]; const capabilities = track.getCapabilities(); const settings = track.getSettings(); setDefaultCameraDeviceId(settings === null || settings === void 0 ? void 0 : settings.deviceId); printLogs('capabilities: ', capabilities, debugType); printLogs('settings: ', settings, debugType); const element = document.getElementById(domElement); element.srcObject = stream; element.play(); yield new Promise((resolve) => (element.onplaying = resolve)); mediaStream = stream; mediaDevices = devices; return { status: true, stream, devices, faceMode, settings, capabilities }; } catch (e) { printLogs('Error while getAccessToCamera', e, debugType, LOGTYPE.ERROR); return null; } }); const createCallbackCompareDocumentAndFace = (callback) => (operation, id, response_str) => { const isResponse = response_str.length > 0; console.log('================[JS RESPONSE]: response_str', isResponse ? JSON.parse(response_str) : ''); //, LOGTYPE.LOG); console.log('[JS RESPONSE]: operation', operation || 'null'); // , LOGTYPE.LOG); console.log('[JS RESPONSE]: id', id || 'null'); // , LOGTYPE.LOG); if (isResponse) { if (operation === 'compare_mugshot_and_face') { const returnValue = JSON.parse(response_str); const getJsonParsed = (toParse) => { try { return JSON.parse(toParse); } catch (e) { return ''; } }; callback({ status: FaceStatuses.WASM_RESPONSE, returnValue: getJsonParsed(returnValue.compare_face_and_mugshot.http_response_payload), }); } } }; export const documentMugshotFaceCompare = (callback, imageDataA, imageDataB, config) => __awaiter(void 0, void 0, void 0, function* () { privid_wasm_result = createCallbackCompareDocumentAndFace(callback); let finalConfig = { input_image_format: 'rgba', skip_antispoof: true, angle_rotation_left_threshold: 100.0, angle_rotation_right_threshold: 100.0, threshold_high_vertical_enroll: -0.2, threshold_down_vertical_enroll: 0.2, threshold_high_vertical_predict: -0.2, threshold_down_vertical_predict: 0.2, threshold_user_too_far: 0.01, threshold_profile_predict: 0.8, threshold_profile_enroll: 0.8, }; if (config) { finalConfig = Object.assign(Object.assign({}, finalConfig), config); } const configJSON = JSON.stringify(finalConfig); const result = yield prividDocumentMugshotFaceCompare(imageDataA, imageDataB, isSimd, debugType, proxy(privid_wasm_result), configJSON); return result; }); const createCallbackFrontDlScan = (callback, canvas) => (operation, id, response_str) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1; const isResponse = response_str.length > 0; // console.log('================[JS RESPONSE]: response_str', isResponse ? JSON.parse(response_str) : ''); // , LOGTYPE.LOG); // console.log('[JS RESPONSE]: operation', operation || 'null'); //, LOGTYPE.LOG); // console.log('[JS RESPONSE]: id', id || 'null'); //, LOGTYPE.LOG); if (isResponse) { if (operation === 'document_model') { const returnValue = JSON.parse(response_str); const returnData = { document_validation_status: (_b = (_a = returnValue === null || returnValue === void 0 ? void 0 : returnValue.doc_face) === null || _a === void 0 ? void 0 : _a.document_data) === null || _b === void 0 ? void 0 : _b.document_validation_status, call_status: (_c = returnValue === null || returnValue === void 0 ? void 0 : returnValue.call_status) === null || _c === void 0 ? void 0 : _c.return_status, cropped_mugshot: { data: (_e = (_d = returnValue === null || returnValue === void 0 ? void 0 : returnValue.doc_face) === null || _d === void 0 ? void 0 : _d.cropped_face_image) === null || _e === void 0 ? void 0 : _e.data, width: (_h = (_g = (_f = returnValue === null || returnValue === void 0 ? void 0 : returnValue.doc_face) === null || _f === void 0 ? void 0 : _f.cropped_face_image) === null || _g === void 0 ? void 0 : _g.info) === null || _h === void 0 ? void 0 : _h.width, height: (_l = (_k = (_j = returnValue === null || returnValue === void 0 ? void 0 : returnValue.doc_face) === null || _j === void 0 ? void 0 : _j.cropped_face_image) === null || _k === void 0 ? void 0 : _k.info) === null || _l === void 0 ? void 0 : _l.height, }, cropped_document: { data: (_p = (_o = (_m = returnValue === null || returnValue === void 0 ? void 0 : returnValue.doc_face) === null || _m === void 0 ? void 0 : _m.document_data) === null || _o === void 0 ? void 0 : _o.cropped_document_image) === null || _p === void 0 ? void 0 : _p.data, width: (_t = (_s = (_r = (_q = returnValue === null || returnValue === void 0 ? void 0 : returnValue.doc_face) === null || _q === void 0 ? void 0 : _q.document_data) === null || _r === void 0 ? void 0 : _r.cropped_document_image) === null || _s === void 0 ? void 0 : _s.info) === null || _t === void 0 ? void 0 : _t.width, height: (_x = (_w = (_v = (_u = returnValue === null || returnValue === void 0 ? void 0 : returnValue.doc_face) === null || _u === void 0 ? void 0 : _u.document_data) === null || _v === void 0 ? void 0 : _v.cropped_document_image) === null || _w === void 0 ? void 0 : _w.info) === null || _x === void 0 ? void 0 : _x.height, }, }; callback({ status: FaceStatuses.WASM_RESPONSE, returnValue: Object.assign(Object.assign({}, returnData), { status_message: getFrontDocumentStatusMessage((_z = (_y = returnValue === null || returnValue === void 0 ? void 0 : returnValue.doc_face) === null || _y === void 0 ? void 0 : _y.document_data) === null || _z === void 0 ? void 0 : _z.document_validation_status) }), }); if (((_1 = (_0 = returnValue === null || returnValue === void 0 ? void 0 : returnValue.doc_face) === null || _0 === void 0 ? void 0 : _0.document_data) === null || _1 === void 0 ? void 0 : _1.document_validation_status) === 0) { releaseCanvas(canvas); } } } }; const createCallbackBackDlScan = (callback, canvas) => (operation, id, response_str) => { var _a, _b, _c, _d; const isResponse = response_str.length > 0; // console.log('================[JS RESPONSE]: response_str', isResponse ? JSON.parse(response_str) : ''); //, LOGTYPE.LOG); // console.log('[JS RESPONSE]: operation', operation || 'null'); //, LOGTYPE.LOG); // console.log('[JS RESPONSE]: id', id || 'null'); //, LOGTYPE.LOG); if (isResponse) { const returnValue = JSON.parse(response_str); const parseResponse = (toParse) => { try { return JSON.parse(toParse); } catch (e) { return ''; } }; if (operation === 'gage_doc_scan_barcode_for_age') { const returnData = { call_status: (_a = returnValue === null || returnValue === void 0 ? void 0 : returnValue.call_status) === null || _a === void 0 ? void 0 : _a.return_status, document_validation_status: (_b = returnValue === null || returnValue === void 0 ? void 0 : returnValue.scan_barcode_for_age) === null || _b === void 0 ? void 0 : _b.document_validation_status, barcode_status: (_c = returnValue === null || returnValue === void 0 ? void 0 : returnValue.scan_barcode_for_age) === null || _c === void 0 ? void 0 : _c.bar_code_detection_status, api_response: parseResponse((_d = returnValue === null || returnValue === void 0 ? void 0 : returnValue.scan_barcode_for_age) === null || _d === void 0 ? void 0 : _d.http_response_payload), }; // GAN, if Missing Field = undefined callback({ status: FaceStatuses.WASM_RESPONSE, returnValue: Object.assign({}, returnData), }); if (returnData.barcode_status === 0) { releaseCanvas(canvas); } } } }; const isValidPhotoIDCanvas = document.createElement('canvas'); export const isValidPhotoID = (docType, callback = () => { }, image, config = null, canvasSize = {}) => __awaiter(void 0, void 0, void 0, function* () { printLogs('________________ DOCUMENT SCAN ______________', '', debugType); const videoEl = document.getElementById(videoElement); let configuration = { document_auto_rotation: false, input_image_format: 'rgba', }; if (config) { configuration = Object.assign(Object.assign({}, configuration), config); } if (docType === DocType.PHOTO_ID_FRONT) { privid_wasm_result = createCallbackFrontDlScan(callback, isValidPhotoIDCanvas); } else { privid_wasm_result = createCallbackBackDlScan(callback, isValidPhotoIDCanvas); } if (image && docType === DocType.PHOTO_ID_FRONT) { // console.log('uploading with image', image); const result = yield scanDocument(image, isSimd, proxy(privid_wasm_result), undefined, JSON.stringify(configuration), debugType); return Object.assign({ imageData: image }, result); } if (image && docType === DocType.PHOTO_ID_BACK) { configuration = JSON.stringify(configuration); // console.log('uploading with image', image); const result = yield isValidBarCode(image, isSimd, proxy(privid_wasm_result), configuration, debugType); return Object.assign({ imageData: image }, result); } if (!videoElement || !videoEl) { printLogs('capture need the video element id', '', debugType, LOGTYPE.ERROR); return { result: 'error' }; } const isDocument = docType === DocType.PHOTO_ID_FRONT; let height = (canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.height) || videoEl.videoHeight; let width = (canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.width) || videoEl.videoWidth; if (isMobileFunc()) { height = videoEl.videoHeight; width = videoEl.videoWidth; } isValidPhotoIDCanvas.setAttribute('id', 'test-canvas'); isValidPhotoIDCanvas.setAttribute('height', `${height}`); isValidPhotoIDCanvas.setAttribute('width', `${width}`); const context = isValidPhotoIDCanvas.getContext('2d', { willReadFrequently: true }); context.drawImage(videoEl, 0, 0); if ((image === null || image === void 0 ? void 0 : image.width) === 0 || width === 0 || height === 0) return { result: 'error' }; let imageData = context.getImageData(0, 0, width, height); let result = null; const cb = proxy(privid_wasm_result); if (['900', '901', '902', '903'].includes(debugType)) { yield createImages([imageData], ImageType.original, true); } if (image) { imageData = image; } try { configuration = JSON.stringify(configuration); if (isDocument) { result = yield scanDocument(imageData, isSimd, cb, undefined, configuration, debugType); } else { result = yield isValidBarCode(imageData, isSimd, cb, configuration, debugType); } imageData = null; return Object.assign({}, result); } catch (e) { printLogs('--------isValidPhotoID error', e, debugType); return { result: -1, }; } }); const createCallbackFrontOcr = (callback) => (operation, id, response_str) => { var _a, _b, _c, _d; const isResponse = response_str.length > 0; console.log('================[JS RESPONSE]: CC OCR response_str', isResponse ? JSON.parse(response_str) : ''); //, LOGTYPE.LOG); // console.log('[JS RESPONSE]: operation', operation || 'null'); //, LOGTYPE.LOG); // console.log('[JS RESPONSE]: id', id || 'null'); //, LOGTYPE.LOG); const parseJson = (doParse) => { try { return JSON.parse(doParse); } catch (e) { return ''; } }; if (isResponse) { // if (operation === 'estimate_age') { const returnValue = JSON.parse(response_str); const returnData = { call_status: returnValue.call_status.return_status, face_validation_status: (_a = returnValue === null || returnValue === void 0 ? void 0 : returnValue.scan_document_for_age) === null || _a === void 0 ? void 0 : _a.face_validataion_status, antispoof_status: (_b = returnValue === null || returnValue === void 0 ? void 0 : returnValue.scan_document_for_age) === null || _b === void 0 ? void 0 : _b.antispoofing_status, api_payload: (_c = returnValue === null || returnValue === void 0 ? void 0 : returnValue.scan_document_for_age) === null || _c === void 0 ? void 0 : _c.http_response_payload, age_estimation: (_d = returnValue === null || returnValue === void 0 ? void 0 : returnValue.scan_document_for_age) === null || _d === void 0 ? void 0 : _d.age_estimation }; callback({ status: FaceStatuses.WASM_RESPONSE, returnValue: returnData }); // } } }; export const scanDocumentWithOcr = (callback = () => { }, image, config = null, canvasSize = {}) => __awaiter(void 0, void 0, void 0, function* () { printLogs('________________ DOCUMENT SCAN ______________', '', debugType); const videoEl = document.getElementById(videoElement); let configuration = { document_auto_rotation: false, input_image_format: 'rgba', }; if (config) { configuration = Object.assign(Object.assign({}, configuration), config); } privid_wasm_result = createCallbackFrontOcr(callback); if (!videoElement || !videoEl) { printLogs('capture need the video element id', '', debugType, LOGTYPE.ERROR); return { result: 'error' }; } let height = (canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.height) || videoEl.videoHeight; let width = (canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.width) || videoEl.videoWidth; if (isMobileFunc()) { height = videoEl.videoHeight; width = videoEl.videoWidth; } isValidPhotoIDCanvas.setAttribute('id', 'test-canvas'); isValidPhotoIDCanvas.setAttribute('height', `${height}`); isValidPhotoIDCanvas.setAttribute('width', `${width}`); const context = isValidPhotoIDCanvas.getContext('2d', { willReadFrequently: true }); context.drawImage(videoEl, 0, 0); if ((image === null || image === void 0 ? void 0 : image.width) === 0 || width === 0 || height === 0) return { result: 'error' }; let imageData = context.getImageData(0, 0, width, height); let result = null; const cb = proxy(privid_wasm_result); if (['900', '901', '902', '903'].includes(debugType)) { yield