@jaak.ai/stamps 1.0.0-beta.1

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.
Files changed (122) hide show
  1. package/README.md +385 -0
  2. package/dist/cjs/document-detector_19.cjs.entry.js +8540 -0
  3. package/dist/cjs/index-5e4e5e7d.js +1685 -0
  4. package/dist/cjs/index.cjs.js +2 -0
  5. package/dist/cjs/loader.cjs.js +22 -0
  6. package/dist/cjs/mb-tooltip.cjs.entry.js +26 -0
  7. package/dist/cjs/stamps.cjs.js +23 -0
  8. package/dist/collection/collection-manifest.json +31 -0
  9. package/dist/collection/components/document-detector/document-detector.css +154 -0
  10. package/dist/collection/components/document-detector/document-detector.js +416 -0
  11. package/dist/collection/components/shared/mb-api-process-status/mb-api-process-status.css +360 -0
  12. package/dist/collection/components/shared/mb-api-process-status/mb-api-process-status.js +124 -0
  13. package/dist/collection/components/shared/mb-button/mb-button.css +95 -0
  14. package/dist/collection/components/shared/mb-button/mb-button.js +201 -0
  15. package/dist/collection/components/shared/mb-button-classic/mb-button-classic.css +100 -0
  16. package/dist/collection/components/shared/mb-button-classic/mb-button-classic.js +130 -0
  17. package/dist/collection/components/shared/mb-camera-experience/mb-camera-experience.css +740 -0
  18. package/dist/collection/components/shared/mb-camera-experience/mb-camera-experience.js +827 -0
  19. package/dist/collection/components/shared/mb-camera-experience/mb-camera-experience.utils.js +55 -0
  20. package/dist/collection/components/shared/mb-camera-selection/mb-camera-selection.css +124 -0
  21. package/dist/collection/components/shared/mb-camera-selection/mb-camera-selection.js +194 -0
  22. package/dist/collection/components/shared/mb-camera-toolbar/mb-camera-toolbar.css +80 -0
  23. package/dist/collection/components/shared/mb-camera-toolbar/mb-camera-toolbar.js +275 -0
  24. package/dist/collection/components/shared/mb-completed/mb-completed.css +17 -0
  25. package/dist/collection/components/shared/mb-completed/mb-completed.js +48 -0
  26. package/dist/collection/components/shared/mb-component/mb-component.css +321 -0
  27. package/dist/collection/components/shared/mb-component/mb-component.js +2269 -0
  28. package/dist/collection/components/shared/mb-component/mb-component.utils.js +14 -0
  29. package/dist/collection/components/shared/mb-container/mb-container.css +7 -0
  30. package/dist/collection/components/shared/mb-container/mb-container.js +23 -0
  31. package/dist/collection/components/shared/mb-feedback/mb-feedback.css +36 -0
  32. package/dist/collection/components/shared/mb-feedback/mb-feedback.js +91 -0
  33. package/dist/collection/components/shared/mb-feedback/mb-feedback.utils.js +11 -0
  34. package/dist/collection/components/shared/mb-help/mb-help.css +191 -0
  35. package/dist/collection/components/shared/mb-help/mb-help.js +409 -0
  36. package/dist/collection/components/shared/mb-help/mb-help.model.js +5 -0
  37. package/dist/collection/components/shared/mb-image-box/mb-image-box.css +78 -0
  38. package/dist/collection/components/shared/mb-image-box/mb-image-box.js +150 -0
  39. package/dist/collection/components/shared/mb-modal/mb-modal.css +106 -0
  40. package/dist/collection/components/shared/mb-modal/mb-modal.js +239 -0
  41. package/dist/collection/components/shared/mb-overlay/mb-overlay.css +46 -0
  42. package/dist/collection/components/shared/mb-overlay/mb-overlay.js +76 -0
  43. package/dist/collection/components/shared/mb-progress-tracker/mb-progress-tracker.css +24 -0
  44. package/dist/collection/components/shared/mb-progress-tracker/mb-progress-tracker.js +80 -0
  45. package/dist/collection/components/shared/mb-screen/mb-screen.css +19 -0
  46. package/dist/collection/components/shared/mb-screen/mb-screen.js +48 -0
  47. package/dist/collection/components/shared/mb-spinner/mb-spinner.css +30 -0
  48. package/dist/collection/components/shared/mb-spinner/mb-spinner.js +67 -0
  49. package/dist/collection/components/shared/mb-tooltip/mb-tooltip.css +62 -0
  50. package/dist/collection/components/shared/mb-tooltip/mb-tooltip.js +150 -0
  51. package/dist/collection/components/shared/mb-tooltip-advanced/mb-tooltip-advanced.css +91 -0
  52. package/dist/collection/components/shared/mb-tooltip-advanced/mb-tooltip-advanced.js +96 -0
  53. package/dist/collection/index.js +1 -0
  54. package/dist/collection/utils/data-structures.js +189 -0
  55. package/dist/collection/utils/device.helpers.js +37 -0
  56. package/dist/collection/utils/error-structures.js +47 -0
  57. package/dist/collection/utils/generic.helpers.js +82 -0
  58. package/dist/collection/utils/sdk.service.js +943 -0
  59. package/dist/collection/utils/state-lifter.js +3 -0
  60. package/dist/collection/utils/status.document-detector.js +15 -0
  61. package/dist/collection/utils/translation.service.js +97 -0
  62. package/dist/esm/document-detector_19.entry.js +8518 -0
  63. package/dist/esm/index-dc740acb.js +1656 -0
  64. package/dist/esm/index.js +1 -0
  65. package/dist/esm/loader.js +18 -0
  66. package/dist/esm/mb-tooltip.entry.js +22 -0
  67. package/dist/esm/polyfills/core-js.js +11 -0
  68. package/dist/esm/polyfills/css-shim.js +1 -0
  69. package/dist/esm/polyfills/dom.js +79 -0
  70. package/dist/esm/polyfills/es5-html-element.js +1 -0
  71. package/dist/esm/polyfills/index.js +34 -0
  72. package/dist/esm/polyfills/system.js +6 -0
  73. package/dist/esm/stamps.js +18 -0
  74. package/dist/index.cjs.js +1 -0
  75. package/dist/index.js +1 -0
  76. package/dist/stamps/index.esm.js +0 -0
  77. package/dist/stamps/p-66d9fb33.entry.js +9 -0
  78. package/dist/stamps/p-7f07a434.js +2 -0
  79. package/dist/stamps/p-ec3f5972.entry.js +1 -0
  80. package/dist/stamps/stamps.esm.js +1 -0
  81. package/dist/types/components/document-detector/document-detector.d.ts +86 -0
  82. package/dist/types/components/shared/mb-api-process-status/mb-api-process-status.d.ts +30 -0
  83. package/dist/types/components/shared/mb-button/mb-button.d.ts +41 -0
  84. package/dist/types/components/shared/mb-button-classic/mb-button-classic.d.ts +27 -0
  85. package/dist/types/components/shared/mb-camera-experience/mb-camera-experience.d.ts +141 -0
  86. package/dist/types/components/shared/mb-camera-experience/mb-camera-experience.utils.d.ts +3 -0
  87. package/dist/types/components/shared/mb-camera-selection/mb-camera-selection.d.ts +33 -0
  88. package/dist/types/components/shared/mb-camera-toolbar/mb-camera-toolbar.d.ts +54 -0
  89. package/dist/types/components/shared/mb-completed/mb-completed.d.ts +12 -0
  90. package/dist/types/components/shared/mb-component/mb-component.d.ts +308 -0
  91. package/dist/types/components/shared/mb-component/mb-component.utils.d.ts +3 -0
  92. package/dist/types/components/shared/mb-container/mb-container.d.ts +8 -0
  93. package/dist/types/components/shared/mb-feedback/mb-feedback.d.ts +19 -0
  94. package/dist/types/components/shared/mb-feedback/mb-feedback.utils.d.ts +2 -0
  95. package/dist/types/components/shared/mb-help/mb-help.d.ts +66 -0
  96. package/dist/types/components/shared/mb-help/mb-help.model.d.ts +9 -0
  97. package/dist/types/components/shared/mb-image-box/mb-image-box.d.ts +35 -0
  98. package/dist/types/components/shared/mb-modal/mb-modal.d.ts +53 -0
  99. package/dist/types/components/shared/mb-overlay/mb-overlay.d.ts +17 -0
  100. package/dist/types/components/shared/mb-progress-tracker/mb-progress-tracker.d.ts +19 -0
  101. package/dist/types/components/shared/mb-screen/mb-screen.d.ts +12 -0
  102. package/dist/types/components/shared/mb-spinner/mb-spinner.d.ts +16 -0
  103. package/dist/types/components/shared/mb-tooltip/mb-tooltip.d.ts +10 -0
  104. package/dist/types/components/shared/mb-tooltip-advanced/mb-tooltip-advanced.d.ts +7 -0
  105. package/dist/types/components.d.ts +1382 -0
  106. package/dist/types/index.d.ts +1 -0
  107. package/dist/types/stencil-public-runtime.d.ts +1637 -0
  108. package/dist/types/utils/data-structures.d.ts +264 -0
  109. package/dist/types/utils/device.helpers.d.ts +7 -0
  110. package/dist/types/utils/error-structures.d.ts +44 -0
  111. package/dist/types/utils/generic.helpers.d.ts +21 -0
  112. package/dist/types/utils/sdk.service.d.ts +52 -0
  113. package/dist/types/utils/state-lifter.d.ts +3 -0
  114. package/dist/types/utils/status.document-detector.d.ts +14 -0
  115. package/dist/types/utils/translation.service.d.ts +77 -0
  116. package/loader/cdn.js +3 -0
  117. package/loader/index.cjs.js +3 -0
  118. package/loader/index.d.ts +21 -0
  119. package/loader/index.es2017.js +3 -0
  120. package/loader/index.js +4 -0
  121. package/loader/package.json +11 -0
  122. package/package.json +63 -0
@@ -0,0 +1,943 @@
1
+ import * as BlinkIDSDK from "@microblink/blinkid-in-browser-sdk";
2
+ import { AvailableRecognizers, CameraExperience, EventReady, ImageRecognitionType, RecognitionStatus, SDKError, } from "./data-structures";
3
+ import * as ErrorTypes from "./error-structures";
4
+ import { globalState } from "./state-lifter";
5
+ /**
6
+ * Get the additional processing information from the BlinkIdResult.
7
+ * @param result
8
+ * @returns
9
+ */
10
+ export function getAdditionalProcessingInfo(result) {
11
+ if ("scanningFirstSideDone" in result) {
12
+ return !result.scanningFirstSideDone
13
+ ? result.frontAdditionalProcessingInfo
14
+ : result.backAdditionalProcessingInfo;
15
+ }
16
+ else {
17
+ return result.additionalProcessingInfo;
18
+ }
19
+ }
20
+ export function getImageAnalysisResult(result) {
21
+ if ("scanningFirstSideDone" in result) {
22
+ return !result.scanningFirstSideDone
23
+ ? result.frontImageAnalysisResult
24
+ : result.backImageAnalysisResult;
25
+ }
26
+ else {
27
+ return result.imageAnalysisResult;
28
+ }
29
+ }
30
+ export const isFirstSideDone = (result) => {
31
+ return "scanningFirstSideDone" in result && result.scanningFirstSideDone;
32
+ };
33
+ export async function getCameraDevices() {
34
+ const devices = await BlinkIDSDK.getCameraDevices();
35
+ const allDevices = devices.frontCameras.concat(devices.backCameras);
36
+ const finalEntries = allDevices.map((el) => {
37
+ return {
38
+ prettyName: el.label,
39
+ details: el,
40
+ };
41
+ });
42
+ return finalEntries;
43
+ }
44
+ export class SdkService {
45
+ constructor() {
46
+ this.cancelInitiatedFromOutside = false;
47
+ this.showOverlay = false;
48
+ this.lastKnownCardRotation = BlinkIDSDK.CardRotation.None;
49
+ this.lastDetectionStatus = BlinkIDSDK.DetectionStatus.Failed;
50
+ this.eventEmitter$ = document.createElement("a");
51
+ }
52
+ delete() {
53
+ this.sdk?.delete();
54
+ }
55
+ async initialize(licenseKey, sdkSettings) {
56
+ const loadSettings = new BlinkIDSDK.WasmSDKLoadSettings(licenseKey);
57
+ loadSettings.allowHelloMessage = sdkSettings.allowHelloMessage;
58
+ loadSettings.engineLocation = sdkSettings.engineLocation;
59
+ loadSettings.workerLocation = await fetch(sdkSettings.workerLocation)
60
+ .then((response) => response.blob())
61
+ .then((blob) => window.URL.createObjectURL(blob));
62
+ loadSettings.blinkIdVariant = sdkSettings.blinkIdVariant;
63
+ if (sdkSettings.wasmType) {
64
+ loadSettings.wasmType = sdkSettings.wasmType;
65
+ }
66
+ return new Promise((resolve) => {
67
+ BlinkIDSDK.loadWasmModule(loadSettings)
68
+ .then((sdk) => {
69
+ this.sdk = sdk;
70
+ this.showOverlay = sdk.showOverlay;
71
+ resolve(new EventReady(this.sdk));
72
+ })
73
+ .catch((error) => {
74
+ resolve(new SDKError(ErrorTypes.componentErrors.sdkLoadFailed, error));
75
+ });
76
+ });
77
+ }
78
+ checkRecognizers(recognizers) {
79
+ if (!recognizers || !recognizers.length) {
80
+ return {
81
+ status: false,
82
+ message: "There are no provided recognizers!",
83
+ };
84
+ }
85
+ for (const recognizer of recognizers) {
86
+ if (!this.isRecognizerAvailable(recognizer)) {
87
+ return {
88
+ status: false,
89
+ message: `Recognizer "${recognizer}" doesn't exist!`,
90
+ };
91
+ }
92
+ if (recognizer === "BlinkIdMultiSideRecognizer" &&
93
+ recognizers.length > 1) {
94
+ return {
95
+ status: false,
96
+ message: 'Recognizer "BlinkIdMultiSideRecognizer" cannot be used in combination with other recognizers!',
97
+ };
98
+ }
99
+ }
100
+ return {
101
+ status: true,
102
+ };
103
+ }
104
+ getDesiredCameraExperience(_recognizers = [], _recognizerOptions = {}) {
105
+ if (_recognizers.indexOf("BlinkIdMultiSideRecognizer") > -1) {
106
+ return CameraExperience.CardMultiSide;
107
+ }
108
+ if (_recognizers.indexOf("BlinkIdSingleSideRecognizer") > -1) {
109
+ return CameraExperience.CardSingleSide;
110
+ }
111
+ return CameraExperience.Barcode;
112
+ }
113
+ async scanFromCamera(configuration, eventCallback) {
114
+ eventCallback({ status: RecognitionStatus.Preparing });
115
+ this.cancelInitiatedFromOutside = false;
116
+ // Prepare terminate mechanism before recognizer and runner instances are created
117
+ this.eventEmitter$.addEventListener("terminate", async () => {
118
+ this.videoRecognizer?.cancelRecognition?.();
119
+ window.setTimeout(() => this.videoRecognizer?.releaseVideoFeed?.(), 1);
120
+ if (recognizerRunner) {
121
+ try {
122
+ await recognizerRunner.delete();
123
+ }
124
+ catch (error) {
125
+ // Psst, this error should not happen.
126
+ }
127
+ }
128
+ for (const recognizer of recognizers) {
129
+ if (!recognizer) {
130
+ continue;
131
+ }
132
+ if (recognizer.recognizer?.objectHandle > -1) {
133
+ recognizer.recognizer.delete?.();
134
+ }
135
+ }
136
+ });
137
+ // Prepare recognizers and runner
138
+ const recognizers = await this.createRecognizers(configuration.recognizers, configuration.recognizerOptions, eventCallback);
139
+ const recognizerRunner = await this.createRecognizerRunner(recognizers);
140
+ if (configuration.pingProxyUrl) {
141
+ await recognizerRunner.setPingProxyUrl(configuration.pingProxyUrl);
142
+ }
143
+ try {
144
+ this.videoRecognizer =
145
+ await BlinkIDSDK.VideoRecognizer.createVideoRecognizerFromCameraStream(configuration.cameraFeed, recognizerRunner, configuration.cameraId);
146
+ eventCallback({ status: RecognitionStatus.Ready });
147
+ await this.videoRecognizer.setVideoRecognitionMode(BlinkIDSDK.VideoRecognitionMode.Recognition);
148
+ const activeRecognizer = recognizers[0]
149
+ .recognizer;
150
+ const recognizerSettings = await activeRecognizer.currentSettings();
151
+ // We do per-frame operations here
152
+ this.videoRecognizer.setOnFrameProcessed((result) => {
153
+ window.setTimeout(() => {
154
+ // detection status callback is triggered before the video frame callback
155
+ // reset it after each frame is done processing
156
+ this.lastDetectionStatus = BlinkIDSDK.DetectionStatus.Failed;
157
+ }, 0);
158
+ const isMultiside = "scanningFirstSideDone" in result;
159
+ const isFrontSuccessFrame = result.processingStatus ===
160
+ BlinkIDSDK.ProcessingStatus.AwaitingOtherSide;
161
+ //We start scanning the second side only after not the success frame
162
+ const isOnSecondSide = isMultiside && result.scanningFirstSideDone && !isFrontSuccessFrame;
163
+ const additionalProcessingInfo = getAdditionalProcessingInfo(result);
164
+ const imageAnalysisResult = getImageAnalysisResult(result);
165
+ const isPassport = result.classInfo.documentType === BlinkIDSDK.DocumentType.PASSPORT;
166
+ // horrible hack to get the passport status to the global state
167
+ globalState.isPassport = isPassport;
168
+ const notDetected = this.lastDetectionStatus === BlinkIDSDK.DetectionStatus.Failed;
169
+ if (imageAnalysisResult.cardRotation) {
170
+ // save last known rotation in case we lose the document
171
+ this.lastKnownCardRotation = imageAnalysisResult.cardRotation;
172
+ }
173
+ // framing
174
+ switch (this.lastDetectionStatus) {
175
+ case BlinkIDSDK.DetectionStatus.CameraTooFar:
176
+ eventCallback({
177
+ status: RecognitionStatus.DetectionStatusCameraTooHigh,
178
+ });
179
+ break;
180
+ case BlinkIDSDK.DetectionStatus.FallbackSuccess:
181
+ eventCallback({
182
+ status: RecognitionStatus.DetectionStatusFallbackSuccess,
183
+ });
184
+ break;
185
+ case BlinkIDSDK.DetectionStatus.DocumentPartiallyVisible:
186
+ eventCallback({ status: RecognitionStatus.DetectionStatusPartial });
187
+ break;
188
+ case BlinkIDSDK.DetectionStatus.CameraAngleTooSteep:
189
+ eventCallback({
190
+ status: RecognitionStatus.DetectionStatusCameraAtAngle,
191
+ });
192
+ break;
193
+ case BlinkIDSDK.DetectionStatus.CameraTooClose:
194
+ eventCallback({
195
+ status: RecognitionStatus.DetectionStatusCameraTooNear,
196
+ });
197
+ break;
198
+ case BlinkIDSDK.DetectionStatus.DocumentTooCloseToCameraEdge:
199
+ eventCallback({
200
+ status: RecognitionStatus.DetectionStatusDocumentTooCloseToEdge,
201
+ });
202
+ break;
203
+ }
204
+ // handle no detection
205
+ if (notDetected) {
206
+ if (!isPassport) {
207
+ eventCallback({
208
+ // this status doesn't seem to do anything
209
+ // the logic is probably handled as a "default" state somewhere else
210
+ status: RecognitionStatus.DetectionStatusFail,
211
+ });
212
+ }
213
+ else {
214
+ // Get the user to scan the passport
215
+ // again, refer to the page relative to the last one scanned
216
+ if (isOnSecondSide) {
217
+ switch (this.lastKnownCardRotation) {
218
+ case BlinkIDSDK.CardRotation.None: {
219
+ eventCallback({
220
+ status: RecognitionStatus.MovePassportUpError,
221
+ });
222
+ break;
223
+ }
224
+ case BlinkIDSDK.CardRotation.Clockwise90: {
225
+ eventCallback({
226
+ status: RecognitionStatus.MovePassportRightError,
227
+ });
228
+ break;
229
+ }
230
+ case BlinkIDSDK.CardRotation.CounterClockwise90: {
231
+ eventCallback({
232
+ status: RecognitionStatus.MovePassportLeftError,
233
+ });
234
+ break;
235
+ }
236
+ case BlinkIDSDK.CardRotation.UpsideDown: {
237
+ eventCallback({
238
+ status: RecognitionStatus.MovePassportDownError,
239
+ });
240
+ break;
241
+ }
242
+ }
243
+ }
244
+ }
245
+ return;
246
+ }
247
+ // handle glare
248
+ if (imageAnalysisResult.glareDetected &&
249
+ recognizerSettings.enableGlareFilter) {
250
+ eventCallback({
251
+ status: RecognitionStatus.GlareDetected,
252
+ });
253
+ return;
254
+ }
255
+ // handle blur
256
+ if (imageAnalysisResult.blurDetected &&
257
+ recognizerSettings.enableBlurFilter) {
258
+ eventCallback({
259
+ status: RecognitionStatus.BlurDetected,
260
+ });
261
+ return;
262
+ }
263
+ // handle face occlusion
264
+ if (additionalProcessingInfo.imageExtractionFailures?.includes(BlinkIDSDK.ImageExtractionType.Face)) {
265
+ eventCallback({
266
+ status: RecognitionStatus.FacePhotoCovered,
267
+ });
268
+ return;
269
+ }
270
+ // first side done - show flip/move. This status triggers only once
271
+ if (isFrontSuccessFrame) {
272
+ if (!isPassport) {
273
+ eventCallback({ status: RecognitionStatus.OnFirstSideResult });
274
+ }
275
+ else {
276
+ // Passport only branch
277
+ switch (this.lastKnownCardRotation) {
278
+ case BlinkIDSDK.CardRotation.None: {
279
+ eventCallback({
280
+ status: RecognitionStatus.MovePassportUp,
281
+ });
282
+ break;
283
+ }
284
+ case BlinkIDSDK.CardRotation.Clockwise90: {
285
+ eventCallback({
286
+ status: RecognitionStatus.MovePassportRight,
287
+ });
288
+ break;
289
+ }
290
+ case BlinkIDSDK.CardRotation.CounterClockwise90: {
291
+ eventCallback({
292
+ status: RecognitionStatus.MovePassportLeft,
293
+ });
294
+ break;
295
+ }
296
+ case BlinkIDSDK.CardRotation.UpsideDown: {
297
+ eventCallback({
298
+ status: RecognitionStatus.MovePassportDown,
299
+ });
300
+ break;
301
+ }
302
+ }
303
+ }
304
+ return;
305
+ }
306
+ // scanning wrong side
307
+ if (result.processingStatus ===
308
+ BlinkIDSDK.ProcessingStatus.ScanningWrongSide) {
309
+ if (isPassport) {
310
+ // Passport only branch
311
+ switch (this.lastKnownCardRotation) {
312
+ case BlinkIDSDK.CardRotation.None: {
313
+ eventCallback({
314
+ status: RecognitionStatus.MovePassportUpError,
315
+ });
316
+ break;
317
+ }
318
+ case BlinkIDSDK.CardRotation.Clockwise90: {
319
+ eventCallback({
320
+ status: RecognitionStatus.MovePassportRightError,
321
+ });
322
+ break;
323
+ }
324
+ case BlinkIDSDK.CardRotation.CounterClockwise90: {
325
+ eventCallback({
326
+ status: RecognitionStatus.MovePassportLeftError,
327
+ });
328
+ break;
329
+ }
330
+ case BlinkIDSDK.CardRotation.UpsideDown: {
331
+ eventCallback({
332
+ status: RecognitionStatus.MovePassportDownError,
333
+ });
334
+ break;
335
+ }
336
+ }
337
+ }
338
+ else {
339
+ // some other document, maybe unclassified?
340
+ eventCallback({
341
+ status: RecognitionStatus.WrongSide,
342
+ });
343
+ }
344
+ return;
345
+ }
346
+ // fallback - success?
347
+ eventCallback({ status: RecognitionStatus.DetectionStatusSuccess });
348
+ });
349
+ //////////////////////////////////////////////////
350
+ // Start recognition
351
+ await this.videoRecognizer
352
+ .startRecognition(async (recognitionState) => {
353
+ this.videoRecognizer.pauseRecognition();
354
+ eventCallback({ status: RecognitionStatus.Processing });
355
+ if (recognitionState !== BlinkIDSDK.RecognizerResultState.Empty) {
356
+ for (const recognizer of recognizers) {
357
+ const results = await recognizer.recognizer.getResult();
358
+ this.recognizerName = recognizer.recognizer.recognizerName;
359
+ if (!results ||
360
+ results.state === BlinkIDSDK.RecognizerResultState.Empty) {
361
+ eventCallback({
362
+ status: RecognitionStatus.EmptyResultState,
363
+ data: {
364
+ initiatedByUser: this.cancelInitiatedFromOutside,
365
+ recognizerName: this.recognizerName,
366
+ },
367
+ });
368
+ }
369
+ else {
370
+ const recognitionResults = {
371
+ recognizer: results,
372
+ recognizerName: this.recognizerName,
373
+ };
374
+ if (configuration.recognizerOptions?.returnSignedJSON) {
375
+ recognitionResults.resultSignedJSON =
376
+ await recognizer.recognizer.toSignedJSON();
377
+ }
378
+ if (results.fullDocumentFrontImage.encodedImage) {
379
+ results.fullDocumentFrontImage.encodedImage = this.base64ArrayBuffer(results.fullDocumentFrontImage.encodedImage);
380
+ }
381
+ if (results.fullDocumentBackImage.encodedImage) {
382
+ results.fullDocumentBackImage.encodedImage = this.base64ArrayBuffer(results.fullDocumentBackImage.encodedImage);
383
+ }
384
+ if (results.signatureImage.encodedImage) {
385
+ results.signatureImage.encodedImage = this.base64ArrayBuffer(results.signatureImage.encodedImage);
386
+ }
387
+ if (results.faceImage.encodedImage) {
388
+ results.faceImage.encodedImage = this.base64ArrayBuffer(results.faceImage.encodedImage);
389
+ }
390
+ let borderlessFront = undefined;
391
+ let borderlessBack = undefined;
392
+ if (results.fullDocumentFrontImage?.encodedImage) {
393
+ let base64Image;
394
+ if (typeof results.fullDocumentFrontImage.encodedImage === 'string') {
395
+ base64Image = results.fullDocumentFrontImage.encodedImage;
396
+ }
397
+ else {
398
+ base64Image = this.base64ArrayBuffer(results.fullDocumentFrontImage.encodedImage);
399
+ }
400
+ if (!base64Image.startsWith('data:image/')) {
401
+ base64Image = 'data:image/jpeg;base64,' + base64Image;
402
+ }
403
+ borderlessFront = await this.cropDocumentFromImage(base64Image, {
404
+ upFactor: 0.1,
405
+ downFactor: 0.1,
406
+ leftFactor: 0.1,
407
+ rightFactor: 0.1
408
+ });
409
+ }
410
+ if (results.fullDocumentBackImage?.encodedImage) {
411
+ let base64Image;
412
+ if (typeof results.fullDocumentBackImage.encodedImage === 'string') {
413
+ base64Image = results.fullDocumentBackImage.encodedImage;
414
+ }
415
+ else {
416
+ base64Image = this.base64ArrayBuffer(results.fullDocumentBackImage.encodedImage);
417
+ }
418
+ if (!base64Image.startsWith('data:image/')) {
419
+ base64Image = 'data:image/jpeg;base64,' + base64Image;
420
+ }
421
+ borderlessBack = await this.cropDocumentFromImage(base64Image, {
422
+ upFactor: 0.1,
423
+ downFactor: 0.1,
424
+ leftFactor: 0.1,
425
+ rightFactor: 0.1
426
+ });
427
+ }
428
+ const scanData = {
429
+ result: {
430
+ status: RecognitionStatus.ScanSuccessful,
431
+ data: {
432
+ type: "RESULTS",
433
+ message: "results-success",
434
+ data: {
435
+ documentData: {
436
+ generalData: {
437
+ type: results.mrz.documentCode,
438
+ nationality: results.nationality.latin,
439
+ name: results.fullName.latin || results.firstName.latin,
440
+ surname: results.fathersName.latin || results.lastName.latin,
441
+ motherSurname: results.mothersName.latin,
442
+ address: results.address.latin,
443
+ expiryPermanent: false,
444
+ birthDate: results.frontViz.dateOfBirth.originalString.latin,
445
+ gender: results.sex.latin,
446
+ documentImage: {
447
+ frontFull: results.fullDocumentFrontImage.encodedImage,
448
+ backFull: results.fullDocumentBackImage.encodedImage,
449
+ front: borderlessFront,
450
+ back: borderlessBack,
451
+ signature: results.signatureImage.encodedImage,
452
+ face: results.faceImage.encodedImage
453
+ }
454
+ },
455
+ mechanicalReadingZone: results.mrz.rawMRZString,
456
+ specificData: [
457
+ {
458
+ label: "curp",
459
+ value: results.personalIdNumber.latin
460
+ },
461
+ {
462
+ label: "electorKey",
463
+ value: results.frontViz.documentAdditionalNumber.latin
464
+ },
465
+ {
466
+ label: "registerYear",
467
+ value: results.frontViz.dateOfIssue.year
468
+ },
469
+ {
470
+ label: "registerMonth",
471
+ value: results.frontViz.dateOfIssue.month
472
+ },
473
+ {
474
+ label: "emissionYear",
475
+ value: results.frontViz.dateOfIssue.year
476
+ },
477
+ {
478
+ label: "identificationOCR",
479
+ value: results.mrz.sanitizedOpt1
480
+ },
481
+ {
482
+ label: "numIdentificationCredential",
483
+ value: results.mrz.documentNumber
484
+ }
485
+ ]
486
+ },
487
+ },
488
+ },
489
+ },
490
+ initiatedByUser: this.cancelInitiatedFromOutside,
491
+ };
492
+ eventCallback({
493
+ status: RecognitionStatus.ScanSuccessful,
494
+ data: scanData,
495
+ });
496
+ break;
497
+ }
498
+ }
499
+ }
500
+ else {
501
+ eventCallback({
502
+ status: RecognitionStatus.EmptyResultState,
503
+ data: {
504
+ initiatedByUser: this.cancelInitiatedFromOutside,
505
+ recognizerName: "",
506
+ },
507
+ });
508
+ }
509
+ window.setTimeout(() => void this.cancelRecognition(), 400);
510
+ }, configuration.recognitionTimeout)
511
+ .then(() => {
512
+ /* Scanning... */
513
+ })
514
+ .catch((error) => {
515
+ throw error;
516
+ });
517
+ }
518
+ catch (error) {
519
+ if (!error.code) {
520
+ eventCallback({ status: RecognitionStatus.UnknownError });
521
+ }
522
+ else {
523
+ switch (error.code) {
524
+ case BlinkIDSDK.ErrorCodes.VIDEO_RECOGNIZER_MEDIA_DEVICES_UNSUPPORTED:
525
+ eventCallback({
526
+ status: RecognitionStatus.NoSupportForMediaDevices,
527
+ });
528
+ break;
529
+ case BlinkIDSDK.ErrorCodes.VIDEO_RECOGNIZER_CAMERA_MISSING:
530
+ eventCallback({ status: RecognitionStatus.CameraNotFound });
531
+ break;
532
+ case BlinkIDSDK.ErrorCodes.VIDEO_RECOGNIZER_CAMERA_NOT_ALLOWED:
533
+ eventCallback({ status: RecognitionStatus.CameraNotAllowed });
534
+ break;
535
+ case BlinkIDSDK.ErrorCodes.VIDEO_RECOGNIZER_CAMERA_IN_USE:
536
+ eventCallback({ status: RecognitionStatus.CameraInUse });
537
+ break;
538
+ default:
539
+ eventCallback({ status: RecognitionStatus.UnableToAccessCamera });
540
+ break;
541
+ }
542
+ }
543
+ console.warn("Error in VideoRecognizer", error.code, error.message);
544
+ void this.cancelRecognition();
545
+ }
546
+ }
547
+ async cropDocumentFromImage(imageBase64, factors) {
548
+ return new Promise((resolve, reject) => {
549
+ const image = new window.Image();
550
+ image.onload = () => {
551
+ const width = image.width;
552
+ const height = image.height;
553
+ const docWidth = width / (1 + factors.leftFactor + factors.rightFactor);
554
+ const docHeight = height / (1 + factors.upFactor + factors.downFactor);
555
+ const offsetX = factors.leftFactor * docWidth;
556
+ const offsetY = factors.upFactor * docHeight;
557
+ const canvas = document.createElement('canvas');
558
+ canvas.width = docWidth;
559
+ canvas.height = docHeight;
560
+ const ctx = canvas.getContext('2d');
561
+ ctx.drawImage(image, offsetX, offsetY, docWidth, docHeight, 0, 0, docWidth, docHeight);
562
+ resolve(canvas.toDataURL().replace(/^data:image\/(png|jpg);base64,/, ""));
563
+ };
564
+ image.onerror = reject;
565
+ image.src = imageBase64;
566
+ });
567
+ }
568
+ base64ArrayBuffer(arrayBuffer) {
569
+ let base64 = "";
570
+ const encodings = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
571
+ const bytes = new Uint8Array(arrayBuffer);
572
+ const byteLength = bytes.byteLength;
573
+ const byteRemainder = byteLength % 3;
574
+ const mainLength = byteLength - byteRemainder;
575
+ let a;
576
+ let b;
577
+ let c;
578
+ let d;
579
+ let chunk;
580
+ // Main loop deals with bytes in chunks of 3
581
+ for (let i = 0; i < mainLength; i = i + 3) {
582
+ // Combine the three bytes into a single integer
583
+ // tslint:disable-next-line:no-bitwise
584
+ chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
585
+ // Use bitmasks to extract 6-bit segments from the triplet
586
+ // tslint:disable-next-line:no-bitwise
587
+ a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
588
+ // tslint:disable-next-line:no-bitwise
589
+ b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12
590
+ // tslint:disable-next-line:no-bitwise
591
+ c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6
592
+ // tslint:disable-next-line:no-bitwise
593
+ d = chunk & 63; // 63 = 2^6 - 1
594
+ // Convert the raw binary segments to the appropriate ASCII encoding
595
+ base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
596
+ }
597
+ // Deal with the remaining bytes and padding
598
+ if (byteRemainder === 1) {
599
+ chunk = bytes[mainLength];
600
+ // tslint:disable-next-line:no-bitwise
601
+ a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2
602
+ // Set the 4 least significant bits to zero
603
+ // tslint:disable-next-line:no-bitwise
604
+ b = (chunk & 3) << 4; // 3 = 2^2 - 1
605
+ base64 += encodings[a] + encodings[b] + "==";
606
+ }
607
+ else if (byteRemainder === 2) {
608
+ // tslint:disable-next-line:no-bitwise
609
+ chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];
610
+ // tslint:disable-next-line:no-bitwise
611
+ a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
612
+ // tslint:disable-next-line:no-bitwise
613
+ b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4
614
+ // Set the 2 least significant bits to zero
615
+ // tslint:disable-next-line:no-bitwise
616
+ c = (chunk & 15) << 2; // 15 = 2^4 - 1
617
+ base64 += encodings[a] + encodings[b] + encodings[c] + "=";
618
+ }
619
+ return base64;
620
+ }
621
+ async flipCamera() {
622
+ await this.videoRecognizer.flipCamera();
623
+ }
624
+ isCameraFlipped() {
625
+ if (!this.videoRecognizer) {
626
+ return false;
627
+ }
628
+ return this.videoRecognizer.isCameraFlipped();
629
+ }
630
+ isScanFromImageAvailable(_recognizers = [], _recognizerOptions = {}) {
631
+ return true;
632
+ }
633
+ getScanFromImageType(_recognizers = [], _recognizerOptions = {}) {
634
+ if (_recognizers.indexOf("BlinkIdMultiSideRecognizer") > -1) {
635
+ return ImageRecognitionType.MultiSide;
636
+ }
637
+ return ImageRecognitionType.SingleSide;
638
+ }
639
+ async scanFromImage(configuration, eventCallback) {
640
+ eventCallback({ status: RecognitionStatus.Preparing });
641
+ const recognizers = await this.createRecognizers(configuration.recognizers, configuration.recognizerOptions, eventCallback);
642
+ const recognizerRunner = await this.createRecognizerRunner(recognizers);
643
+ if (configuration.pingProxyUrl) {
644
+ await recognizerRunner.setPingProxyUrl(configuration.pingProxyUrl);
645
+ }
646
+ const handleTerminate = async () => {
647
+ this.eventEmitter$.removeEventListener("terminate", handleTerminate);
648
+ if (recognizerRunner) {
649
+ try {
650
+ await recognizerRunner.delete();
651
+ }
652
+ catch (error) {
653
+ // Psst, this error should not happen.
654
+ }
655
+ }
656
+ for (const recognizer of recognizers) {
657
+ if (!recognizer) {
658
+ continue;
659
+ }
660
+ if (recognizer.recognizer?.objectHandle > -1) {
661
+ recognizer.recognizer.delete?.();
662
+ }
663
+ }
664
+ this.eventEmitter$.dispatchEvent(new Event("terminate:done"));
665
+ };
666
+ this.eventEmitter$.addEventListener("terminate", handleTerminate);
667
+ // Get image file
668
+ if (!configuration.file ||
669
+ !RegExp(/^image\//).exec(configuration.file.type)) {
670
+ eventCallback({ status: RecognitionStatus.NoImageFileFound });
671
+ window.setTimeout(() => void this.cancelRecognition(), 500);
672
+ return;
673
+ }
674
+ const file = configuration.file;
675
+ const imageElement = new Image();
676
+ imageElement.src = URL.createObjectURL(file);
677
+ await imageElement.decode();
678
+ const imageFrame = BlinkIDSDK.captureFrame(imageElement);
679
+ // Get results
680
+ eventCallback({ status: RecognitionStatus.Processing });
681
+ const processResult = await recognizerRunner.processImage(imageFrame);
682
+ if (processResult !== BlinkIDSDK.RecognizerResultState.Empty) {
683
+ for (const recognizer of recognizers) {
684
+ const results = await recognizer.recognizer.getResult();
685
+ if (!results ||
686
+ results.state === BlinkIDSDK.RecognizerResultState.Empty) {
687
+ eventCallback({
688
+ status: RecognitionStatus.EmptyResultState,
689
+ data: {
690
+ initiatedByUser: this.cancelInitiatedFromOutside,
691
+ recognizerName: recognizer.name,
692
+ },
693
+ });
694
+ }
695
+ else {
696
+ const recognitionResults = {
697
+ recognizer: results,
698
+ recognizerName: recognizer.name,
699
+ };
700
+ if (configuration.recognizerOptions?.returnSignedJSON) {
701
+ recognitionResults.resultSignedJSON =
702
+ await recognizer.recognizer.toSignedJSON();
703
+ }
704
+ eventCallback({
705
+ status: RecognitionStatus.ScanSuccessful,
706
+ data: recognitionResults,
707
+ });
708
+ break;
709
+ }
710
+ }
711
+ }
712
+ else {
713
+ // If necessary, scan the image once again with different settings
714
+ if (configuration.thoroughScan &&
715
+ configuration.recognizers.indexOf("BlinkIdSingleSideRecognizer") > -1) {
716
+ const c = configuration;
717
+ c.thoroughScan = false;
718
+ c.recognizerOptions = c.recognizerOptions || {};
719
+ for (const r of c.recognizers) {
720
+ c.recognizerOptions[r] = c.recognizerOptions[r] || {};
721
+ c.recognizerOptions[r].scanCroppedDocumentImage =
722
+ !!c.recognizerOptions[r].scanCroppedDocumentImage;
723
+ c.recognizerOptions[r].scanCroppedDocumentImage =
724
+ !c.recognizerOptions[r].scanCroppedDocumentImage;
725
+ }
726
+ const eventHandler = (recognitionEvent) => eventCallback(recognitionEvent);
727
+ const handleTerminateDone = () => {
728
+ this.eventEmitter$.removeEventListener("terminate:done", handleTerminateDone);
729
+ this.scanFromImage(configuration, eventHandler);
730
+ };
731
+ this.eventEmitter$.addEventListener("terminate:done", handleTerminateDone);
732
+ window.setTimeout(() => void this.cancelRecognition(), 500);
733
+ return;
734
+ }
735
+ eventCallback({
736
+ status: RecognitionStatus.EmptyResultState,
737
+ data: {
738
+ initiatedByUser: this.cancelInitiatedFromOutside,
739
+ recognizerName: "",
740
+ },
741
+ });
742
+ }
743
+ window.setTimeout(() => void this.cancelRecognition(), 500);
744
+ }
745
+ async scanFromImageMultiSide(configuration, eventCallback) {
746
+ eventCallback({ status: RecognitionStatus.Preparing });
747
+ const recognizers = await this.createRecognizers(configuration.recognizers, configuration.recognizerOptions, eventCallback);
748
+ const recognizerRunner = await this.createRecognizerRunner(recognizers);
749
+ if (configuration.pingProxyUrl) {
750
+ await recognizerRunner.setPingProxyUrl(configuration.pingProxyUrl);
751
+ }
752
+ const handleTerminate = async () => {
753
+ this.eventEmitter$.removeEventListener("terminate", handleTerminate);
754
+ if (recognizerRunner) {
755
+ try {
756
+ await recognizerRunner.delete();
757
+ }
758
+ catch (error) {
759
+ // Psst, this error should not happen.
760
+ }
761
+ }
762
+ for (const recognizer of recognizers) {
763
+ if (!recognizer) {
764
+ continue;
765
+ }
766
+ if (recognizer.recognizer?.objectHandle > -1) {
767
+ recognizer.recognizer.delete?.();
768
+ }
769
+ }
770
+ this.eventEmitter$.dispatchEvent(new Event("terminate:done"));
771
+ };
772
+ this.eventEmitter$.addEventListener("terminate", handleTerminate);
773
+ if (!configuration.firstFile) {
774
+ eventCallback({ status: RecognitionStatus.NoFirstImageFileFound });
775
+ window.setTimeout(() => void this.cancelRecognition(), 500);
776
+ return;
777
+ }
778
+ if (!configuration.secondFile) {
779
+ eventCallback({ status: RecognitionStatus.NoSecondImageFileFound });
780
+ window.setTimeout(() => void this.cancelRecognition(), 500);
781
+ return;
782
+ }
783
+ // Get results
784
+ eventCallback({ status: RecognitionStatus.Processing });
785
+ const imageElement = new Image();
786
+ imageElement.src = URL.createObjectURL(configuration.firstFile);
787
+ await imageElement.decode();
788
+ const firstFrame = BlinkIDSDK.captureFrame(imageElement);
789
+ const firstProcessResult = await recognizerRunner.processImage(firstFrame);
790
+ if (firstProcessResult !== BlinkIDSDK.RecognizerResultState.Empty) {
791
+ const imageElement = new Image();
792
+ imageElement.src = URL.createObjectURL(configuration.secondFile);
793
+ await imageElement.decode();
794
+ const secondFrame = BlinkIDSDK.captureFrame(imageElement);
795
+ const secondProcessResult = await recognizerRunner.processImage(secondFrame);
796
+ if (secondProcessResult !== BlinkIDSDK.RecognizerResultState.Empty) {
797
+ for (const recognizer of recognizers) {
798
+ const results = await recognizer.recognizer.getResult();
799
+ if (!results ||
800
+ results.state === BlinkIDSDK.RecognizerResultState.Empty) {
801
+ eventCallback({
802
+ status: RecognitionStatus.EmptyResultState,
803
+ data: {
804
+ initiatedByUser: this.cancelInitiatedFromOutside,
805
+ recognizerName: recognizer.name,
806
+ },
807
+ });
808
+ }
809
+ else {
810
+ const recognitionResults = {
811
+ recognizer: results,
812
+ recognizerName: recognizer.name,
813
+ };
814
+ if (configuration.recognizerOptions?.returnSignedJSON) {
815
+ recognitionResults.resultSignedJSON =
816
+ await recognizer.recognizer.toSignedJSON();
817
+ }
818
+ eventCallback({
819
+ status: RecognitionStatus.ScanSuccessful,
820
+ data: recognitionResults,
821
+ });
822
+ break;
823
+ }
824
+ }
825
+ }
826
+ else {
827
+ eventCallback({
828
+ status: RecognitionStatus.EmptyResultState,
829
+ data: {
830
+ initiatedByUser: this.cancelInitiatedFromOutside,
831
+ recognizerName: "",
832
+ },
833
+ });
834
+ }
835
+ }
836
+ else {
837
+ // If necessary, scan the image once again with different settings
838
+ if (configuration.thoroughScan &&
839
+ configuration.recognizers.indexOf("BlinkIdMultiSideRecognizer") > -1) {
840
+ const c = configuration;
841
+ c.thoroughScan = false;
842
+ c.recognizerOptions = c.recognizerOptions || {};
843
+ for (const r of c.recognizers) {
844
+ c.recognizerOptions[r] = c.recognizerOptions[r] || {};
845
+ c.recognizerOptions[r].scanCroppedDocumentImage =
846
+ !!c.recognizerOptions[r].scanCroppedDocumentImage;
847
+ c.recognizerOptions[r].scanCroppedDocumentImage =
848
+ !c.recognizerOptions[r].scanCroppedDocumentImage;
849
+ }
850
+ const eventHandler = (recognitionEvent) => eventCallback(recognitionEvent);
851
+ const handleTerminateDone = () => {
852
+ this.eventEmitter$.removeEventListener("terminate:done", handleTerminateDone);
853
+ this.scanFromImageMultiSide(configuration, eventHandler);
854
+ };
855
+ this.eventEmitter$.addEventListener("terminate:done", handleTerminateDone);
856
+ window.setTimeout(() => void this.cancelRecognition(), 500);
857
+ return;
858
+ }
859
+ eventCallback({
860
+ status: RecognitionStatus.EmptyResultState,
861
+ data: {
862
+ initiatedByUser: this.cancelInitiatedFromOutside,
863
+ recognizerName: "",
864
+ },
865
+ });
866
+ }
867
+ window.setTimeout(() => void this.cancelRecognition(), 500);
868
+ }
869
+ async stopRecognition() {
870
+ void (await this.cancelRecognition(true));
871
+ }
872
+ async resumeRecognition() {
873
+ this.videoRecognizer.resumeRecognition(true);
874
+ }
875
+ changeCameraDevice(camera) {
876
+ return new Promise((resolve) => {
877
+ this.videoRecognizer
878
+ .changeCameraDevice(camera)
879
+ .then(() => resolve(true))
880
+ .catch(() => resolve(false));
881
+ });
882
+ }
883
+ getProductIntegrationInfo() {
884
+ return this.sdk.getProductIntegrationInfo();
885
+ }
886
+ //////////////////////////////////////////////////////////////////////////////
887
+ //
888
+ // PRIVATE METHODS
889
+ isRecognizerAvailable(recognizer) {
890
+ return !!AvailableRecognizers[recognizer];
891
+ }
892
+ async createRecognizers(recognizers, recognizerOptions, eventCallback) {
893
+ const pureRecognizers = [];
894
+ for (const recognizer of recognizers) {
895
+ const instance = await BlinkIDSDK[AvailableRecognizers[recognizer]](this.sdk);
896
+ pureRecognizers.push(instance);
897
+ }
898
+ if (recognizerOptions && Object.keys(recognizerOptions).length > 0) {
899
+ for (const recognizer of pureRecognizers) {
900
+ const settings = await recognizer.currentSettings();
901
+ if (!recognizerOptions[recognizer.recognizerName] ||
902
+ Object.keys(recognizerOptions[recognizer.recognizerName]).length < 1) {
903
+ continue;
904
+ }
905
+ for (const [key, value] of Object.entries(recognizerOptions[recognizer.recognizerName])) {
906
+ if (key in settings) {
907
+ settings[key] = value;
908
+ }
909
+ }
910
+ settings.barcodeScanningStartedCallback = () => {
911
+ eventCallback({ status: RecognitionStatus.BarcodeScanningStarted });
912
+ };
913
+ settings.classifierCallback = (supported) => {
914
+ eventCallback({
915
+ status: RecognitionStatus.DocumentClassified,
916
+ data: supported,
917
+ });
918
+ };
919
+ await recognizer.updateSettings(settings);
920
+ }
921
+ }
922
+ const recognizerInstances = [];
923
+ for (let i = 0; i < pureRecognizers.length; ++i) {
924
+ const recognizer = pureRecognizers[i];
925
+ const instance = { name: recognizers[i], recognizer };
926
+ recognizerInstances.push(instance);
927
+ }
928
+ return recognizerInstances;
929
+ }
930
+ async createRecognizerRunner(recognizers) {
931
+ const metadataCallbacks = {
932
+ onQuadDetection: (quad) => {
933
+ this.lastDetectionStatus = quad.detectionStatus;
934
+ },
935
+ };
936
+ const recognizerRunner = await BlinkIDSDK.createRecognizerRunner(this.sdk, recognizers.map((el) => el.recognizer), false, metadataCallbacks);
937
+ return recognizerRunner;
938
+ }
939
+ async cancelRecognition(initiatedFromOutside = false) {
940
+ this.cancelInitiatedFromOutside = initiatedFromOutside;
941
+ this.eventEmitter$.dispatchEvent(new Event("terminate"));
942
+ }
943
+ }