santoid-sdk 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -147,7 +147,7 @@ Ao importar a biblioteca via tag script, a função **livenessDetection** ficar
147
147
  <body>
148
148
  <button onclick="startLiveness()">Iniciar</button>
149
149
 
150
- <script src="https://cdn.jsdelivr.net/npm/santoid-sdk@1.0.1/dist/browser/liveness/index.js"></script>
150
+ <script src="https://cdn.jsdelivr.net/npm/santoid-sdk@1.0.3/dist/browser/liveness/index.js"></script>
151
151
 
152
152
  <script>
153
153
  async function startLiveness () {
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("SantoiDSDK",[],t):"object"==typeof exports?exports.SantoiDSDK=t():e.SantoiDSDK=t()}(this,(()=>(()=>{"use strict";var e={401:function(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var a=Object.getOwnPropertyDescriptor(t,o);a&&!("get"in a?!t.__esModule:a.writable||a.configurable)||(a={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,a)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),a=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),t.livenessDetection=void 0;const r=o(553),i=o(793),c=o(692);async function l(e){var t,o,n;let a,l,s,d=!1,u=!1,v=!1;async function p(e,t,o){var n;o&&clearInterval(o),t&&(0,c.disconnectFromWebSocket)(t),a&&a.stopGetNextFrame(),!v&&await(null===(n=e.endCallback)||void 0===n?void 0:n.call(e)),v=!0,d=!0}try{let n;return s=await(0,c.connectToWebSocket)(e),await(null===(t=e.nextStepCallback)||void 0===t?void 0:t.call(e,"front")),await(null===(o=e.frontCallback)||void 0===o?void 0:o.call(e)),e.getNextFrame||a||(a=await(0,i.builtInGetNextFrame)()),l=setInterval((async()=>{try{if(null==n?void 0:n.can_send_next_bytes){let t;t=e.getNextFrame?await e.getNextFrame():await(null==a?void 0:a.getNextFrame()),t&&(null==s||s.send(t))}}catch(t){await p(e,s,l)}}),r.SEND_FRAMES_INTERVAL_MS),s.addEventListener("message",(async t=>{var o;const a=await async function(e,t){var o,n,a;const r=t.data;let i;try{i=JSON.parse(r)}catch(e){console.error("Cannot parse API message",e)}return(null==i?void 0:i.next_step)&&!i.error&&(await(null===(o=e.nextStepCallback)||void 0===o?void 0:o.call(e,i.next_step)),await(null===(n=e[`${i.next_step}Callback`])||void 0===n?void 0:n.call(e))),(null==i?void 0:i.error)&&await(null===(a=e.errorCallback)||void 0===a?void 0:a.call(e,{code:"wrong-position"})),i}(e,t);a&&(n=a),(null==a?void 0:a.success)&&(u=!0,await(null===(o=e.successCallback)||void 0===o?void 0:o.call(e)),await p(e,s,l))})),s.addEventListener("error",(async()=>{var t;!u&&(null===(t=e.errorCallback)||void 0===t||t.call(e,{code:"internal-error"})),await p(e,s,l)})),s.addEventListener("close",(async()=>{var t;d||(!u&&(null===(t=e.errorCallback)||void 0===t||t.call(e,{code:"internal-error"})),await p(e,s,l))})),n={can_send_next_bytes:!0},{stopLivenessDetection:async()=>{await p(e,s,l)},videoStream:null==a?void 0:a.videoStream}}catch(t){throw!u&&(null===(n=e.errorCallback)||void 0===n||n.call(e,{code:"internal-error"})),await p(e,s,l),t}}a(o(722),t),t.livenessDetection=l;class s{}s.livenessDetection=l,t.default=s},793:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.builtInGetNextFrame=void 0,t.builtInGetNextFrame=async function(){let e,t,o;return e&&t&&o||(e=await navigator.mediaDevices.getUserMedia({video:!0}),t=document.createElement("video"),t.setAttribute("autoplay","true"),t.style.position="absolute",t.style.left="99999px",document.body.appendChild(t),t.srcObject=e,o=document.createElement("canvas")),{getNextFrame:async function(){if(o&&t){const e=o.getContext("2d");return o.width=t.videoWidth,o.height=t.videoHeight,null==e||e.drawImage(t,0,0,o.width,o.height),await new Promise(((e,t)=>{o?o.toBlob((t=>{e(t)})):e(null)}))}throw new Error("Cannot found video element")},stopGetNextFrame:function(){t&&(document.body.removeChild(t),t=void 0),o&&(o=void 0),null==e||e.getTracks().forEach((e=>{e.stop()})),e=void 0},videoStream:e}}},268:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.decodeJwt=void 0,t.decodeJwt=function(e){const t=e.split(".")[1].replace(/-/g,"+").replace(/_/g,"/"),o=decodeURIComponent(window.atob(t).split("").map((e=>"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2))).join(""));return JSON.parse(o)}},722:function(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var a=Object.getOwnPropertyDescriptor(t,o);a&&!("get"in a?!t.__esModule:a.writable||a.configurable)||(a={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,a)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),a=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),a(o(307),t)},692:(e,t,o)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.disconnectFromWebSocket=t.connectToWebSocket=void 0;const n=o(268),a=o(553);t.connectToWebSocket=async function(e){var t;const o=(0,n.decodeJwt)(e.token),r=`?x_endpoint_api_userinfo=${e.token}&domain=${o.claims.domain}&track=${e.track}&customerRequestId=${e.customId}`,i=new WebSocket(`${null!==(t=e.customWebSocketUrl)&&void 0!==t?t:a.WEBSOCKET_BASE_URL}${r}`);return await async function(e){if(await new Promise((t=>{const o=setInterval((()=>{[3,1].includes(e.readyState)&&(clearInterval(o),t())}),5)})),3===e.readyState)throw new Error("Cannot connect to server")}(i),i},t.disconnectFromWebSocket=function(e){var t;[2,3].includes(e.readyState)||null===(t=e.close)||void 0===t||t.call(e)}},553:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SEND_FRAMES_INTERVAL_MS=t.API_GATEWAY_URL=t.WEBSOCKET_BASE_URL=void 0,t.WEBSOCKET_BASE_URL="ws://santoid-liveness-w4ynos5dlq-ue.a.run.app/api/v1/liveness/ws",t.API_GATEWAY_URL="https://api.santoid.com.br/api/v1/service-account/refresh-token",t.SEND_FRAMES_INTERVAL_MS=100},307:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0})}},t={},o=function o(n){var a=t[n];if(void 0!==a)return a.exports;var r=t[n]={exports:{}};return e[n].call(r.exports,r,r.exports,o),r.exports}(401);return o.default})()));
1
+ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("SantoiDSDK",[],t):"object"==typeof exports?exports.SantoiDSDK=t():e.SantoiDSDK=t()}(this,(()=>(()=>{"use strict";var e={401:function(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var a=Object.getOwnPropertyDescriptor(t,o);a&&!("get"in a?!t.__esModule:a.writable||a.configurable)||(a={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,a)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),a=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),t.livenessDetection=void 0;const r=o(553),i=o(793),c=o(692);async function l(e){var t,o,n;let a,l,s,d=!1,u=!1,v=!1,p=!0;async function f(e,t,o){var n;o&&clearInterval(o),t&&(0,c.disconnectFromWebSocket)(t),a&&a.stopGetNextFrame(),!v&&await(null===(n=e.endCallback)||void 0===n?void 0:n.call(e)),v=!0,d=!0}try{return s=await(0,c.connectToWebSocket)(e),await(null===(t=e.nextStepCallback)||void 0===t?void 0:t.call(e,"front")),await(null===(o=e.frontCallback)||void 0===o?void 0:o.call(e)),e.getNextFrame||a||(a=await(0,i.builtInGetNextFrame)()),l=setInterval((async()=>{try{if(p){let t;t=e.getNextFrame?await e.getNextFrame():await(null==a?void 0:a.getNextFrame()),t&&(null==s||s.send(t),p=!1)}}catch(t){await f(e,s,l)}}),r.SEND_FRAMES_INTERVAL_MS),s.addEventListener("message",(async t=>{var o;const n=await async function(e,t){var o,n,a;const r=t.data;let i;try{i=JSON.parse(r)}catch(e){console.error("Cannot parse API message",e)}return(null==i?void 0:i.next_step)&&!i.error&&(await(null===(o=e.nextStepCallback)||void 0===o?void 0:o.call(e,i.next_step)),await(null===(n=e[`${i.next_step}Callback`])||void 0===n?void 0:n.call(e))),(null==i?void 0:i.error)&&await(null===(a=e.errorCallback)||void 0===a?void 0:a.call(e,{code:"wrong-position"})),i}(e,t);n&&(p=!!(null==n?void 0:n.can_send_next_bytes)),(null==n?void 0:n.success)&&(u=!0,await(null===(o=e.successCallback)||void 0===o?void 0:o.call(e)),await f(e,s,l))})),s.addEventListener("error",(async()=>{var t;!u&&(null===(t=e.errorCallback)||void 0===t||t.call(e,{code:"internal-error"})),await f(e,s,l)})),s.addEventListener("close",(async()=>{var t;d||(!u&&(null===(t=e.errorCallback)||void 0===t||t.call(e,{code:"internal-error"})),await f(e,s,l))})),{stopLivenessDetection:async()=>{await f(e,s,l)},videoStream:null==a?void 0:a.videoStream}}catch(t){throw!u&&(null===(n=e.errorCallback)||void 0===n||n.call(e,{code:"internal-error"})),await f(e,s,l),t}}a(o(722),t),t.livenessDetection=l;class s{}s.livenessDetection=l,t.default=s},793:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.builtInGetNextFrame=void 0,t.builtInGetNextFrame=async function(){let e,t,o,n;return e&&t&&o||(e=await navigator.mediaDevices.getUserMedia({video:!0}),t=document.createElement("video"),t.setAttribute("autoplay","true"),t.style.transform="scale(-1, 1)",t.style.position="absolute",t.style.left="99999px",document.body.appendChild(t),t.srcObject=e,o=document.createElement("canvas"),n=o.getContext("2d")),{getNextFrame:async function(){if(o&&t)return o.width=t.videoWidth,o.height=t.videoHeight,null==n||n.drawImage(t,0,0,o.width,o.height),await new Promise(((e,t)=>{o?o.toBlob((t=>{e(t)})):e(null)}));throw new Error("Cannot found video element")},stopGetNextFrame:function(){t&&(document.body.removeChild(t),t=void 0),o&&(o=void 0),n&&(n=void 0),null==e||e.getTracks().forEach((e=>{e.stop()})),e=void 0},videoStream:e}}},268:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.decodeJwt=void 0,t.decodeJwt=function(e){const t=e.split(".")[1].replace(/-/g,"+").replace(/_/g,"/"),o=decodeURIComponent(window.atob(t).split("").map((e=>"%"+("00"+e.charCodeAt(0).toString(16)).slice(-2))).join(""));return JSON.parse(o)}},722:function(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var a=Object.getOwnPropertyDescriptor(t,o);a&&!("get"in a?!t.__esModule:a.writable||a.configurable)||(a={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,a)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),a=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),a(o(307),t)},692:(e,t,o)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.disconnectFromWebSocket=t.connectToWebSocket=void 0;const n=o(268),a=o(553);t.connectToWebSocket=async function(e){var t;const o=(0,n.decodeJwt)(e.token),r=`?x_endpoint_api_userinfo=${e.token}&domain=${o.claims.domain}&track=${e.track}&customerRequestId=${e.customId}`,i=new WebSocket(`${null!==(t=e.customWebSocketUrl)&&void 0!==t?t:a.WEBSOCKET_BASE_URL}${r}`);return await async function(e){if(await new Promise((t=>{const o=setInterval((()=>{[3,1].includes(e.readyState)&&(clearInterval(o),t())}),5)})),3===e.readyState)throw new Error("Cannot connect to server")}(i),i},t.disconnectFromWebSocket=function(e){var t;[2,3].includes(e.readyState)||null===(t=e.close)||void 0===t||t.call(e)}},553:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SEND_FRAMES_INTERVAL_MS=t.API_GATEWAY_URL=t.WEBSOCKET_BASE_URL=void 0,t.WEBSOCKET_BASE_URL="wss://santoid-liveness-w4ynos5dlq-ue.a.run.app/api/v1/liveness/ws",t.API_GATEWAY_URL="https://api.santoid.com.br/api/v1/service-account/refresh-token",t.SEND_FRAMES_INTERVAL_MS=100},307:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0})}},t={},o=function o(n){var a=t[n];if(void 0!==a)return a.exports;var r=t[n]={exports:{}};return e[n].call(r.exports,r,r.exports,o),r.exports}(401);return o.default})()));
@@ -44,6 +44,7 @@ async function livenessDetection(options) {
44
44
  let builtInGetNextFrameReturn;
45
45
  let validationSuccess = false;
46
46
  let endCalled = false;
47
+ let canSendNextBytes = true;
47
48
  async function stopLivenessDetection(options, websocket, intervalKey) {
48
49
  var _a;
49
50
  if (intervalKey) {
@@ -65,13 +66,12 @@ async function livenessDetection(options) {
65
66
  websocket = await (0, websocket_1.connectToWebSocket)(options);
66
67
  await ((_a = options.nextStepCallback) === null || _a === void 0 ? void 0 : _a.call(options, 'front'));
67
68
  await ((_b = options.frontCallback) === null || _b === void 0 ? void 0 : _b.call(options));
68
- let lastMessage;
69
69
  if (!options.getNextFrame && !builtInGetNextFrameReturn) {
70
70
  builtInGetNextFrameReturn = await (0, getNextFrame_1.builtInGetNextFrame)();
71
71
  }
72
72
  sendFramesIntervalKey = setInterval(async () => {
73
73
  try {
74
- if (lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.can_send_next_bytes) {
74
+ if (canSendNextBytes) {
75
75
  let bytes;
76
76
  if (options.getNextFrame) {
77
77
  bytes = await options.getNextFrame();
@@ -81,6 +81,7 @@ async function livenessDetection(options) {
81
81
  }
82
82
  if (bytes) {
83
83
  websocket === null || websocket === void 0 ? void 0 : websocket.send(bytes);
84
+ canSendNextBytes = false;
84
85
  }
85
86
  }
86
87
  }
@@ -92,7 +93,7 @@ async function livenessDetection(options) {
92
93
  var _a;
93
94
  const parsedMessage = await onWebSocketMessage(options, event);
94
95
  if (parsedMessage) {
95
- lastMessage = parsedMessage;
96
+ canSendNextBytes = !!(parsedMessage === null || parsedMessage === void 0 ? void 0 : parsedMessage.can_send_next_bytes);
96
97
  }
97
98
  if (parsedMessage === null || parsedMessage === void 0 ? void 0 : parsedMessage.success) {
98
99
  validationSuccess = true;
@@ -112,7 +113,6 @@ async function livenessDetection(options) {
112
113
  await stopLivenessDetection(options, websocket, sendFramesIntervalKey);
113
114
  }
114
115
  });
115
- lastMessage = { can_send_next_bytes: true };
116
116
  return {
117
117
  stopLivenessDetection: async () => { await stopLivenessDetection(options, websocket, sendFramesIntervalKey); },
118
118
  videoStream: builtInGetNextFrameReturn === null || builtInGetNextFrameReturn === void 0 ? void 0 : builtInGetNextFrameReturn.videoStream,
@@ -5,12 +5,12 @@ async function builtInGetNextFrame() {
5
5
  let videoStream;
6
6
  let videoElement;
7
7
  let canvasElement;
8
+ let canvasContext;
8
9
  async function getNextFrame() {
9
10
  if (canvasElement && videoElement) {
10
- const ctx = canvasElement.getContext('2d');
11
11
  canvasElement.width = videoElement.videoWidth;
12
12
  canvasElement.height = videoElement.videoHeight;
13
- ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(videoElement, 0, 0, canvasElement.width, canvasElement.height);
13
+ canvasContext === null || canvasContext === void 0 ? void 0 : canvasContext.drawImage(videoElement, 0, 0, canvasElement.width, canvasElement.height);
14
14
  return await new Promise((resolve, reject) => {
15
15
  if (!canvasElement) {
16
16
  resolve(null);
@@ -33,6 +33,9 @@ async function builtInGetNextFrame() {
33
33
  if (canvasElement) {
34
34
  canvasElement = undefined;
35
35
  }
36
+ if (canvasContext) {
37
+ canvasContext = undefined;
38
+ }
36
39
  videoStream === null || videoStream === void 0 ? void 0 : videoStream.getTracks().forEach(track => { track.stop(); });
37
40
  videoStream = undefined;
38
41
  }
@@ -40,11 +43,13 @@ async function builtInGetNextFrame() {
40
43
  videoStream = await navigator.mediaDevices.getUserMedia({ video: true });
41
44
  videoElement = document.createElement('video');
42
45
  videoElement.setAttribute('autoplay', 'true');
46
+ videoElement.style.transform = 'scale(-1, 1)';
43
47
  videoElement.style.position = 'absolute';
44
48
  videoElement.style.left = '99999px';
45
49
  document.body.appendChild(videoElement);
46
50
  videoElement.srcObject = videoStream;
47
51
  canvasElement = document.createElement('canvas');
52
+ canvasContext = canvasElement.getContext('2d');
48
53
  }
49
54
  return {
50
55
  getNextFrame,
@@ -27,6 +27,7 @@ async function livenessDetection(options) {
27
27
  let websocketClosedBySDK = false;
28
28
  let validationSuccess = false;
29
29
  let endCalled = false;
30
+ let canSendNextBytes = true;
30
31
  async function stopLivenessDetection(options, websocket, intervalKey) {
31
32
  var _a;
32
33
  if (intervalKey) {
@@ -45,13 +46,13 @@ async function livenessDetection(options) {
45
46
  websocket = await (0, websocket_1.connectToWebSocket)(options);
46
47
  await ((_a = options.nextStepCallback) === null || _a === void 0 ? void 0 : _a.call(options, 'front'));
47
48
  await ((_b = options.frontCallback) === null || _b === void 0 ? void 0 : _b.call(options));
48
- let lastMessage;
49
49
  sendFramesIntervalKey = setInterval(async () => {
50
50
  try {
51
- if (lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.can_send_next_bytes) {
51
+ if (canSendNextBytes) {
52
52
  const bytes = await options.getNextFrame();
53
53
  if (bytes) {
54
54
  websocket === null || websocket === void 0 ? void 0 : websocket.send(bytes);
55
+ canSendNextBytes = false;
55
56
  }
56
57
  }
57
58
  }
@@ -63,7 +64,7 @@ async function livenessDetection(options) {
63
64
  var _a;
64
65
  const parsedMessage = await onWebSocketMessage(options, { data: Buffer.from(data).toString() });
65
66
  if (parsedMessage) {
66
- lastMessage = parsedMessage;
67
+ canSendNextBytes = !!(parsedMessage === null || parsedMessage === void 0 ? void 0 : parsedMessage.can_send_next_bytes);
67
68
  }
68
69
  if (parsedMessage === null || parsedMessage === void 0 ? void 0 : parsedMessage.success) {
69
70
  validationSuccess = true;
@@ -83,7 +84,6 @@ async function livenessDetection(options) {
83
84
  await stopLivenessDetection(options, websocket, sendFramesIntervalKey);
84
85
  }
85
86
  });
86
- lastMessage = { can_send_next_bytes: true };
87
87
  return {
88
88
  stopLivenessDetection: async () => { await stopLivenessDetection(options, websocket, sendFramesIntervalKey); },
89
89
  };
@@ -1,3 +1,3 @@
1
- export declare const WEBSOCKET_BASE_URL = "ws://santoid-liveness-w4ynos5dlq-ue.a.run.app/api/v1/liveness/ws";
1
+ export declare const WEBSOCKET_BASE_URL = "wss://santoid-liveness-w4ynos5dlq-ue.a.run.app/api/v1/liveness/ws";
2
2
  export declare const API_GATEWAY_URL = "https://api.santoid.com.br/api/v1/service-account/refresh-token";
3
3
  export declare const SEND_FRAMES_INTERVAL_MS = 100;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SEND_FRAMES_INTERVAL_MS = exports.API_GATEWAY_URL = exports.WEBSOCKET_BASE_URL = void 0;
4
- exports.WEBSOCKET_BASE_URL = 'ws://santoid-liveness-w4ynos5dlq-ue.a.run.app/api/v1/liveness/ws';
4
+ exports.WEBSOCKET_BASE_URL = 'wss://santoid-liveness-w4ynos5dlq-ue.a.run.app/api/v1/liveness/ws';
5
5
  exports.API_GATEWAY_URL = 'https://api.santoid.com.br/api/v1/service-account/refresh-token';
6
6
  exports.SEND_FRAMES_INTERVAL_MS = 100;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "santoid-sdk",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "",
5
5
  "main": "dist/esm/liveness/index.js",
6
6
  "types": "dist/esm/liveness/index.d.ts",
@@ -34,6 +34,7 @@ export async function livenessDetection (options: TWebSDKOptions) {
34
34
  let builtInGetNextFrameReturn: builtInGetNextFrameReturn | undefined
35
35
  let validationSuccess = false
36
36
  let endCalled = false
37
+ let canSendNextBytes = true
37
38
 
38
39
  async function stopLivenessDetection (options: TWebSDKOptions, websocket?: WebSocket, intervalKey?: any) {
39
40
  if (intervalKey) {
@@ -63,15 +64,13 @@ export async function livenessDetection (options: TWebSDKOptions) {
63
64
  await options.nextStepCallback?.('front')
64
65
  await options.frontCallback?.()
65
66
 
66
- let lastMessage: IWebSocketMessage | undefined
67
-
68
67
  if (!options.getNextFrame && !builtInGetNextFrameReturn) {
69
68
  builtInGetNextFrameReturn = await builtInGetNextFrame()
70
69
  }
71
70
 
72
71
  sendFramesIntervalKey = setInterval(async () => {
73
72
  try {
74
- if (lastMessage?.can_send_next_bytes) {
73
+ if (canSendNextBytes) {
75
74
  let bytes
76
75
 
77
76
  if (options.getNextFrame) {
@@ -82,6 +81,7 @@ export async function livenessDetection (options: TWebSDKOptions) {
82
81
 
83
82
  if (bytes) {
84
83
  websocket?.send(bytes)
84
+ canSendNextBytes = false
85
85
  }
86
86
  }
87
87
  } catch (err) {
@@ -93,7 +93,7 @@ export async function livenessDetection (options: TWebSDKOptions) {
93
93
  const parsedMessage = await onWebSocketMessage(options, event)
94
94
 
95
95
  if (parsedMessage) {
96
- lastMessage = parsedMessage
96
+ canSendNextBytes = !!parsedMessage?.can_send_next_bytes
97
97
  }
98
98
 
99
99
  if (parsedMessage?.success) {
@@ -115,8 +115,6 @@ export async function livenessDetection (options: TWebSDKOptions) {
115
115
  }
116
116
  })
117
117
 
118
- lastMessage = { can_send_next_bytes: true }
119
-
120
118
  return {
121
119
  stopLivenessDetection: async () => { await stopLivenessDetection(options, websocket, sendFramesIntervalKey) },
122
120
  videoStream: builtInGetNextFrameReturn?.videoStream,
@@ -8,15 +8,14 @@ export async function builtInGetNextFrame (): Promise<builtInGetNextFrameReturn>
8
8
  let videoStream: MediaStream | undefined
9
9
  let videoElement: HTMLVideoElement | undefined
10
10
  let canvasElement: HTMLCanvasElement | undefined
11
+ let canvasContext: CanvasRenderingContext2D | null | undefined
11
12
 
12
13
  async function getNextFrame (): Promise<Blob | null> {
13
14
  if (canvasElement && videoElement) {
14
- const ctx = canvasElement.getContext('2d')
15
-
16
15
  canvasElement.width = videoElement.videoWidth
17
16
  canvasElement.height = videoElement.videoHeight
18
17
 
19
- ctx?.drawImage(videoElement, 0, 0, canvasElement.width, canvasElement.height)
18
+ canvasContext?.drawImage(videoElement, 0, 0, canvasElement.width, canvasElement.height)
20
19
 
21
20
  return await new Promise((resolve, reject) => {
22
21
  if (!canvasElement) {
@@ -43,6 +42,10 @@ export async function builtInGetNextFrame (): Promise<builtInGetNextFrameReturn>
43
42
  canvasElement = undefined
44
43
  }
45
44
 
45
+ if (canvasContext) {
46
+ canvasContext = undefined
47
+ }
48
+
46
49
  videoStream?.getTracks().forEach(track => { track.stop() })
47
50
  videoStream = undefined
48
51
  }
@@ -53,6 +56,7 @@ export async function builtInGetNextFrame (): Promise<builtInGetNextFrameReturn>
53
56
  videoElement = document.createElement('video')
54
57
  videoElement.setAttribute('autoplay', 'true')
55
58
 
59
+ videoElement.style.transform = 'scale(-1, 1)'
56
60
  videoElement.style.position = 'absolute'
57
61
  videoElement.style.left = '99999px'
58
62
 
@@ -61,6 +65,7 @@ export async function builtInGetNextFrame (): Promise<builtInGetNextFrameReturn>
61
65
  videoElement.srcObject = videoStream
62
66
 
63
67
  canvasElement = document.createElement('canvas')
68
+ canvasContext = canvasElement.getContext('2d')
64
69
  }
65
70
 
66
71
  return {
@@ -31,6 +31,7 @@ export async function livenessDetection (options: TNodeSDKOptions) {
31
31
  let websocketClosedBySDK = false
32
32
  let validationSuccess = false
33
33
  let endCalled = false
34
+ let canSendNextBytes = true
34
35
 
35
36
  async function stopLivenessDetection (options: TNodeSDKOptions, websocket?: WebSocket, intervalKey?: any) {
36
37
  if (intervalKey) {
@@ -56,15 +57,14 @@ export async function livenessDetection (options: TNodeSDKOptions) {
56
57
  await options.nextStepCallback?.('front')
57
58
  await options.frontCallback?.()
58
59
 
59
- let lastMessage: IWebSocketMessage | undefined
60
-
61
60
  sendFramesIntervalKey = setInterval(async () => {
62
61
  try {
63
- if (lastMessage?.can_send_next_bytes) {
62
+ if (canSendNextBytes) {
64
63
  const bytes = await options.getNextFrame()
65
64
 
66
65
  if (bytes) {
67
66
  websocket?.send(bytes)
67
+ canSendNextBytes = false
68
68
  }
69
69
  }
70
70
  } catch (err) {
@@ -76,7 +76,7 @@ export async function livenessDetection (options: TNodeSDKOptions) {
76
76
  const parsedMessage = await onWebSocketMessage(options, { data: Buffer.from(data).toString() })
77
77
 
78
78
  if (parsedMessage) {
79
- lastMessage = parsedMessage
79
+ canSendNextBytes = !!parsedMessage?.can_send_next_bytes
80
80
  }
81
81
 
82
82
  if (parsedMessage?.success) {
@@ -98,8 +98,6 @@ export async function livenessDetection (options: TNodeSDKOptions) {
98
98
  }
99
99
  })
100
100
 
101
- lastMessage = { can_send_next_bytes: true }
102
-
103
101
  return {
104
102
  stopLivenessDetection: async () => { await stopLivenessDetection(options, websocket, sendFramesIntervalKey) },
105
103
  }
@@ -1,3 +1,3 @@
1
- export const WEBSOCKET_BASE_URL = 'ws://santoid-liveness-w4ynos5dlq-ue.a.run.app/api/v1/liveness/ws'
1
+ export const WEBSOCKET_BASE_URL = 'wss://santoid-liveness-w4ynos5dlq-ue.a.run.app/api/v1/liveness/ws'
2
2
  export const API_GATEWAY_URL = 'https://api.santoid.com.br/api/v1/service-account/refresh-token'
3
3
  export const SEND_FRAMES_INTERVAL_MS = 100