@incodetech/core 2.0.0-alpha.8 → 2.0.0-rc.0

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 (184) hide show
  1. package/dist/Actor-CI32dTbG.d.ts +2 -0
  2. package/dist/BaseWasmProvider-C_DLEI40.esm.js +1118 -0
  3. package/dist/BrowserStorageProvider-CuOW1Er2.esm.js +55 -0
  4. package/dist/BrowserTimerProvider-DhNc_x02.esm.js +22 -0
  5. package/dist/ITimerCapability-C67ZRskg.esm.js +7 -0
  6. package/dist/IpifyProvider-D7jx52AL.esm.js +139 -0
  7. package/dist/MotionSensorProvider-4v7xkqAp.esm.js +254 -0
  8. package/dist/OpenViduRecordingProvider-CMu6XVdc.esm.js +87 -0
  9. package/dist/StateMachine-BCQrZJhf.d.ts +2 -0
  10. package/dist/WasmUtilProvider-j98OJf-S.esm.js +114 -0
  11. package/dist/addressSearch-BpTbTWCa.esm.js +430 -0
  12. package/dist/ae-signature-DDDZmWXj.esm.js +12 -0
  13. package/dist/ae-signature.d.ts +25 -0
  14. package/dist/ae-signature.esm.js +8 -0
  15. package/dist/antifraud.d.ts +57 -0
  16. package/dist/antifraud.esm.js +45 -0
  17. package/dist/antifraudStateMachine-O0TMf6yc.esm.js +39 -0
  18. package/dist/api-CESGtpbH.esm.js +53 -0
  19. package/dist/authentication.d.ts +12 -0
  20. package/dist/authentication.esm.js +25 -0
  21. package/dist/authenticationManager-5M-fKzXx.esm.js +67 -0
  22. package/dist/authenticationManager-C83GNIhl.d.ts +66 -0
  23. package/dist/authenticationStateMachine-BMZqatiF.esm.js +139 -0
  24. package/dist/backCameraStream-DMdMeGk2.esm.js +346 -0
  25. package/dist/browserSimulation-gxD8cSpM.esm.js +20 -0
  26. package/dist/camera-DBSxa6ML.d.ts +4 -0
  27. package/dist/camera-PA2Ljri3.esm.js +22 -0
  28. package/dist/camera.d.ts +15 -0
  29. package/dist/camera.esm.js +5 -0
  30. package/dist/consent.d.ts +398 -0
  31. package/dist/consent.esm.js +79 -0
  32. package/dist/consentStateMachine-CCT-B60O.esm.js +151 -0
  33. package/dist/cpf-PPz2Njto.esm.js +38 -0
  34. package/dist/cpf-ocr.d.ts +204 -0
  35. package/dist/cpf-ocr.esm.js +177 -0
  36. package/dist/cross-document-data-match.d.ts +34 -0
  37. package/dist/cross-document-data-match.esm.js +71 -0
  38. package/dist/curp-validation.d.ts +188 -0
  39. package/dist/curp-validation.esm.js +110 -0
  40. package/dist/curpValidationStateMachine-CitWLr2c.esm.js +595 -0
  41. package/dist/custom-fields.d.ts +115 -0
  42. package/dist/custom-fields.esm.js +177 -0
  43. package/dist/custom-watchlist.d.ts +66 -0
  44. package/dist/custom-watchlist.esm.js +86 -0
  45. package/dist/dateUtils-UoN5xswP.esm.js +23 -0
  46. package/dist/deepsightLoader-Cm4JIT_z.esm.js +52 -0
  47. package/dist/deepsightService-CEVxzehb.d.ts +412 -0
  48. package/dist/deepsightService-O74l4Y__.esm.js +489 -0
  49. package/dist/device.d.ts +46 -0
  50. package/dist/device.esm.js +106 -0
  51. package/dist/displayErrors-DqJ_IbsG.d.ts +39 -0
  52. package/dist/document-capture.d.ts +906 -0
  53. package/dist/document-capture.esm.js +156 -0
  54. package/dist/document-upload.d.ts +331 -0
  55. package/dist/document-upload.esm.js +203 -0
  56. package/dist/documentCaptureStateMachine-BqzTDy9k.esm.js +394 -0
  57. package/dist/dynamic-forms.d.ts +178 -0
  58. package/dist/dynamic-forms.esm.js +323 -0
  59. package/dist/ekyb.d.ts +148 -0
  60. package/dist/ekyb.esm.js +127 -0
  61. package/dist/ekybStateMachine-B59rQjgj.esm.js +674 -0
  62. package/dist/ekyc.d.ts +164 -0
  63. package/dist/ekyc.esm.js +104 -0
  64. package/dist/ekycStateMachine-oeO0Iekd.esm.js +10626 -0
  65. package/dist/electronic-signature.d.ts +4 -0
  66. package/dist/electronic-signature.esm.js +7 -0
  67. package/dist/electronicSignatureManager-D9OHzTpG.esm.js +428 -0
  68. package/dist/email.d.ts +3 -263
  69. package/dist/email.esm.js +7 -477
  70. package/dist/emailManager-DIfnS5g1.d.ts +352 -0
  71. package/dist/emailManager-wAV0LE-H.esm.js +238 -0
  72. package/dist/emailStateMachine-DOf4j58N.esm.js +292 -0
  73. package/dist/endpoints-CnN3SyDa.esm.js +87 -0
  74. package/dist/events-D6-e4vok.esm.js +596 -0
  75. package/dist/events.d.ts +265 -0
  76. package/dist/events.esm.js +4 -0
  77. package/dist/extensibility.d.ts +122 -0
  78. package/dist/extensibility.esm.js +43 -0
  79. package/dist/face-match.d.ts +228 -0
  80. package/dist/face-match.esm.js +173 -0
  81. package/dist/faceCaptureManagerFactory-Dh2PdGlF.esm.js +290 -0
  82. package/dist/faceCaptureManagerFactory-yqtpxjnN.d.ts +690 -0
  83. package/dist/faceCaptureSetup-B3faSpYA.esm.js +873 -0
  84. package/dist/faceMatchStateMachine-DNFrxTFS.esm.js +127 -0
  85. package/dist/flow-events.d.ts +6 -0
  86. package/dist/flow-events.esm.js +0 -0
  87. package/dist/flow.d.ts +101 -321
  88. package/dist/flow.esm.js +370 -173
  89. package/dist/flowCompletionService-DhkT4SRY.d.ts +10 -0
  90. package/dist/flowCompletionService-P54yzGvA.esm.js +13 -0
  91. package/dist/flowServices-DTsm-Vf1.esm.js +188 -0
  92. package/dist/geolocation.d.ts +127 -0
  93. package/dist/geolocation.esm.js +89 -0
  94. package/dist/geolocationStateMachine-asasuHY2.esm.js +105 -0
  95. package/dist/getBrowser-BSXUTWXw.esm.js +41 -0
  96. package/dist/getDeviceClass-BSntT9_j.esm.js +14 -0
  97. package/dist/government-validation.d.ts +67 -0
  98. package/dist/government-validation.esm.js +81 -0
  99. package/dist/governmentValidationStateMachine-BDDYrJTo.esm.js +271 -0
  100. package/dist/home.d.ts +99 -0
  101. package/dist/home.esm.js +61 -0
  102. package/dist/http.d.ts +68 -0
  103. package/dist/http.esm.js +3 -0
  104. package/dist/id-ocr.d.ts +635 -0
  105. package/dist/id-ocr.esm.js +86 -0
  106. package/dist/id-verification.d.ts +190 -0
  107. package/dist/id-verification.esm.js +43 -0
  108. package/dist/id.d.ts +24 -0
  109. package/dist/id.esm.js +164 -0
  110. package/dist/idCaptureManager-B9TGA5dq.d.ts +956 -0
  111. package/dist/idCaptureManager-DMK0GIt3.esm.js +581 -0
  112. package/dist/idCaptureStateMachine-Bq0fVZXl.esm.js +2954 -0
  113. package/dist/idOcrStateMachine-YbjjC_Gg.esm.js +388 -0
  114. package/dist/idVerificationStateMachine-xbw9HP1Z.esm.js +71 -0
  115. package/dist/identity-reuse.d.ts +530 -0
  116. package/dist/identity-reuse.esm.js +274 -0
  117. package/dist/index-BLKtMA0g.d.ts +1177 -0
  118. package/dist/index-BcRG8rtJ.d.ts +97 -0
  119. package/dist/index.d.ts +3 -226
  120. package/dist/index.esm.js +11 -154
  121. package/dist/invokeOnCaptureCallback-rc6kBHo5.esm.js +30 -0
  122. package/dist/{lib-Bu9XGMBW.esm.js → lib-BB0B_qQX.esm.js} +801 -2
  123. package/dist/mandatory-consent.d.ts +412 -0
  124. package/dist/mandatory-consent.esm.js +78 -0
  125. package/dist/mandatoryConsentStateMachine-Cnco1jvn.esm.js +126 -0
  126. package/dist/openviduLazy-Cm0XFh_v.esm.js +3 -0
  127. package/dist/openviduLazy-Cok70ZSg.esm.js +12 -0
  128. package/dist/permissionServices-D_i6nzEw.esm.js +50 -0
  129. package/dist/phone.d.ts +3 -291
  130. package/dist/phone.esm.js +7 -548
  131. package/dist/phoneManager-B6M30hKE.d.ts +397 -0
  132. package/dist/phoneManager-DAJbGhlY.esm.js +256 -0
  133. package/dist/phoneStateMachine-CuPARRaT.esm.js +351 -0
  134. package/dist/platform-CfrjKhmi.esm.js +83 -0
  135. package/dist/qe-signature-DFo_Cc-I.esm.js +12 -0
  136. package/dist/qe-signature.d.ts +25 -0
  137. package/dist/qe-signature.esm.js +8 -0
  138. package/dist/recordingService-Ig2UgbLv.esm.js +1003 -0
  139. package/dist/redirect-to-mobile.d.ts +107 -0
  140. package/dist/redirect-to-mobile.esm.js +102 -0
  141. package/dist/redirectToMobileStateMachine-BOEqe46A.esm.js +249 -0
  142. package/dist/runChildModule-CqqwqAkW.esm.js +219 -0
  143. package/dist/selfie.d.ts +21 -754
  144. package/dist/selfie.esm.js +113 -962
  145. package/dist/selfieManager-D0lSgd-J.d.ts +68 -0
  146. package/dist/selfieManager-Duisl7qN.esm.js +60 -0
  147. package/dist/selfieStateMachine-D76whWEf.esm.js +68 -0
  148. package/dist/session-BS-d_vuE.esm.js +3206 -0
  149. package/dist/session.d.ts +217 -0
  150. package/dist/session.esm.js +9 -0
  151. package/dist/setup-Buy-hyj4.esm.js +887 -0
  152. package/dist/setup-C5AITV8m.d.ts +254 -0
  153. package/dist/signature.d.ts +94 -0
  154. package/dist/signature.esm.js +66 -0
  155. package/dist/signatureStateMachine-B5-QVUve.esm.js +132 -0
  156. package/dist/stats-CIfiPzb1.esm.js +16 -0
  157. package/dist/stats.d.ts +16 -0
  158. package/dist/stats.esm.js +4 -0
  159. package/dist/trust-graph.d.ts +54 -0
  160. package/dist/trust-graph.esm.js +56 -0
  161. package/dist/types-B06Ypu2F.d.ts +49 -0
  162. package/dist/types-BP1m8VRw.d.ts +340 -0
  163. package/dist/types-CFV9G_7j.d.ts +24 -0
  164. package/dist/{warmup-CEJTfxQr.d.ts → warmup-CEcppFiS.d.ts} +11 -3
  165. package/dist/wasm.d.ts +15 -0
  166. package/dist/wasm.esm.js +12 -0
  167. package/dist/watchlist-for-business.d.ts +79 -0
  168. package/dist/watchlist-for-business.esm.js +148 -0
  169. package/dist/watchlist.d.ts +62 -0
  170. package/dist/watchlist.esm.js +86 -0
  171. package/dist/watchlistServices-DMbUhkBX.esm.js +12 -0
  172. package/dist/workflow.d.ts +907 -0
  173. package/dist/workflow.esm.js +702 -0
  174. package/dist/{xstate.esm-B_rda9yU.esm.js → xstate.esm-B70JrNqo.esm.js} +144 -1
  175. package/package.json +203 -6
  176. package/dist/OpenViduLogger-BdPfiZO6.esm.js +0 -3
  177. package/dist/OpenViduLogger-CQyDxBvM.esm.js +0 -803
  178. package/dist/StateMachine-DRE1oH2B.d.ts +0 -2
  179. package/dist/addEvent-W0ORK0jT.esm.js +0 -16
  180. package/dist/endpoints-BSTFaHYo.esm.js +0 -1706
  181. package/dist/permissionServices-I6vX6DBy.esm.js +0 -72
  182. /package/dist/{Manager-BGfxEmyv.d.ts → Manager-C8PrhBOx.d.ts} +0 -0
  183. /package/dist/{chunk-C_Yo44FK.esm.js → chunk-CRF6K_H_.esm.js} +0 -0
  184. /package/dist/{types-iZi2rawo.d.ts → types-CAD4va6a.d.ts} +0 -0
@@ -0,0 +1,1003 @@
1
+ import { l as WasmPipelineType, r as mlWasmJSApi_default, t as BaseWasmProvider } from "./BaseWasmProvider-C_DLEI40.esm.js";
2
+ import { t as api } from "./api-CESGtpbH.esm.js";
3
+ import { t as endpoints } from "./endpoints-CnN3SyDa.esm.js";
4
+ import { i as stopCameraStream, r as requestCameraAccess } from "./camera-PA2Ljri3.esm.js";
5
+ import { n as IncodeCanvas } from "./deepsightService-O74l4Y__.esm.js";
6
+ import { a as isIPhone14OrHigher, n as isDesktop, r as isIOS, t as isAndroid } from "./platform-CfrjKhmi.esm.js";
7
+ import { n as getDesktopCameraStream, t as getBackCameraStream } from "./backCameraStream-DMdMeGk2.esm.js";
8
+ import { t as addDeviceStats } from "./stats-CIfiPzb1.esm.js";
9
+ import { t as getDeviceClass } from "./getDeviceClass-BSntT9_j.esm.js";
10
+
11
+ //#region ../infra/src/providers/wasm/FaceDetectionProvider.ts
12
+ var FaceDetectionProvider = class extends BaseWasmProvider {
13
+ constructor() {
14
+ super(WasmPipelineType.SelfieWithQualityMetrics);
15
+ this.defaultThresholds = {
16
+ frameMinX: 0,
17
+ frameMinY: 0,
18
+ frameMaxX: 1,
19
+ frameMaxY: 1,
20
+ brightnessThreshold: 50,
21
+ blurrinessThreshold: 50,
22
+ tiltRotationAngleThreshold: 15,
23
+ minMagicCropSize: 200,
24
+ headwearThreshold: .86,
25
+ lensesThreshold: .95,
26
+ closedEyesThreshold: .9,
27
+ maskThreshold: .85,
28
+ minFaceQualityScore: .63,
29
+ faceOcclusionThreshold: .3,
30
+ getReadyDelay: 2e3,
31
+ framesAggregationInterval: 2e3,
32
+ minFramesWithFace: 3
33
+ };
34
+ this.currentFrame = null;
35
+ }
36
+ async processFrame(image) {
37
+ this.currentFrame = image;
38
+ await this.processFrameWasm(image);
39
+ }
40
+ async initialize(config) {
41
+ if (config.useOnDeviceWorkflow === true) {
42
+ this.pipelineType = WasmPipelineType.OnDeviceSelfieWorkflow;
43
+ await this.initializeBase(config, "onDeviceSelfie");
44
+ } else await this.initializeBase(config, "selfie");
45
+ this.applyDefaults(config.autocaptureInterval ?? 0);
46
+ }
47
+ processPhoto(canvas) {
48
+ this.ensureInitialized();
49
+ mlWasmJSApi_default.processPhoto(canvas);
50
+ }
51
+ async postFaceResults(config) {
52
+ this.ensureInitialized();
53
+ return mlWasmJSApi_default.postFaceResults(config);
54
+ }
55
+ setCallbacks(callbacks) {
56
+ this.ensureInitialized();
57
+ const onCaptureWrapper = (wasmCanvas, face) => {
58
+ let frameCanvas = null;
59
+ if (this.currentFrame) frameCanvas = IncodeCanvas.fromImageData(this.currentFrame);
60
+ else if (wasmCanvas) frameCanvas = new IncodeCanvas(wasmCanvas);
61
+ if (!frameCanvas) return;
62
+ const faceCoordinates = face ? this.formatFaceCoordinates(face) : this.createDefaultFaceCoordinates(frameCanvas);
63
+ try {
64
+ frameCanvas.updateBase64Image();
65
+ frameCanvas.updateBlob();
66
+ } catch {}
67
+ callbacks.onCapture?.(frameCanvas, faceCoordinates);
68
+ };
69
+ mlWasmJSApi_default.setFaceDetectionCallbacks(this.getPipelineType(), callbacks.onFarAway ?? (() => {}), callbacks.onTooClose ?? (() => {}), callbacks.onTooManyFaces ?? (() => {}), callbacks.onNoFace ?? (() => {}), onCaptureWrapper, callbacks.onGetReady ?? (() => {}), callbacks.onGetReadyFinished ?? (() => {}), callbacks.onCenterFace ?? (() => {}), callbacks.onDark ?? (() => {}), callbacks.onBlur ?? (() => {}), callbacks.onFaceAngle ?? (() => {}), callbacks.onLenses ?? (() => {}), callbacks.onMask ?? (() => {}), callbacks.onEyesClosed ?? (() => {}), callbacks.onHeadWear ?? (() => {}), callbacks.onSwitchToManualCapture ?? (() => {}), callbacks.onFaceOccluded ?? (() => {}));
70
+ }
71
+ setPositionConstraints(constraints) {
72
+ this.ensureInitialized();
73
+ mlWasmJSApi_default.setFacePositionConstraints(this.getPipelineType(), constraints.minX, constraints.minY, constraints.maxX, constraints.maxY);
74
+ }
75
+ applyDefaults(autocaptureInterval = 0) {
76
+ this.ensureInitialized();
77
+ this.setThresholds({
78
+ brightnessThreshold: this.defaultThresholds.brightnessThreshold,
79
+ blurrinessThreshold: this.defaultThresholds.blurrinessThreshold,
80
+ tiltRotationAngleThreshold: this.defaultThresholds.tiltRotationAngleThreshold,
81
+ minMagicCropSize: this.defaultThresholds.minMagicCropSize,
82
+ autocaptureInterval,
83
+ minFaceQualityScore: this.defaultThresholds.minFaceQualityScore,
84
+ faceOcclusionThreshold: this.defaultThresholds.faceOcclusionThreshold,
85
+ getReadyDelay: this.defaultThresholds.getReadyDelay,
86
+ framesAggregationInterval: this.defaultThresholds.framesAggregationInterval,
87
+ minFramesWithFace: this.defaultThresholds.minFramesWithFace
88
+ });
89
+ this.setPositionConstraints({
90
+ minX: this.defaultThresholds.frameMinX,
91
+ minY: this.defaultThresholds.frameMinY,
92
+ maxX: this.defaultThresholds.frameMaxX,
93
+ maxY: this.defaultThresholds.frameMaxY
94
+ });
95
+ this.setAttributesThresholds({
96
+ headwearThreshold: this.defaultThresholds.headwearThreshold,
97
+ lensesThreshold: this.defaultThresholds.lensesThreshold,
98
+ closedEyesThreshold: this.defaultThresholds.closedEyesThreshold,
99
+ maskThreshold: this.defaultThresholds.maskThreshold
100
+ });
101
+ }
102
+ setAutocaptureInterval(interval) {
103
+ this.ensureInitialized();
104
+ if (!this.currentThresholds) {
105
+ this.applyDefaults(interval);
106
+ return;
107
+ }
108
+ this.setThresholds({
109
+ ...this.currentThresholds,
110
+ autocaptureInterval: interval
111
+ });
112
+ }
113
+ setThresholds(thresholds) {
114
+ this.ensureInitialized();
115
+ this.currentThresholds = { ...thresholds };
116
+ mlWasmJSApi_default.setFaceDetectionThresholds(this.getPipelineType(), thresholds.brightnessThreshold, thresholds.blurrinessThreshold, thresholds.tiltRotationAngleThreshold, thresholds.minMagicCropSize, thresholds.autocaptureInterval, thresholds.minFaceQualityScore, thresholds.faceOcclusionThreshold, thresholds.getReadyDelay, thresholds.framesAggregationInterval, thresholds.minFramesWithFace);
117
+ }
118
+ setAttributesThresholds(thresholds) {
119
+ this.ensureInitialized();
120
+ mlWasmJSApi_default.setFaceAttributesThresholds(this.getPipelineType(), thresholds.headwearThreshold, thresholds.lensesThreshold, thresholds.closedEyesThreshold, thresholds.maskThreshold);
121
+ }
122
+ setChecksEnabled(config) {
123
+ this.ensureInitialized();
124
+ mlWasmJSApi_default.setFaceChecksEnabled(this.getPipelineType(), config.lenses, config.mask, config.closedEyes, config.headWear, config.occlusion);
125
+ }
126
+ setVideoSelfieMode(enabled) {
127
+ this.ensureInitialized();
128
+ mlWasmJSApi_default.setFaceDetectionMode(this.getPipelineType(), enabled);
129
+ }
130
+ reset() {
131
+ super.reset();
132
+ this.currentFrame = null;
133
+ }
134
+ createDefaultFaceCoordinates(canvas) {
135
+ return {
136
+ rightEyeX: 0,
137
+ rightEyeY: 0,
138
+ leftEyeX: 0,
139
+ leftEyeY: 0,
140
+ noseTipX: 0,
141
+ noseTipY: 0,
142
+ rightMouthX: 0,
143
+ rightMouthY: 0,
144
+ mouthX: 0,
145
+ mouthY: 0,
146
+ x: 0,
147
+ y: 0,
148
+ width: canvas.width() ?? 0,
149
+ height: canvas.height() ?? 0
150
+ };
151
+ }
152
+ formatFaceCoordinates(face) {
153
+ return {
154
+ rightEyeX: face.rightEye.x,
155
+ rightEyeY: face.rightEye.y,
156
+ leftEyeX: face.leftEye.x,
157
+ leftEyeY: face.leftEye.y,
158
+ noseTipX: face.noseTip.x,
159
+ noseTipY: face.noseTip.y,
160
+ rightMouthX: face.rightMouthCorner.x,
161
+ rightMouthY: face.rightMouthCorner.y,
162
+ mouthX: face.leftMouthCorner.x,
163
+ mouthY: face.leftMouthCorner.y,
164
+ x: face.rect.x,
165
+ y: face.rect.y,
166
+ width: face.rect.width,
167
+ height: face.rect.height
168
+ };
169
+ }
170
+ };
171
+
172
+ //#endregion
173
+ //#region ../infra/src/media/StreamCanvasProcessingSession.ts
174
+ var StreamCanvasProcessingSession = class {
175
+ /**
176
+ * Creates a processing session that reacts to `StreamCanvasCapture` frame events
177
+ * and drives a provider's `processFrame()` method with backpressure.
178
+ */
179
+ constructor(params) {
180
+ this.disposed = false;
181
+ this.isProcessing = false;
182
+ this.onFrameEvent = () => {
183
+ if (this.disposed || this.isProcessing) return;
184
+ const frame = this.capturer.getLatestFrame();
185
+ if (!frame) return;
186
+ this.onFrame?.(frame);
187
+ this.isProcessing = true;
188
+ this.provider.processFrame(frame).catch(() => {}).finally(() => {
189
+ this.isProcessing = false;
190
+ });
191
+ };
192
+ this.capturer = params.capturer;
193
+ this.provider = params.provider;
194
+ this.onFrame = params.onFrame;
195
+ this.capturer.addEventListener("frame", this.onFrameEvent);
196
+ }
197
+ /**
198
+ * Unsubscribes from frame events and resets the provider.
199
+ */
200
+ dispose() {
201
+ if (this.disposed) return;
202
+ this.disposed = true;
203
+ this.capturer.removeEventListener("frame", this.onFrameEvent);
204
+ this.provider.reset();
205
+ }
206
+ /**
207
+ * Returns whether the session has been disposed.
208
+ */
209
+ isDisposed() {
210
+ return this.disposed;
211
+ }
212
+ };
213
+
214
+ //#endregion
215
+ //#region src/internal/recordings/recordingsRepository.ts
216
+ async function createRecordingSession(type) {
217
+ return (await api.post(endpoints.recordingCreateSessionV2, { type })).data;
218
+ }
219
+ async function startRecording(params) {
220
+ return (await api.post(endpoints.recordingStartV2, {
221
+ videoRecordingId: params.videoRecordingId,
222
+ frameRate: 30,
223
+ outputMode: "COMPOSED",
224
+ resolution: params.resolution,
225
+ type: params.type,
226
+ hasAudio: params.hasAudio ?? false
227
+ })).data;
228
+ }
229
+ async function stopRecording$1(videoRecordingId) {
230
+ return (await api.post(endpoints.recordingStopV2, { videoRecordingId })).data;
231
+ }
232
+ async function uploadDeepsightVideo(encryptedVideo, token) {
233
+ try {
234
+ return (await api.post(endpoints.deepsightVideoImport, {
235
+ video: encryptedVideo,
236
+ type: "selfie"
237
+ }, { headers: { "X-Incode-Hardware-Id": token } })).data.recordingId ?? "";
238
+ } catch {
239
+ return "";
240
+ }
241
+ }
242
+
243
+ //#endregion
244
+ //#region src/internal/faceCapture/types.ts
245
+ const FACE_ERROR_CODES = {
246
+ FACE_OCCLUDED: "FACE_OCCLUDED",
247
+ LIVENESS: "LIVENESS_ERROR",
248
+ BRIGHTNESS: "BRIGHTNESS_ERROR",
249
+ LENSES: "LENSES_ERROR",
250
+ MASK: "MASK_ERROR",
251
+ CLOSED_EYES: "CLOSED_EYES_ERROR",
252
+ HEAD_COVER: "HEAD_COVER_ERROR",
253
+ SERVER: "SERVER_ERROR",
254
+ FACE_NOT_FOUND: "FACE_NOT_FOUND",
255
+ MULTIPLE_FACES: "MULTIPLE_FACES",
256
+ TOO_BLURRY: "TOO_BLURRY_ERROR",
257
+ TOO_DARK: "TOO_DARK_ERROR",
258
+ USER_IS_NOT_RECOGNIZED: "USER_IS_NOT_RECOGNIZED",
259
+ SPOOF_ATTEMPT_DETECTED: "SPOOF_ATTEMPT_DETECTED",
260
+ FACE_TOO_DARK: "FACE_TOO_DARK",
261
+ LENSES_DETECTED: "LENSES_DETECTED",
262
+ FACE_MASK_DETECTED: "FACE_MASK_DETECTED",
263
+ CLOSED_EYES_DETECTED: "CLOSED_EYES_DETECTED",
264
+ HEAD_COVER_DETECTED: "HEAD_COVER_DETECTED",
265
+ FACE_CROPPING_FAILED: "FACE_CROPPING_FAILED",
266
+ FACE_TOO_SMALL: "FACE_TOO_SMALL",
267
+ FACE_TOO_BLURRY: "FACE_TOO_BLURRY",
268
+ BAD_PHOTO_QUALITY: "BAD_PHOTO_QUALITY",
269
+ PROCESSING_ERROR: "PROCESSING_ERROR",
270
+ BAD_REQUEST: "BAD_REQUEST",
271
+ NONEXISTENT_CUSTOMER: "NONEXISTENT_CUSTOMER",
272
+ HINT_NOT_PROVIDED: "HINT_NOT_PROVIDED",
273
+ SELFIE_IMAGE_LOW_QUALITY: "SELFIE_IMAGE_LOW_QUALITY"
274
+ };
275
+
276
+ //#endregion
277
+ //#region src/modules/selfie/selfieUploadService.ts
278
+ /**
279
+ * Uploads a selfie image to the backend.
280
+ */
281
+ async function uploadSelfie({ encryptedBase64Image, faceCoordinates, signal, metadata, recordingId }) {
282
+ try {
283
+ const payload = {
284
+ base64Image: encryptedBase64Image,
285
+ faceCoordinates: faceCoordinates ?? void 0,
286
+ encrypted: true,
287
+ clientInfo: { deviceClass: getDeviceClass() },
288
+ metadata: metadata ?? void 0
289
+ };
290
+ const query = { imageType: "selfie" };
291
+ if (recordingId) query.recordingId = recordingId;
292
+ const res = await api.post(endpoints.selfie, payload, {
293
+ signal,
294
+ query
295
+ });
296
+ if (!res.ok) throw new Error(`POST ${endpoints.selfie} failed: ${res.status} ${res.statusText}`);
297
+ return res.data;
298
+ } catch (error) {
299
+ const errorCode = getFaceErrorCodeFromHttpError(error);
300
+ if (errorCode) throw new Error(errorCode);
301
+ throw new Error(FACE_ERROR_CODES.SERVER);
302
+ }
303
+ }
304
+ const getFaceErrorCodeFromHttpError = (error) => {
305
+ const err = error;
306
+ if (err.ok !== false || typeof err.status !== "number") return;
307
+ if (err.status !== 400) return FACE_ERROR_CODES.SERVER;
308
+ if (typeof err.data?.status !== "number") return FACE_ERROR_CODES.BAD_REQUEST;
309
+ return {
310
+ 3004: FACE_ERROR_CODES.FACE_NOT_FOUND,
311
+ 3005: FACE_ERROR_CODES.FACE_NOT_FOUND,
312
+ 3006: FACE_ERROR_CODES.TOO_BLURRY,
313
+ 3007: FACE_ERROR_CODES.TOO_DARK,
314
+ 4010: FACE_ERROR_CODES.MULTIPLE_FACES,
315
+ 4019: FACE_ERROR_CODES.FACE_NOT_FOUND,
316
+ 4077: FACE_ERROR_CODES.BAD_PHOTO_QUALITY,
317
+ 4078: FACE_ERROR_CODES.FACE_OCCLUDED
318
+ }[err.data.status] ?? FACE_ERROR_CODES.BAD_REQUEST;
319
+ };
320
+ async function processFace(imageType = "selfie", signal) {
321
+ return (await api.post(endpoints.processFace, {}, {
322
+ query: { imageType },
323
+ signal
324
+ })).data;
325
+ }
326
+
327
+ //#endregion
328
+ //#region src/internal/faceCapture/faceCaptureServices.ts
329
+ function sendLabelInspectionEvent() {
330
+ return addDeviceStats({ cameraLabelInspectionStatus: "FAIL" });
331
+ }
332
+ const MOBILE_SELFIE_CONSTRAINTS = {
333
+ video: {
334
+ facingMode: "user",
335
+ height: { ideal: 480 },
336
+ width: { ideal: 640 }
337
+ },
338
+ audio: false
339
+ };
340
+ const IPHONE14_SELFIE_CONSTRAINTS = {
341
+ video: { height: { ideal: 1080 } },
342
+ audio: false
343
+ };
344
+ function buildCameraConstraints(resolution) {
345
+ if (resolution) return {
346
+ video: {
347
+ facingMode: "user",
348
+ height: resolution.height ? { ideal: resolution.height } : void 0,
349
+ width: resolution.width ? { ideal: resolution.width } : void 0
350
+ },
351
+ audio: false
352
+ };
353
+ if (isIPhone14OrHigher()) return IPHONE14_SELFIE_CONSTRAINTS;
354
+ return MOBILE_SELFIE_CONSTRAINTS;
355
+ }
356
+ function stopStream(stream) {
357
+ stopCameraStream(stream);
358
+ }
359
+ async function getFrontCameraStream(resolution) {
360
+ if (resolution) return requestCameraAccess(buildCameraConstraints(resolution));
361
+ if (isDesktop()) return getDesktopCameraStream({});
362
+ return requestCameraAccess(buildCameraConstraints());
363
+ }
364
+ async function initializeCamera(params) {
365
+ const { config } = params;
366
+ const prcConstraints = buildCameraConstraints(config.cameraResolution);
367
+ const provider = new FaceDetectionProvider();
368
+ await provider.initialize({
369
+ autocaptureInterval: config.autoCaptureTimeout * 1e3,
370
+ useOnDeviceWorkflow: config.onDeviceFaceResultsSubmissionEnabled === true
371
+ });
372
+ provider.setChecksEnabled({
373
+ lenses: config.validateLenses ?? false,
374
+ mask: config.validateFaceMask ?? false,
375
+ closedEyes: config.validateClosedEyes ?? false,
376
+ headWear: config.validateHeadCover ?? false,
377
+ occlusion: false
378
+ });
379
+ await params.deepsightService.performPrcCheck({ constraints: { video: prcConstraints.video } });
380
+ return {
381
+ stream: config.assistedOnboarding ? (await getBackCameraStream()).stream : await getFrontCameraStream(config.cameraResolution),
382
+ provider
383
+ };
384
+ }
385
+ /**
386
+ * Encrypts the provided selfie image using WASM.
387
+ */
388
+ async function encryptSelfieImage({ canvas, dependencies }) {
389
+ const base64Image = canvas.getBase64Image();
390
+ if (!base64Image) throw new Error("Canvas image is empty or null");
391
+ return (await dependencies.getWasmUtil()).encryptImage(base64Image);
392
+ }
393
+ function startDetection(params) {
394
+ let lastStatus;
395
+ let session;
396
+ const { provider } = params;
397
+ const setStatus = (status) => {
398
+ if (session?.isDisposed() === true) return;
399
+ if (lastStatus === status) return;
400
+ lastStatus = status;
401
+ params.onUpdate(status);
402
+ };
403
+ const stopDetectionLoop = () => {
404
+ session?.dispose();
405
+ };
406
+ const reset = () => {
407
+ provider.reset();
408
+ };
409
+ const cleanup = () => {
410
+ stopDetectionLoop();
411
+ };
412
+ (async () => {
413
+ try {
414
+ provider.setCallbacks({
415
+ onFarAway: () => setStatus("tooFar"),
416
+ onTooClose: () => setStatus("tooClose"),
417
+ onTooManyFaces: () => setStatus("tooManyFaces"),
418
+ onNoFace: () => setStatus("idle"),
419
+ onCenterFace: () => setStatus("centerFace"),
420
+ onGetReady: () => setStatus("getReady"),
421
+ onGetReadyFinished: () => setStatus("getReadyFinished"),
422
+ onDark: () => {
423
+ if (params.config.validateBrightness) setStatus("dark");
424
+ },
425
+ onBlur: () => setStatus("blur"),
426
+ onFaceAngle: () => setStatus("faceAngle"),
427
+ onLenses: () => {
428
+ if (params.config.validateLenses) setStatus("lenses");
429
+ },
430
+ onMask: () => {
431
+ if (params.config.validateFaceMask) setStatus("faceMask");
432
+ },
433
+ onEyesClosed: () => {
434
+ if (params.config.validateClosedEyes) setStatus("eyesClosed");
435
+ },
436
+ onHeadWear: () => {
437
+ if (params.config.validateHeadCover) setStatus("headWear");
438
+ },
439
+ onFaceOccluded: () => setStatus("faceOcclusion"),
440
+ onSwitchToManualCapture: () => {
441
+ setStatus("manualCapture");
442
+ stopDetectionLoop();
443
+ },
444
+ onCapture: (canvas, faceCoordinates) => {
445
+ setStatus("success");
446
+ params.onSuccess(canvas, faceCoordinates);
447
+ cleanup();
448
+ }
449
+ });
450
+ setStatus("detecting");
451
+ session = new StreamCanvasProcessingSession({
452
+ capturer: params.capturer,
453
+ provider,
454
+ onFrame: params.onFrame
455
+ });
456
+ } catch {
457
+ setStatus("error");
458
+ cleanup();
459
+ }
460
+ })();
461
+ return {
462
+ cleanup,
463
+ reset
464
+ };
465
+ }
466
+ function buildResolutionFromStream(stream) {
467
+ const track = stream.getVideoTracks()[0];
468
+ if (!track) return;
469
+ const settings = track.getSettings();
470
+ const width = settings.width;
471
+ const height = settings.height;
472
+ if (typeof width === "number" && typeof height === "number") return `${width}x${height}`;
473
+ }
474
+ async function createOpenViduRecordingProvider() {
475
+ const { OpenViduRecordingProvider } = await import("./OpenViduRecordingProvider-CMu6XVdc.esm.js");
476
+ return new OpenViduRecordingProvider();
477
+ }
478
+ async function startRecordingSession(params) {
479
+ if (params.config.deepsightLiveness === "VIDEOLIVENESS") return;
480
+ if (params.config.enableFaceRecording !== true) return;
481
+ if (params.existing) return params.existing;
482
+ const provider = params.config.recording?.capability ?? await createOpenViduRecordingProvider();
483
+ const clonedStream = params.clonedStream;
484
+ const hasAudio = clonedStream.getAudioTracks().length > 0;
485
+ const resolution = buildResolutionFromStream(clonedStream);
486
+ const session = await createRecordingSession("selfie");
487
+ const connection = await provider.connect({
488
+ sessionToken: session.token,
489
+ stream: clonedStream,
490
+ events: {}
491
+ });
492
+ await startRecording({
493
+ videoRecordingId: session.videoRecordingId,
494
+ type: "selfie",
495
+ resolution,
496
+ hasAudio
497
+ });
498
+ return {
499
+ token: session.token,
500
+ sessionId: session.sessionId,
501
+ videoRecordingId: session.videoRecordingId,
502
+ connection,
503
+ resolution,
504
+ hasAudio
505
+ };
506
+ }
507
+ async function stopRecording(session) {
508
+ try {
509
+ await stopRecording$1(session.videoRecordingId);
510
+ } finally {
511
+ await session.connection.disconnect();
512
+ }
513
+ }
514
+ async function initializeDeepsightSession(options) {
515
+ const { loadDeepsightSession } = await import("./deepsightLoader-Cm4JIT_z.esm.js");
516
+ return loadDeepsightSession({
517
+ ds: options.ds,
518
+ storage: options.storage
519
+ });
520
+ }
521
+
522
+ //#endregion
523
+ //#region ../infra/src/media/StreamCanvasCapture.ts
524
+ var StreamCanvasCapture = class {
525
+ constructor(stream, options) {
526
+ this.hasFrame = false;
527
+ this.disposed = false;
528
+ this.eventTarget = new EventTarget();
529
+ this.video = document.createElement("video");
530
+ this.video.srcObject = stream;
531
+ this.video.autoplay = true;
532
+ this.video.playsInline = true;
533
+ this.video.muted = true;
534
+ const settings = stream.getVideoTracks()[0]?.getSettings();
535
+ const initialWidth = options?.width ?? settings?.width ?? 1280;
536
+ const initialHeight = options?.height ?? settings?.height ?? 720;
537
+ this.canvas = document.createElement("canvas");
538
+ this.canvas.width = initialWidth;
539
+ this.canvas.height = initialHeight;
540
+ this.ctx = this.canvas.getContext("2d", { willReadFrequently: true });
541
+ const fps = options?.fps ?? 10;
542
+ const intervalMs = fps > 0 ? Math.max(16, Math.floor(1e3 / fps)) : 0;
543
+ this.video.addEventListener("loadedmetadata", () => {
544
+ if (this.video.videoWidth > 0 && this.video.videoHeight > 0) {
545
+ this.canvas.width = this.video.videoWidth;
546
+ this.canvas.height = this.video.videoHeight;
547
+ }
548
+ });
549
+ try {
550
+ this.video.play();
551
+ } catch {}
552
+ this.rafLoop(intervalMs);
553
+ }
554
+ addEventListener(type, listener, options) {
555
+ this.eventTarget.addEventListener(type, listener, options);
556
+ }
557
+ removeEventListener(type, listener, options) {
558
+ this.eventTarget.removeEventListener(type, listener, options);
559
+ }
560
+ /**
561
+ * Returns the latest cached frame as an {@link IncodeCanvas}.
562
+ */
563
+ getLatestCanvas() {
564
+ if (!this.hasFrame) this.tick();
565
+ if (!this.hasFrame) return null;
566
+ return new IncodeCanvas(this.canvas);
567
+ }
568
+ /**
569
+ * Returns the latest cached frame as raw {@link ImageData}.
570
+ */
571
+ getLatestFrame() {
572
+ if (!this.ctx) return null;
573
+ if (!this.hasFrame) this.tick();
574
+ if (!this.hasFrame) return null;
575
+ try {
576
+ return this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);
577
+ } catch {
578
+ return null;
579
+ }
580
+ }
581
+ /**
582
+ * Disposes internal resources and stops the capture loop.
583
+ */
584
+ dispose() {
585
+ if (this.disposed) return;
586
+ this.disposed = true;
587
+ if (this.rafId !== void 0) {
588
+ window.cancelAnimationFrame(this.rafId);
589
+ this.rafId = void 0;
590
+ }
591
+ this.video.srcObject = null;
592
+ this.canvas.width = 0;
593
+ this.canvas.height = 0;
594
+ this.hasFrame = false;
595
+ }
596
+ rafLoop(intervalMs) {
597
+ const loop = (timeMs) => {
598
+ if (this.disposed) return;
599
+ if (intervalMs <= 0 || this.lastTickTimeMs === void 0 || timeMs - this.lastTickTimeMs >= intervalMs) {
600
+ this.lastTickTimeMs = timeMs;
601
+ const previousFrameTimeSeconds = this.lastFrameTimeSeconds;
602
+ this.tick();
603
+ const currentFrameTimeSeconds = this.video.currentTime;
604
+ if (previousFrameTimeSeconds === void 0) {
605
+ if (this.hasFrame) {
606
+ this.lastFrameTimeSeconds = currentFrameTimeSeconds;
607
+ this.eventTarget.dispatchEvent(new Event("frame"));
608
+ }
609
+ } else if (this.hasFrame && currentFrameTimeSeconds !== previousFrameTimeSeconds) {
610
+ this.lastFrameTimeSeconds = currentFrameTimeSeconds;
611
+ this.eventTarget.dispatchEvent(new Event("frame"));
612
+ }
613
+ }
614
+ this.rafId = window.requestAnimationFrame(loop);
615
+ };
616
+ this.rafId = window.requestAnimationFrame(loop);
617
+ }
618
+ tick() {
619
+ if (!this.ctx) return;
620
+ if (this.video.readyState < HTMLMediaElement.HAVE_CURRENT_DATA) return;
621
+ const videoWidth = this.video.videoWidth;
622
+ const videoHeight = this.video.videoHeight;
623
+ if (videoWidth === 0 || videoHeight === 0) return;
624
+ if (this.canvas.width !== videoWidth || this.canvas.height !== videoHeight) {
625
+ this.canvas.width = videoWidth;
626
+ this.canvas.height = videoHeight;
627
+ }
628
+ try {
629
+ this.ctx.drawImage(this.video, 0, 0);
630
+ this.hasFrame = true;
631
+ } catch {
632
+ this.hasFrame = false;
633
+ }
634
+ }
635
+ };
636
+
637
+ //#endregion
638
+ //#region src/internal/manualReview/manualReviewService.ts
639
+ async function flagFaceManualReview() {
640
+ try {
641
+ await api.put(endpoints.updateSession, { manualSelfieCheckNeeded: true });
642
+ } catch {}
643
+ }
644
+ async function flagIdManualReview() {
645
+ try {
646
+ await api.put(endpoints.updateSession, { manualIdCheckNeeded: true });
647
+ } catch {}
648
+ }
649
+
650
+ //#endregion
651
+ //#region ../infra/src/media/VideoTrimmer.ts
652
+ async function getDurationBySeek(videoBlob) {
653
+ const video = document.createElement("video");
654
+ video.preload = "metadata";
655
+ video.src = URL.createObjectURL(videoBlob);
656
+ try {
657
+ if (!Number.isFinite(video.duration)) {
658
+ video.currentTime = Number.MAX_SAFE_INTEGER;
659
+ await new Promise((resolve) => {
660
+ const onDurationChange = () => {
661
+ if (Number.isFinite(video.duration)) {
662
+ video.removeEventListener("durationchange", onDurationChange);
663
+ video.removeEventListener("timeupdate", onTimeUpdate);
664
+ resolve(video.duration);
665
+ }
666
+ };
667
+ const onTimeUpdate = () => {
668
+ if (Number.isFinite(video.duration)) {
669
+ video.removeEventListener("timeupdate", onTimeUpdate);
670
+ video.removeEventListener("durationchange", onDurationChange);
671
+ resolve(video.duration);
672
+ }
673
+ };
674
+ video.addEventListener("durationchange", onDurationChange);
675
+ video.addEventListener("timeupdate", onTimeUpdate);
676
+ });
677
+ }
678
+ const duration = video.duration;
679
+ return Number.isFinite(duration) ? duration : null;
680
+ } finally {
681
+ URL.revokeObjectURL(video.src);
682
+ video.src = "";
683
+ }
684
+ }
685
+ async function trimLastNSecondsUsingPlayback(videoBlob, seconds) {
686
+ const video = document.createElement("video");
687
+ video.preload = "metadata";
688
+ video.playsInline = true;
689
+ video.muted = true;
690
+ const videoURL = URL.createObjectURL(videoBlob);
691
+ video.src = videoURL;
692
+ const duration = await getDurationBySeek(videoBlob);
693
+ if (!duration || duration < seconds) {
694
+ URL.revokeObjectURL(videoURL);
695
+ return videoBlob;
696
+ }
697
+ const startTime = Math.max(0, Math.floor(duration) - seconds);
698
+ await new Promise((resolve) => {
699
+ if (video.readyState >= 2) resolve();
700
+ else video.addEventListener("loadedmetadata", () => resolve(), { once: true });
701
+ });
702
+ const canvas = document.createElement("canvas");
703
+ canvas.width = 230;
704
+ canvas.height = 320;
705
+ const captureFps = isAndroid() ? 15 : 24;
706
+ const stream = canvas.captureStream(captureFps);
707
+ const ctx = canvas.getContext("2d");
708
+ video.currentTime = startTime;
709
+ await new Promise((resolve) => {
710
+ video.addEventListener("seeked", () => resolve(), { once: true });
711
+ });
712
+ ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
713
+ const mimeType = videoBlob.type || (MediaRecorder.isTypeSupported("video/webm") ? "video/webm" : "video/mp4");
714
+ const mediaRecorder = new MediaRecorder(stream.clone(), {
715
+ mimeType,
716
+ videoBitsPerSecond: 5e5,
717
+ bitsPerSecond: 5e5
718
+ });
719
+ const chunks = [];
720
+ mediaRecorder.ondataavailable = (event) => {
721
+ if (event.data.size > 0) chunks.push(event.data);
722
+ };
723
+ const recordingPromise = new Promise((resolve) => {
724
+ mediaRecorder.onstop = () => {
725
+ const trimmedBlob$1 = new Blob(chunks, { type: mimeType });
726
+ URL.revokeObjectURL(videoURL);
727
+ mediaRecorder.stream?.getTracks().forEach((track) => track.stop());
728
+ stream.getTracks().forEach((track) => track.stop());
729
+ video.src = "";
730
+ resolve(trimmedBlob$1);
731
+ };
732
+ });
733
+ video.addEventListener("play", () => {
734
+ function drawVideo() {
735
+ if (video.currentTime >= duration) {
736
+ mediaRecorder.stop();
737
+ video.pause();
738
+ return;
739
+ }
740
+ ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
741
+ requestAnimationFrame(drawVideo);
742
+ }
743
+ drawVideo();
744
+ setTimeout(() => {
745
+ mediaRecorder.start(100);
746
+ }, 500);
747
+ });
748
+ video.play().catch(() => {
749
+ URL.revokeObjectURL(videoURL);
750
+ });
751
+ const trimmedBlob = await recordingPromise;
752
+ console.timeEnd("trimLastNSecondsUsingPlayback");
753
+ return trimmedBlob;
754
+ }
755
+ async function trimLastNSeconds(videoBlob, seconds) {
756
+ return await trimLastNSecondsUsingPlayback(videoBlob, seconds);
757
+ }
758
+
759
+ //#endregion
760
+ //#region ../infra/src/providers/browser/LocalRecordingProvider.ts
761
+ function toBase64(videoBlob) {
762
+ return new Promise((resolve, reject) => {
763
+ const reader = new FileReader();
764
+ reader.onloadend = () => {
765
+ const base64 = reader.result.split(",")[1];
766
+ resolve(base64);
767
+ };
768
+ reader.onerror = () => reject(reader.error ?? /* @__PURE__ */ new Error("FileReader error"));
769
+ reader.readAsDataURL(videoBlob);
770
+ });
771
+ }
772
+ function getSupportedMediaRecorderMimeType() {
773
+ const possibleTypes = isIOS() ? [
774
+ "video/mp4",
775
+ "video/webm",
776
+ "video/webm;codecs=vp9",
777
+ "video/webm;codecs=vp8"
778
+ ] : [
779
+ "video/webm",
780
+ "video/webm;codecs=vp9",
781
+ "video/webm;codecs=vp8",
782
+ "video/mp4"
783
+ ];
784
+ for (const type of possibleTypes) if (MediaRecorder.isTypeSupported(type)) return type;
785
+ return "";
786
+ }
787
+ function getAdaptiveMediaRecorderOptions() {
788
+ const mimeType = getSupportedMediaRecorderMimeType();
789
+ if (isIOS()) return {
790
+ mimeType,
791
+ videoBitsPerSecond: 1e6,
792
+ bitsPerSecond: 1e6
793
+ };
794
+ return {
795
+ mimeType,
796
+ videoBitsPerSecond: 5e5,
797
+ bitsPerSecond: 5e5
798
+ };
799
+ }
800
+ var LocalRecordingProvider = class {
801
+ constructor() {
802
+ this.mediaRecorder = null;
803
+ this._isRecording = false;
804
+ this._hasError = false;
805
+ this._error = null;
806
+ this.mimeType = "";
807
+ this.stream = null;
808
+ this.pauseRecordingBound = this.pauseRecording.bind(this);
809
+ }
810
+ get isRecording() {
811
+ return this._isRecording;
812
+ }
813
+ get hasError() {
814
+ return this._hasError;
815
+ }
816
+ get error() {
817
+ return this._error;
818
+ }
819
+ startRecording(stream) {
820
+ this.reset();
821
+ this.registerEventListeners();
822
+ this.stream = stream;
823
+ try {
824
+ const options = getAdaptiveMediaRecorderOptions();
825
+ this.mimeType = options.mimeType;
826
+ const recorder = new MediaRecorder(stream.clone(), options);
827
+ recorder.onerror = (event) => {
828
+ this._error = `Recording error: ${event}`;
829
+ this._isRecording = false;
830
+ this._hasError = true;
831
+ };
832
+ recorder.start();
833
+ this.mediaRecorder = recorder;
834
+ this._isRecording = true;
835
+ this._error = null;
836
+ this._hasError = false;
837
+ } catch (err) {
838
+ this._error = `Failed to start recording: ${err}`;
839
+ this._hasError = true;
840
+ }
841
+ }
842
+ async stopRecording(trimSeconds, encrypt, generateChecksum) {
843
+ const recorder = this.mediaRecorder;
844
+ return new Promise((resolve, reject) => {
845
+ this.removeEventListeners();
846
+ if (recorder && this._isRecording) {
847
+ const chunks = [];
848
+ recorder.ondataavailable = (event) => {
849
+ if (event.data.size > 0) chunks.push(event.data);
850
+ };
851
+ recorder.onstop = async () => {
852
+ try {
853
+ const trimmedVideo = await trimLastNSeconds(new Blob(chunks, { type: this.mimeType }), trimSeconds);
854
+ const encryptedVideoBase64 = encrypt(await toBase64(trimmedVideo));
855
+ generateChecksum(await trimmedVideo.arrayBuffer());
856
+ this._isRecording = false;
857
+ resolve({
858
+ trimmedBlob: trimmedVideo,
859
+ encryptedVideo: encryptedVideoBase64
860
+ });
861
+ } catch (error) {
862
+ this._isRecording = false;
863
+ this._error = `Recording stop failed: ${error}`;
864
+ this._hasError = true;
865
+ reject(error);
866
+ }
867
+ };
868
+ recorder.stop();
869
+ this._isRecording = false;
870
+ } else resolve({
871
+ trimmedBlob: new Blob([], { type: this.mimeType }),
872
+ encryptedVideo: ""
873
+ });
874
+ recorder?.stream?.getTracks().forEach((track) => track.stop());
875
+ });
876
+ }
877
+ reset() {
878
+ this._isRecording = false;
879
+ this._error = null;
880
+ this._hasError = false;
881
+ }
882
+ pauseRecording() {
883
+ if (!this._isRecording) return;
884
+ if (this.mediaRecorder?.state === "recording") try {
885
+ this.mediaRecorder.pause();
886
+ } catch {}
887
+ }
888
+ registerEventListeners() {
889
+ document.addEventListener("visibilitychange", this.pauseRecordingBound);
890
+ }
891
+ removeEventListeners() {
892
+ document.removeEventListener("visibilitychange", this.pauseRecordingBound);
893
+ }
894
+ };
895
+
896
+ //#endregion
897
+ //#region src/internal/faceCapture/recordingService.ts
898
+ let openViduProviderImportPromise;
899
+ let openViduBrowserImportPromise;
900
+ function loadOpenViduProviderModule() {
901
+ if (!openViduProviderImportPromise) openViduProviderImportPromise = import("./OpenViduRecordingProvider-CMu6XVdc.esm.js");
902
+ return openViduProviderImportPromise;
903
+ }
904
+ function loadOpenViduBrowserModule() {
905
+ if (!openViduBrowserImportPromise) openViduBrowserImportPromise = (async () => {
906
+ return (await import("./openviduLazy-Cm0XFh_v.esm.js")).loadOpenVidu();
907
+ })();
908
+ return openViduBrowserImportPromise;
909
+ }
910
+ function preloadOpenViduProvider() {
911
+ loadOpenViduProviderModule();
912
+ loadOpenViduBrowserModule();
913
+ }
914
+ /**
915
+ * Records on-device and uploads encrypted video for liveness.
916
+ */
917
+ var LocalRecordingService = class {
918
+ constructor(wasmUtil, sessionToken) {
919
+ this.recorder = new LocalRecordingProvider();
920
+ this.sessionToken = sessionToken;
921
+ this.wasmUtil = wasmUtil;
922
+ }
923
+ async start(stream) {
924
+ this.recorder.startRecording(stream);
925
+ }
926
+ async stop() {
927
+ if (!this.recorder.isRecording) return { recordingId: null };
928
+ const result = await this.recorder.stopRecording(10, (base64) => this.wasmUtil.encryptImage(base64), (buffer) => this.wasmUtil.ckvcks(buffer));
929
+ if (!this.sessionToken) return { recordingId: null };
930
+ return { recordingId: await uploadDeepsightVideo(result.encryptedVideo, this.sessionToken) };
931
+ }
932
+ async stopAndGetVideo() {
933
+ if (!this.recorder.isRecording) return { videoBase64: void 0 };
934
+ try {
935
+ const videoBase64 = (await this.recorder.stopRecording(10, (base64) => base64, () => {})).encryptedVideo;
936
+ return { videoBase64: videoBase64 ? videoBase64 : void 0 };
937
+ } catch {
938
+ return { videoBase64: void 0 };
939
+ }
940
+ }
941
+ cleanup() {
942
+ this.recorder.reset();
943
+ }
944
+ };
945
+ /**
946
+ * Records through OpenVidu and manages the session lifecycle.
947
+ */
948
+ var OpenViduRecordingService = class {
949
+ constructor(config) {
950
+ this.config = config;
951
+ }
952
+ async start(stream) {
953
+ if (!this.provider) {
954
+ const { OpenViduRecordingProvider } = await loadOpenViduProviderModule();
955
+ this.provider = new OpenViduRecordingProvider();
956
+ }
957
+ this.session = await startRecordingSession({
958
+ config: {
959
+ ...this.config,
960
+ recording: { capability: this.provider }
961
+ },
962
+ clonedStream: stream.clone(),
963
+ existing: this.session
964
+ });
965
+ }
966
+ async stop() {
967
+ if (this.session) {
968
+ stopRecording(this.session);
969
+ this.session = void 0;
970
+ }
971
+ return { recordingId: null };
972
+ }
973
+ async stopAndGetVideo() {
974
+ if (this.session) {
975
+ stopRecording(this.session);
976
+ this.session = void 0;
977
+ }
978
+ return { videoBase64: void 0 };
979
+ }
980
+ cleanup() {
981
+ if (this.session) stopRecording(this.session);
982
+ }
983
+ };
984
+ /**
985
+ * Creates the recording service for the current configuration.
986
+ *
987
+ * Order of precedence:
988
+ * 1. `onDeviceFaceResultsSubmissionEnabled === true` → no recording. The
989
+ * on-device workflow never uploads media, only the staged face-results
990
+ * JSON via `WebApi.postFaceResults`. Mirrors V1's
991
+ * `FaceFlowManager.setRecorders()` early return.
992
+ * 2. `deepsightLiveness === 'VIDEOLIVENESS'` → local Deepsight recorder.
993
+ * 3. `enableFaceRecording === true` → server-side OpenVidu recorder.
994
+ * 4. otherwise → no recording.
995
+ */
996
+ function createRecordingService(params) {
997
+ if (params.config.onDeviceFaceResultsSubmissionEnabled === true) return;
998
+ if (params.config.deepsightLiveness === "VIDEOLIVENESS") return new LocalRecordingService(params.wasmUtil, params.sessionToken);
999
+ if (params.config.enableFaceRecording === true) return new OpenViduRecordingService(params.config);
1000
+ }
1001
+
1002
+ //#endregion
1003
+ export { stopRecording$1 as _, StreamCanvasCapture as a, initializeDeepsightSession as c, stopStream as d, processFace as f, startRecording as g, createRecordingSession as h, flagIdManualReview as i, sendLabelInspectionEvent as l, FACE_ERROR_CODES as m, preloadOpenViduProvider as n, encryptSelfieImage as o, uploadSelfie as p, flagFaceManualReview as r, initializeCamera as s, createRecordingService as t, startDetection as u, StreamCanvasProcessingSession as v };