@incodetech/core 0.0.0-dev-20260911-aec162f0 → 0.0.0-dev-20260914-8aef7789
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/dist/{FaceDetectionProvider-Cn1wS-sA.d.ts → BaseWasmProvider-CO0GfaHM.d.ts} +7 -37
- package/dist/{BrowserDiagnosticsCryptoProvider-8sT0QLgq.esm.js → BrowserDiagnosticsCryptoProvider-BoYzmYY5.esm.js} +1 -1
- package/dist/{onDeviceFaceResults-hle2Ci9l.esm.js → FaceDetectionProvider-0bWjPgW5.esm.js} +219 -340
- package/dist/FaceDetectionProvider-CyLxkzRP.d.ts +36 -0
- package/dist/{IIdCaptureCapability-DDWlQzhi.d.ts → IIdCaptureCapability-nfpic2z2.d.ts} +7 -3
- package/dist/{IWasmUtilCapability-SNPhmIwB.d.ts → IWasmUtilCapability-DaP6pfHq.d.ts} +10 -4
- package/dist/{MotionSensorProvider-Vlyhbcty.esm.js → MotionSensorProvider-BnZ8_1Sk.esm.js} +1 -1
- package/dist/{StreamCanvasCapture-D2XcXCZ4.esm.js → StreamCanvasCapture-C9jtgBdT.esm.js} +2 -2
- package/dist/{deepsightService-MZOpj7Vp.d.ts → StreamCanvasCapture-D9Dz8kqB.d.ts} +54 -41
- package/dist/ae-signature.esm.js +1 -1
- package/dist/{apiError-XdhqSAmg.esm.js → apiError-CixFeCyt.esm.js} +1 -1
- package/dist/authentication.d.ts +3 -3
- package/dist/authentication.esm.js +2 -2
- package/dist/{authenticationManager-DqBOkMzk.esm.js → authenticationManager-CN26fkJa.esm.js} +4 -4
- package/dist/{authenticationManager-BCkV6CSG.d.ts → authenticationManager-D7UUqgnN.d.ts} +1 -1
- package/dist/{authenticationStateMachine-Cto_G5bN.esm.js → authenticationStateMachine-CUXpIxAD.esm.js} +6 -62
- package/dist/avatar.d.ts +1 -1
- package/dist/avatar.esm.js +1 -1
- package/dist/{backCameraStream-DE_5qY04.esm.js → backCameraStream-BOtyQowf.esm.js} +75 -18
- package/dist/{camera-_2sXMXiF.esm.js → camera-sIa9ceW2.esm.js} +19 -1
- package/dist/camera.esm.js +1 -1
- package/dist/{canvas-E1zGkel4.esm.js → canvas-BxFzWTt-.esm.js} +19 -0
- package/dist/createCameraCycleOwnership-DQ5-F2oW.esm.js +826 -0
- package/dist/{createFaceAvatar-DQKaRise.esm.js → createFaceAvatar-BNHdeFj8.esm.js} +2 -2
- package/dist/{createFaceAvatar-pUEkdk4X.d.ts → createFaceAvatar-CTM9aj9Q.d.ts} +12 -6
- package/dist/curp-validation.d.ts +1 -1
- package/dist/{curpValidationManager-cSd2MrOQ.d.ts → curpValidationManager-CTJB2RsD.d.ts} +1 -1
- package/dist/{deepsightLoader-Dwr1zKFa.esm.js → deepsightLoader-Dhz9T_KJ.esm.js} +19 -53
- package/dist/document-capture.esm.js +2 -2
- package/dist/{documentCaptureManager-BTpHZMgW.esm.js → documentCaptureManager-BwcbMwo5.esm.js} +1 -1
- package/dist/{documentCaptureStateMachine-CPizkpcg.esm.js → documentCaptureStateMachine-F8SCOtL_.esm.js} +4 -4
- package/dist/dynamic-forms.esm.js +2 -2
- package/dist/{dynamicFormsManager-Cmh84Nz4.esm.js → dynamicFormsManager-CNBrBOR3.esm.js} +1 -1
- package/dist/{dynamicFormsStateMachine-DZr7Ugvy.esm.js → dynamicFormsStateMachine-Bo2qrjHB.esm.js} +1 -1
- package/dist/ekyb.d.ts +1 -1
- package/dist/ekyb.esm.js +3 -3
- package/dist/{ekybManager-Dc2tT9fu.esm.js → ekybManager-D8DdfRAD.esm.js} +1 -1
- package/dist/{ekybStateMachine-GSEMOiHn.esm.js → ekybStateMachine-oPCbEFob.esm.js} +1 -1
- package/dist/electronic-signature.esm.js +1 -1
- package/dist/{electronicSignatureManager-CpLuqw7T.esm.js → electronicSignatureManager-DkKQ07vx.esm.js} +1 -1
- package/dist/extensibility.d.ts +11 -58
- package/dist/extensibility.esm.js +13 -13
- package/dist/{faceCaptureManagerFactory-kDmbL0I7.esm.js → faceCaptureManagerFactory-D_EjQnnE.esm.js} +19 -4
- package/dist/{faceCaptureManagerFactory-CzUr_ZPq.d.ts → faceCaptureManagerFactory-DqrYpjA5.d.ts} +24 -12
- package/dist/{faceCaptureSetup-CAGBnLVx.esm.js → faceCaptureSetup-WeO8-TfR.esm.js} +999 -382
- package/dist/{feature-management-B6CtmH1O.esm.js → feature-management-BEqf3Sr3.esm.js} +1 -1
- package/dist/feature-management.esm.js +1 -1
- package/dist/fiscal-qr.esm.js +1 -1
- package/dist/{fiscalQrManager-DI6uOffY.esm.js → fiscalQrManager-Bp_-3LJr.esm.js} +3 -3
- package/dist/flow-events.d.ts +1 -1
- package/dist/flow.d.ts +6 -6
- package/dist/flow.esm.js +3 -3
- package/dist/{flowCompletionService-BpoZDpAn.esm.js → flowCompletionService-DELbVeL5.esm.js} +1 -1
- package/dist/{flowServices-BVnSStkh.esm.js → flowServices-Brr2fh_c.esm.js} +5 -5
- package/dist/geolocation.esm.js +2 -2
- package/dist/{geolocationManager-CLm86P8G.esm.js → geolocationManager-CtVZDjng.esm.js} +1 -1
- package/dist/{geolocationStateMachine-Bi3vy7Wl.esm.js → geolocationStateMachine-tjsYcMhr.esm.js} +1 -1
- package/dist/home.d.ts +1 -1
- package/dist/id-selfie-flow.d.ts +3 -3
- package/dist/id-selfie-flow.esm.js +10 -10
- package/dist/id.d.ts +4 -4
- package/dist/id.esm.js +35 -44
- package/dist/{idCaptureDefaults-BLsd7shz.esm.js → idCaptureDefaults-C66YvkgN.esm.js} +19 -14
- package/dist/{idCaptureManager-DW1GeEUk.d.ts → idCaptureManager-DE_jyr5X.d.ts} +98 -37
- package/dist/{idCaptureManager-BUTdcmaD.esm.js → idCaptureManager-zjul9YdZ.esm.js} +27 -17
- package/dist/{idCaptureServices-fzIhBqAK.esm.js → idCaptureServices-UXYCBZPK.esm.js} +80 -20
- package/dist/{idCaptureStateMachine-Cp2_revF.esm.js → idCaptureStateMachine-D3pqfK2Z.esm.js} +1954 -1082
- package/dist/{index-1PoJuUJ-.d.ts → index-BGxFwnld.d.ts} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/mandatory-consent.d.ts +2 -2
- package/dist/{mandatoryConsentManager-BJnylLZO.d.ts → mandatoryConsentManager-CZwhsUlO.d.ts} +1 -1
- package/dist/{permissionGuards-DxbvOoZJ.esm.js → permissionGuards-o1JLtewE.esm.js} +1 -1
- package/dist/{permissionServices-f7nBnW5P.esm.js → permissionServices-7lzEiOsO.esm.js} +3 -3
- package/dist/personhood.d.ts +5 -5
- package/dist/personhood.esm.js +8 -8
- package/dist/qe-signature.esm.js +1 -1
- package/dist/{runChildModule-BPlX2IDO.esm.js → runChildModule-BDlvNMrA.esm.js} +1 -1
- package/dist/{safeStorage-Dp9m6aOh.esm.js → safeStorage-1O9k0ulP.esm.js} +8 -8
- package/dist/{sdkVersion-Dr9_E3d9.esm.js → sdkVersion-CS_0s_Lc.esm.js} +1 -1
- package/dist/selfie.d.ts +4 -4
- package/dist/selfie.esm.js +12 -74
- package/dist/{selfieManager-BdP-RgH4.esm.js → selfieManager-BouB9yUQ.esm.js} +4 -4
- package/dist/{selfieManager-Bg_Xwe4p.d.ts → selfieManager-DZ3u_WN9.d.ts} +1 -1
- package/dist/{selfieStateMachine-B8vFeT39.esm.js → selfieStateMachine-TGfI9hNp.esm.js} +22 -31
- package/dist/{session-C2THUsQZ.esm.js → session-m9j27bHm.esm.js} +3 -3
- package/dist/session.d.ts +1 -1
- package/dist/session.esm.js +4 -4
- package/dist/{sessionInitializer-CEycxhm4.esm.js → sessionInitializer-CUpgbHzs.esm.js} +4 -4
- package/dist/{setup-D6yz9se2.d.ts → setup-CEX95gJ1.d.ts} +11 -6
- package/dist/{setup-BHJ3-fhX.esm.js → setup-CfNAVG-d.esm.js} +12 -11
- package/dist/{trueSightService-DLzYznkh.esm.js → trueSightService-TqmmYye3.esm.js} +4 -4
- package/dist/types-BhHF-CuL.d.ts +6 -0
- package/dist/{types-DJ2OM9rw.d.ts → types-BzuUebkB.d.ts} +1 -1
- package/dist/{types-DzmqFoCH.d.ts → types-CBctcPeF.d.ts} +1 -1
- package/dist/{types-BBI4-s9u2.d.ts → types-CoOlCUp82.d.ts} +5 -5
- package/dist/{types-hSqUyXyw.d.ts → types-DL0CXuWv.d.ts} +3 -3
- package/dist/types-Ds928RiU.d.ts +1 -0
- package/dist/{types-_pWNFY1F.d.ts → types-eLtVBhon.d.ts} +1 -1
- package/dist/video-selfie.d.ts +3 -3
- package/dist/video-selfie.esm.js +5 -5
- package/dist/{videoSelfieCameraWarmer-D5E12WjL.esm.js → videoSelfieCameraWarmer-C-cESczy.esm.js} +9 -9
- package/dist/{videoSelfieStepDetector-B8TvFDNK.d.ts → videoSelfieStepDetector-CdXIFh9s.d.ts} +4 -4
- package/dist/virtualCameraCheck-WOloJ-do.esm.js +48 -0
- package/dist/{warmup-BOM-sD-6.esm.js → warmup-CUUnwYxe.esm.js} +282 -90
- package/dist/{warmup-CXHBgvFC.d.ts → warmup-Cis2p6O0.d.ts} +13 -2
- package/dist/wasm.d.ts +9 -3
- package/dist/wasm.esm.js +10 -4
- package/dist/{wasmDsFlagSync-C3k_VK9o.esm.js → wasmDsFlagSync-BJtLh2XK.esm.js} +1 -1
- package/dist/{wasmWebClient-BJCaFeBL.esm.js → wasmWebClient-B7baE-Wf.esm.js} +223 -2
- package/dist/workflow.d.ts +1 -1
- package/dist/workflow.esm.js +15 -15
- package/package.json +1 -1
- package/dist/imageFile-CLaua6xO.esm.js +0 -69
- package/dist/types-m4t_cT5J.d.ts +0 -6
- package/dist/{Face2DProvider-UUQt_vRC.esm.js → Face2DProvider-BF48sz5c.esm.js} +1 -1
- package/dist/{PrivacyLensProvider-D8PS7AJa.esm.js → PrivacyLensProvider-EwnC_C5n.esm.js} +1 -1
- package/dist/{selfieErrorUtils-C6gC06J7.esm.js → selfieErrorUtils-C77GXJH6.esm.js} +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as WasmPipeline } from "./warmup-
|
|
2
|
-
import { _ as MLProviderConfig
|
|
1
|
+
import { c as WasmPipeline } from "./warmup-Cis2p6O0.js";
|
|
2
|
+
import { _ as MLProviderConfig } from "./createFaceAvatar-CTM9aj9Q.js";
|
|
3
3
|
//#region ../infra/src/wasm/WasmPipelineType.d.ts
|
|
4
4
|
declare enum WasmPipelineType {
|
|
5
5
|
IdBlurGlarePipeline = 0,
|
|
@@ -7,7 +7,10 @@ declare enum WasmPipelineType {
|
|
|
7
7
|
IdVideoSelfiePipeline = 2,
|
|
8
8
|
SelfieWithAggregationMetrics = 3,
|
|
9
9
|
SelfieWithQualityMetrics = 4,
|
|
10
|
-
OnDeviceSelfieWorkflow = 5
|
|
10
|
+
OnDeviceSelfieWorkflow = 5,
|
|
11
|
+
IdBlurGlareCoreWorkflow = 6,
|
|
12
|
+
IdBarcodeAndTextQualityCoreWorkflow = 7,
|
|
13
|
+
IdFaceQualityCoreWorkflow = 8
|
|
11
14
|
}
|
|
12
15
|
//#endregion
|
|
13
16
|
//#region ../infra/src/providers/wasm/BaseWasmProvider.d.ts
|
|
@@ -59,37 +62,4 @@ declare abstract class BaseWasmProvider {
|
|
|
59
62
|
dispose(): Promise<void>;
|
|
60
63
|
}
|
|
61
64
|
//#endregion
|
|
62
|
-
|
|
63
|
-
declare class FaceDetectionProvider extends BaseWasmProvider implements IFaceDetectionCapability {
|
|
64
|
-
private defaultThresholds;
|
|
65
|
-
private currentThresholds;
|
|
66
|
-
private currentFrame;
|
|
67
|
-
private onFaceDataCallback;
|
|
68
|
-
constructor();
|
|
69
|
-
processFrame(image: ImageData): Promise<void>;
|
|
70
|
-
initialize(config: FaceDetectionConfig): Promise<void>;
|
|
71
|
-
/**
|
|
72
|
-
* Last-registered onCapture callback — captured into a private
|
|
73
|
-
* field so `forceCapture()` (called from outside the WASM-callback
|
|
74
|
-
* lifecycle) can re-fire the same wrapper. `setCallbacks` rebinds
|
|
75
|
-
* this on each invocation, so the field always reflects the
|
|
76
|
-
* current consumer.
|
|
77
|
-
*/
|
|
78
|
-
private currentOnCaptureWrapper;
|
|
79
|
-
processPhoto(canvas: HTMLCanvasElement): void;
|
|
80
|
-
postFaceResults(config?: WebApiHostRequestConfig): Promise<unknown>;
|
|
81
|
-
setCallbacks(callbacks: FaceDetectionCallbacks): void;
|
|
82
|
-
setPositionConstraints(constraints: FacePositionConstraints): void;
|
|
83
|
-
applyDefaults(autocaptureInterval?: number): void;
|
|
84
|
-
setAutocaptureInterval(interval: number): void;
|
|
85
|
-
setThresholds(thresholds: FaceDetectionThresholds): void;
|
|
86
|
-
setAttributesThresholds(thresholds: FaceAttributesThresholds): void;
|
|
87
|
-
setChecksEnabled(config: FaceChecksConfig): void;
|
|
88
|
-
setVideoSelfieMode(enabled: boolean): void;
|
|
89
|
-
forceCapture(): void;
|
|
90
|
-
reset(): void;
|
|
91
|
-
private createDefaultFaceCoordinates;
|
|
92
|
-
private formatFaceCoordinates;
|
|
93
|
-
}
|
|
94
|
-
//#endregion
|
|
95
|
-
export { BaseWasmProvider as n, FaceDetectionProvider as t };
|
|
65
|
+
export { BaseWasmProvider as t };
|
|
@@ -18,7 +18,7 @@ function decodeTruesightKey(s0Base64, s1Base64) {
|
|
|
18
18
|
*/
|
|
19
19
|
function getTruesightKey() {
|
|
20
20
|
try {
|
|
21
|
-
const key = decodeTruesightKey("
|
|
21
|
+
const key = decodeTruesightKey("otyKosLQyND3E+A5iFHGX1TE2atuG6t36WCf3aVSleQ=", "oN7U9FX22geH2kWrWh68jSat2HWXYRQl1DMvbbqpiHQ=");
|
|
22
22
|
return key.length === KEY_LENGTH_BYTES ? key : null;
|
|
23
23
|
} catch {
|
|
24
24
|
return null;
|
|
@@ -1,17 +1,215 @@
|
|
|
1
|
-
import { t as ensureWasmPipelines } from "./setup-
|
|
2
|
-
import { s as wasmRuntime } from "./warmup-
|
|
3
|
-
import { i as BaseWasmProvider } from "./safeStorage-
|
|
4
|
-
import { r as
|
|
5
|
-
import
|
|
6
|
-
import { v as yieldUntilNextPaint } from "./sessionInitializer-CEycxhm4.esm.js";
|
|
1
|
+
import { t as ensureWasmPipelines } from "./setup-CfNAVG-d.esm.js";
|
|
2
|
+
import { s as wasmRuntime } from "./warmup-CUUnwYxe.esm.js";
|
|
3
|
+
import { i as BaseWasmProvider } from "./safeStorage-1O9k0ulP.esm.js";
|
|
4
|
+
import { c as trueSightHintTransition, r as noteTrueSightCaptureActivity } from "./trueSightService-TqmmYye3.esm.js";
|
|
5
|
+
import "./sessionInitializer-CUpgbHzs.esm.js";
|
|
7
6
|
import { t as addDeviceStats } from "./stats-DkK-f8JT.esm.js";
|
|
8
7
|
import { c as isIPhone14OrHigher, i as isDesktop } from "./platform-DkcRc9JV.esm.js";
|
|
9
|
-
import {
|
|
10
|
-
import { t as
|
|
11
|
-
import { t as IncodeCanvas } from "./canvas-E1zGkel4.esm.js";
|
|
8
|
+
import { i as requestCameraAccess, o as stopCameraStream, r as getCameraReacquisitionConstraints } from "./camera-sIa9ceW2.esm.js";
|
|
9
|
+
import { t as IncodeCanvas } from "./canvas-BxFzWTt-.esm.js";
|
|
12
10
|
import { a as StreamCanvasProcessingSession, n as startRecording, r as stopRecording$1, t as createRecordingSession } from "./recordingsRepository-CCWy13M-.esm.js";
|
|
13
|
-
import { i as hasBackCamera, n as getBackCameraStream, r as getDesktopCameraStream, t as ensureFrontCameraStream } from "./backCameraStream-
|
|
11
|
+
import { i as hasBackCamera, n as getBackCameraStream, r as getDesktopCameraStream, t as ensureFrontCameraStream } from "./backCameraStream-BOtyQowf.esm.js";
|
|
12
|
+
//#region src/internal/faceCapture/onDeviceFaceResults.ts
|
|
13
|
+
/**
|
|
14
|
+
* On-device still-face capture is owned by the protected camera-cycle actor.
|
|
15
|
+
* Core uses this guard only to select the backwards-compatible validation and
|
|
16
|
+
* processing behavior after the native actor posts completion-only results.
|
|
17
|
+
*/
|
|
18
|
+
const isOnDeviceMode = (config) => config.onDeviceFaceResultsSubmissionEnabled === true;
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/internal/faceCapture/faceCaptureServices.ts
|
|
21
|
+
function sendLabelInspectionEvent() {
|
|
22
|
+
return addDeviceStats({ cameraLabelInspectionStatus: "FAIL" });
|
|
23
|
+
}
|
|
24
|
+
const MOBILE_SELFIE_CONSTRAINTS = {
|
|
25
|
+
video: {
|
|
26
|
+
facingMode: "user",
|
|
27
|
+
height: { ideal: 480 },
|
|
28
|
+
width: { ideal: 640 }
|
|
29
|
+
},
|
|
30
|
+
audio: false
|
|
31
|
+
};
|
|
32
|
+
const IPHONE14_SELFIE_CONSTRAINTS = {
|
|
33
|
+
video: { height: { ideal: 1080 } },
|
|
34
|
+
audio: false
|
|
35
|
+
};
|
|
36
|
+
function buildCameraConstraints(resolution, deviceId) {
|
|
37
|
+
if (resolution) return {
|
|
38
|
+
video: {
|
|
39
|
+
facingMode: "user",
|
|
40
|
+
deviceId: deviceId ? { exact: deviceId } : void 0,
|
|
41
|
+
height: resolution.height ? { ideal: resolution.height } : void 0,
|
|
42
|
+
width: resolution.width ? { ideal: resolution.width } : void 0
|
|
43
|
+
},
|
|
44
|
+
audio: false
|
|
45
|
+
};
|
|
46
|
+
if (isIPhone14OrHigher()) return IPHONE14_SELFIE_CONSTRAINTS;
|
|
47
|
+
return MOBILE_SELFIE_CONSTRAINTS;
|
|
48
|
+
}
|
|
49
|
+
function stopStream(stream) {
|
|
50
|
+
stopCameraStream(stream);
|
|
51
|
+
}
|
|
52
|
+
async function getFrontCameraStream(resolution) {
|
|
53
|
+
if (isDesktop()) {
|
|
54
|
+
if (resolution) return ensureFrontCameraStream((deviceId) => requestCameraAccess(buildCameraConstraints(resolution, deviceId)));
|
|
55
|
+
return ensureFrontCameraStream((deviceId) => getDesktopCameraStream(deviceId ? { deviceId } : {}));
|
|
56
|
+
}
|
|
57
|
+
return requestCameraAccess(resolution ? buildCameraConstraints(resolution) : buildCameraConstraints());
|
|
58
|
+
}
|
|
59
|
+
async function initializeCamera(params) {
|
|
60
|
+
const { config } = params;
|
|
61
|
+
await ensureWasmPipelines([isOnDeviceMode(config) ? "onDeviceSelfie" : "selfie"]);
|
|
62
|
+
const usingBackCamera = config.assistedOnboarding === true && await hasBackCamera();
|
|
63
|
+
const backCamera = usingBackCamera ? await getBackCameraStream() : void 0;
|
|
64
|
+
const stream = backCamera?.stream ?? await getFrontCameraStream(config.cameraResolution);
|
|
65
|
+
const constraints = getCameraReacquisitionConstraints(stream.getVideoTracks()[0], backCamera?.constraints);
|
|
66
|
+
return {
|
|
67
|
+
stream,
|
|
68
|
+
provider: params.provider,
|
|
69
|
+
usingBackCamera,
|
|
70
|
+
constraints
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Encrypts the provided selfie image using WASM.
|
|
75
|
+
*/
|
|
76
|
+
async function encryptSelfieImage({ canvas, dependencies }) {
|
|
77
|
+
const base64Image = canvas.getBase64Image();
|
|
78
|
+
if (!base64Image) throw new Error("Canvas image is empty or null");
|
|
79
|
+
return (await dependencies.getWasmUtil()).encryptImage(base64Image);
|
|
80
|
+
}
|
|
81
|
+
function startDetection(params) {
|
|
82
|
+
let lastStatus;
|
|
83
|
+
let session;
|
|
84
|
+
const { provider } = params;
|
|
85
|
+
const setStatus = (status) => {
|
|
86
|
+
if (session?.isDisposed() === true) return;
|
|
87
|
+
if (lastStatus === status) return;
|
|
88
|
+
lastStatus = status;
|
|
89
|
+
trueSightHintTransition("module.face-capture", "faceScan", status);
|
|
90
|
+
params.onUpdate(status);
|
|
91
|
+
};
|
|
92
|
+
const stopDetectionLoop = () => {
|
|
93
|
+
session?.dispose();
|
|
94
|
+
noteTrueSightCaptureActivity(false);
|
|
95
|
+
};
|
|
96
|
+
const reset = () => {
|
|
97
|
+
provider.reset();
|
|
98
|
+
};
|
|
99
|
+
const cleanup = () => {
|
|
100
|
+
stopDetectionLoop();
|
|
101
|
+
};
|
|
102
|
+
(async () => {
|
|
103
|
+
try {
|
|
104
|
+
provider.setCallbacks({
|
|
105
|
+
onFarAway: () => setStatus("tooFar"),
|
|
106
|
+
onTooClose: () => setStatus("tooClose"),
|
|
107
|
+
onTooManyFaces: () => setStatus("tooManyFaces"),
|
|
108
|
+
onNoFace: () => setStatus("idle"),
|
|
109
|
+
onCenterFace: () => setStatus("centerFace"),
|
|
110
|
+
onGetReady: () => setStatus("getReady"),
|
|
111
|
+
onGetReadyFinished: () => setStatus("getReadyFinished"),
|
|
112
|
+
onDark: () => {
|
|
113
|
+
if (params.config.validateBrightness) setStatus("dark");
|
|
114
|
+
},
|
|
115
|
+
onBlur: () => setStatus("blur"),
|
|
116
|
+
onFaceAngle: () => setStatus("faceAngle"),
|
|
117
|
+
onLenses: () => {
|
|
118
|
+
if (params.config.validateLenses) setStatus("lenses");
|
|
119
|
+
},
|
|
120
|
+
onMask: () => {
|
|
121
|
+
if (params.config.validateFaceMask) setStatus("faceMask");
|
|
122
|
+
},
|
|
123
|
+
onEyesClosed: () => {
|
|
124
|
+
if (params.config.validateClosedEyes) setStatus("eyesClosed");
|
|
125
|
+
},
|
|
126
|
+
onHeadWear: () => {
|
|
127
|
+
if (params.config.validateHeadCover) setStatus("headWear");
|
|
128
|
+
},
|
|
129
|
+
onFaceOccluded: () => setStatus("faceOcclusion"),
|
|
130
|
+
onFaceData: params.onPose,
|
|
131
|
+
onSwitchToManualCapture: () => {
|
|
132
|
+
setStatus("manualCapture");
|
|
133
|
+
stopDetectionLoop();
|
|
134
|
+
},
|
|
135
|
+
onCapture: (canvas, faceCoordinates) => {
|
|
136
|
+
setStatus("success");
|
|
137
|
+
params.onSuccess(canvas, faceCoordinates);
|
|
138
|
+
cleanup();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
setStatus("detecting");
|
|
142
|
+
session = new StreamCanvasProcessingSession({
|
|
143
|
+
capturer: params.capturer,
|
|
144
|
+
provider,
|
|
145
|
+
onFrame: params.onFrame
|
|
146
|
+
});
|
|
147
|
+
noteTrueSightCaptureActivity(true);
|
|
148
|
+
} catch {
|
|
149
|
+
setStatus("error");
|
|
150
|
+
cleanup();
|
|
151
|
+
}
|
|
152
|
+
})();
|
|
153
|
+
return {
|
|
154
|
+
cleanup,
|
|
155
|
+
reset
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function buildResolutionFromStream(stream) {
|
|
159
|
+
const track = stream.getVideoTracks()[0];
|
|
160
|
+
if (!track) return;
|
|
161
|
+
const settings = track.getSettings();
|
|
162
|
+
const width = settings.width;
|
|
163
|
+
const height = settings.height;
|
|
164
|
+
if (typeof width === "number" && typeof height === "number") return `${width}x${height}`;
|
|
165
|
+
}
|
|
166
|
+
async function startRecordingSession(params) {
|
|
167
|
+
if (params.config.deepsightLiveness === "VIDEOLIVENESS") return;
|
|
168
|
+
if (params.config.enableFaceRecording !== true) return;
|
|
169
|
+
if (params.existing) return params.existing;
|
|
170
|
+
const provider = params.config.recording?.capability;
|
|
171
|
+
if (!provider) return;
|
|
172
|
+
const clonedStream = params.clonedStream;
|
|
173
|
+
const hasAudio = clonedStream.getAudioTracks().length > 0;
|
|
174
|
+
const resolution = buildResolutionFromStream(clonedStream);
|
|
175
|
+
const session = await createRecordingSession("selfie");
|
|
176
|
+
const connection = await provider.connect({
|
|
177
|
+
sessionToken: session.token,
|
|
178
|
+
stream: clonedStream,
|
|
179
|
+
events: {}
|
|
180
|
+
});
|
|
181
|
+
await startRecording({
|
|
182
|
+
videoRecordingId: session.videoRecordingId,
|
|
183
|
+
type: "selfie",
|
|
184
|
+
resolution,
|
|
185
|
+
hasAudio
|
|
186
|
+
});
|
|
187
|
+
return {
|
|
188
|
+
token: session.token,
|
|
189
|
+
sessionId: session.sessionId,
|
|
190
|
+
videoRecordingId: session.videoRecordingId,
|
|
191
|
+
connection,
|
|
192
|
+
resolution,
|
|
193
|
+
hasAudio
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
async function stopRecording(session) {
|
|
197
|
+
try {
|
|
198
|
+
await stopRecording$1(session.videoRecordingId);
|
|
199
|
+
} finally {
|
|
200
|
+
await session.connection.disconnect();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
async function initializeDeepsightSession(options) {
|
|
204
|
+
const { loadDeepsightSession } = await import("./deepsightLoader-Dhz9T_KJ.esm.js");
|
|
205
|
+
return loadDeepsightSession({
|
|
206
|
+
ds: options.ds,
|
|
207
|
+
storage: options.storage
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
//#endregion
|
|
14
211
|
//#region ../infra/src/wasm/faceProcessingWasmApi.ts
|
|
212
|
+
const PROCESS_PHOTO_UNSUPPORTED_ERROR = "[Incode SDK] processPhoto is unsupported by ml-wasm-kit v2.14.49-post1.";
|
|
15
213
|
var FaceProcessingWasmApi = class {
|
|
16
214
|
constructor(runtime = wasmRuntime) {
|
|
17
215
|
this.runtime = runtime;
|
|
@@ -35,15 +233,12 @@ var FaceProcessingWasmApi = class {
|
|
|
35
233
|
this.runtime.requireFaceProcessingApi("Unable to set face detection callbacks, cpp API hasn't been initialized").setFaceProcessingCallbacks(this.runtime.pipelineTypeToWasmEnum(type), onFarAway, onTooClose, onTooManyFaces, onNoFace, onCapture, onGetReady, onGetReadyFinished, onCenterFace, onDark, onBlur, onFaceAngle, onLenses, onMask, onEyesClosed, onHeadWear, onSwitchToManualCapture, onFaceOccluded);
|
|
36
234
|
}
|
|
37
235
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* for the next {@link postFaceResults} call. No polling, no semaphore wrap.
|
|
42
|
-
*
|
|
43
|
-
* Mirrors `ml-wasm-kit/WasmApi.processPhoto`.
|
|
236
|
+
* @deprecated Removed from ml-wasm-kit v2.14.49-post1. The signature stays
|
|
237
|
+
* available for source compatibility, but the canvas never reaches native
|
|
238
|
+
* code; protected manual capture is owned by the camera-cycle facade.
|
|
44
239
|
*/
|
|
45
|
-
processPhoto(
|
|
46
|
-
|
|
240
|
+
processPhoto(_canvas) {
|
|
241
|
+
throw new Error(PROCESS_PHOTO_UNSUPPORTED_ERROR);
|
|
47
242
|
}
|
|
48
243
|
/**
|
|
49
244
|
* POSTs the staged on-device face-results JSON to `/omni/add/face-results`
|
|
@@ -57,7 +252,7 @@ var FaceProcessingWasmApi = class {
|
|
|
57
252
|
* `initialize()`. The C++ `OnDeviceSelfieWorkflow` has already staged the
|
|
58
253
|
* aggregated best-shot results into that instance via
|
|
59
254
|
* `WebApi::setFaceResults(...)` during per-frame processing (auto-capture) or
|
|
60
|
-
*
|
|
255
|
+
* through the protected camera-cycle manual-capture path.
|
|
61
256
|
*/
|
|
62
257
|
postFaceResults(config) {
|
|
63
258
|
return this.runtime.requireWebApi("Unable to post face results, cpp API hasn't been initialized").postFaceResults(config ?? {});
|
|
@@ -68,7 +263,10 @@ var FaceProcessingWasmApi = class {
|
|
|
68
263
|
*/
|
|
69
264
|
async runSelfieCapture(image) {
|
|
70
265
|
const faceProcessingWasmApi = this.runtime.requireFaceProcessingApi("Unable to run Selfie Capture, cpp API hasn't been initialized");
|
|
71
|
-
|
|
266
|
+
if (image) {
|
|
267
|
+
await this.runtime.allocateImageBuffers(image.width, image.height);
|
|
268
|
+
this.runtime.writeFrame(image);
|
|
269
|
+
}
|
|
72
270
|
return faceProcessingWasmApi.runSelfieCapture();
|
|
73
271
|
}
|
|
74
272
|
};
|
|
@@ -145,7 +343,6 @@ var FaceDetectionProvider = class extends BaseWasmProvider {
|
|
|
145
343
|
if (config.videoSelfie === true) this.setVideoSelfieMode(true);
|
|
146
344
|
}
|
|
147
345
|
processPhoto(canvas) {
|
|
148
|
-
this.ensureInitialized();
|
|
149
346
|
faceProcessingWasmApi.processPhoto(canvas);
|
|
150
347
|
}
|
|
151
348
|
async postFaceResults(config) {
|
|
@@ -274,322 +471,4 @@ var FaceDetectionProvider = class extends BaseWasmProvider {
|
|
|
274
471
|
}
|
|
275
472
|
};
|
|
276
473
|
//#endregion
|
|
277
|
-
|
|
278
|
-
const ONDEVICE_AUTOCAPTURE_INTERVAL_MS = 2147483647;
|
|
279
|
-
function sendLabelInspectionEvent() {
|
|
280
|
-
return addDeviceStats({ cameraLabelInspectionStatus: "FAIL" });
|
|
281
|
-
}
|
|
282
|
-
const MOBILE_SELFIE_CONSTRAINTS = {
|
|
283
|
-
video: {
|
|
284
|
-
facingMode: "user",
|
|
285
|
-
height: { ideal: 480 },
|
|
286
|
-
width: { ideal: 640 }
|
|
287
|
-
},
|
|
288
|
-
audio: false
|
|
289
|
-
};
|
|
290
|
-
const IPHONE14_SELFIE_CONSTRAINTS = {
|
|
291
|
-
video: { height: { ideal: 1080 } },
|
|
292
|
-
audio: false
|
|
293
|
-
};
|
|
294
|
-
function buildCameraConstraints(resolution, deviceId) {
|
|
295
|
-
if (resolution) return {
|
|
296
|
-
video: {
|
|
297
|
-
facingMode: "user",
|
|
298
|
-
deviceId: deviceId ? { exact: deviceId } : void 0,
|
|
299
|
-
height: resolution.height ? { ideal: resolution.height } : void 0,
|
|
300
|
-
width: resolution.width ? { ideal: resolution.width } : void 0
|
|
301
|
-
},
|
|
302
|
-
audio: false
|
|
303
|
-
};
|
|
304
|
-
if (isIPhone14OrHigher()) return IPHONE14_SELFIE_CONSTRAINTS;
|
|
305
|
-
return MOBILE_SELFIE_CONSTRAINTS;
|
|
306
|
-
}
|
|
307
|
-
function stopStream(stream) {
|
|
308
|
-
stopCameraStream(stream);
|
|
309
|
-
}
|
|
310
|
-
async function getFrontCameraStream(resolution) {
|
|
311
|
-
if (isDesktop()) {
|
|
312
|
-
if (resolution) return ensureFrontCameraStream((deviceId) => requestCameraAccess(buildCameraConstraints(resolution, deviceId)));
|
|
313
|
-
return ensureFrontCameraStream((deviceId) => getDesktopCameraStream(deviceId ? { deviceId } : {}));
|
|
314
|
-
}
|
|
315
|
-
return requestCameraAccess(resolution ? buildCameraConstraints(resolution) : buildCameraConstraints());
|
|
316
|
-
}
|
|
317
|
-
async function initializeCamera(params) {
|
|
318
|
-
const { config } = params;
|
|
319
|
-
const prcConstraints = buildCameraConstraints(config.cameraResolution);
|
|
320
|
-
await ensureWasmPipelines([isOnDeviceMode(config) ? "onDeviceSelfie" : "selfie"]);
|
|
321
|
-
const provider = new FaceDetectionProvider();
|
|
322
|
-
await provider.initialize({
|
|
323
|
-
autocaptureInterval: isOnDeviceMode(config) ? ONDEVICE_AUTOCAPTURE_INTERVAL_MS : config.autoCaptureTimeout * 1e3,
|
|
324
|
-
useOnDeviceWorkflow: config.onDeviceFaceResultsSubmissionEnabled === true
|
|
325
|
-
});
|
|
326
|
-
provider.setChecksEnabled({
|
|
327
|
-
lenses: config.validateLenses ?? false,
|
|
328
|
-
mask: config.validateFaceMask ?? false,
|
|
329
|
-
closedEyes: config.validateClosedEyes ?? false,
|
|
330
|
-
headWear: config.validateHeadCover ?? false,
|
|
331
|
-
occlusion: false
|
|
332
|
-
});
|
|
333
|
-
await params.deepsightService.performPrcCheck({ constraints: { video: prcConstraints.video } });
|
|
334
|
-
const usingBackCamera = config.assistedOnboarding === true && await hasBackCamera();
|
|
335
|
-
return {
|
|
336
|
-
stream: usingBackCamera ? (await getBackCameraStream()).stream : await getFrontCameraStream(config.cameraResolution),
|
|
337
|
-
provider,
|
|
338
|
-
usingBackCamera
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Encrypts the provided selfie image using WASM.
|
|
343
|
-
*/
|
|
344
|
-
async function encryptSelfieImage({ canvas, dependencies }) {
|
|
345
|
-
const base64Image = canvas.getBase64Image();
|
|
346
|
-
if (!base64Image) throw new Error("Canvas image is empty or null");
|
|
347
|
-
return (await dependencies.getWasmUtil()).encryptImage(base64Image);
|
|
348
|
-
}
|
|
349
|
-
function startDetection(params) {
|
|
350
|
-
let lastStatus;
|
|
351
|
-
let session;
|
|
352
|
-
const { provider } = params;
|
|
353
|
-
const setStatus = (status) => {
|
|
354
|
-
if (session?.isDisposed() === true) return;
|
|
355
|
-
if (lastStatus === status) return;
|
|
356
|
-
lastStatus = status;
|
|
357
|
-
trueSightHintTransition("module.face-capture", "faceScan", status);
|
|
358
|
-
params.onUpdate(status);
|
|
359
|
-
};
|
|
360
|
-
const stopDetectionLoop = () => {
|
|
361
|
-
session?.dispose();
|
|
362
|
-
noteTrueSightCaptureActivity(false);
|
|
363
|
-
};
|
|
364
|
-
const reset = () => {
|
|
365
|
-
provider.reset();
|
|
366
|
-
};
|
|
367
|
-
const cleanup = () => {
|
|
368
|
-
stopDetectionLoop();
|
|
369
|
-
};
|
|
370
|
-
(async () => {
|
|
371
|
-
try {
|
|
372
|
-
provider.setCallbacks({
|
|
373
|
-
onFarAway: () => setStatus("tooFar"),
|
|
374
|
-
onTooClose: () => setStatus("tooClose"),
|
|
375
|
-
onTooManyFaces: () => setStatus("tooManyFaces"),
|
|
376
|
-
onNoFace: () => setStatus("idle"),
|
|
377
|
-
onCenterFace: () => setStatus("centerFace"),
|
|
378
|
-
onGetReady: () => setStatus("getReady"),
|
|
379
|
-
onGetReadyFinished: () => setStatus("getReadyFinished"),
|
|
380
|
-
onDark: () => {
|
|
381
|
-
if (params.config.validateBrightness) setStatus("dark");
|
|
382
|
-
},
|
|
383
|
-
onBlur: () => setStatus("blur"),
|
|
384
|
-
onFaceAngle: () => setStatus("faceAngle"),
|
|
385
|
-
onLenses: () => {
|
|
386
|
-
if (params.config.validateLenses) setStatus("lenses");
|
|
387
|
-
},
|
|
388
|
-
onMask: () => {
|
|
389
|
-
if (params.config.validateFaceMask) setStatus("faceMask");
|
|
390
|
-
},
|
|
391
|
-
onEyesClosed: () => {
|
|
392
|
-
if (params.config.validateClosedEyes) setStatus("eyesClosed");
|
|
393
|
-
},
|
|
394
|
-
onHeadWear: () => {
|
|
395
|
-
if (params.config.validateHeadCover) setStatus("headWear");
|
|
396
|
-
},
|
|
397
|
-
onFaceOccluded: () => setStatus("faceOcclusion"),
|
|
398
|
-
onFaceData: params.onPose,
|
|
399
|
-
onSwitchToManualCapture: () => {
|
|
400
|
-
setStatus("manualCapture");
|
|
401
|
-
stopDetectionLoop();
|
|
402
|
-
},
|
|
403
|
-
onCapture: (canvas, faceCoordinates) => {
|
|
404
|
-
setStatus("success");
|
|
405
|
-
params.onSuccess(canvas, faceCoordinates);
|
|
406
|
-
cleanup();
|
|
407
|
-
}
|
|
408
|
-
});
|
|
409
|
-
setStatus("detecting");
|
|
410
|
-
session = new StreamCanvasProcessingSession({
|
|
411
|
-
capturer: params.capturer,
|
|
412
|
-
provider,
|
|
413
|
-
onFrame: params.onFrame
|
|
414
|
-
});
|
|
415
|
-
noteTrueSightCaptureActivity(true);
|
|
416
|
-
} catch {
|
|
417
|
-
setStatus("error");
|
|
418
|
-
cleanup();
|
|
419
|
-
}
|
|
420
|
-
})();
|
|
421
|
-
return {
|
|
422
|
-
cleanup,
|
|
423
|
-
reset
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
function buildResolutionFromStream(stream) {
|
|
427
|
-
const track = stream.getVideoTracks()[0];
|
|
428
|
-
if (!track) return;
|
|
429
|
-
const settings = track.getSettings();
|
|
430
|
-
const width = settings.width;
|
|
431
|
-
const height = settings.height;
|
|
432
|
-
if (typeof width === "number" && typeof height === "number") return `${width}x${height}`;
|
|
433
|
-
}
|
|
434
|
-
async function startRecordingSession(params) {
|
|
435
|
-
if (params.config.deepsightLiveness === "VIDEOLIVENESS") return;
|
|
436
|
-
if (params.config.enableFaceRecording !== true) return;
|
|
437
|
-
if (params.existing) return params.existing;
|
|
438
|
-
const provider = params.config.recording?.capability;
|
|
439
|
-
if (!provider) return;
|
|
440
|
-
const clonedStream = params.clonedStream;
|
|
441
|
-
const hasAudio = clonedStream.getAudioTracks().length > 0;
|
|
442
|
-
const resolution = buildResolutionFromStream(clonedStream);
|
|
443
|
-
const session = await createRecordingSession("selfie");
|
|
444
|
-
const connection = await provider.connect({
|
|
445
|
-
sessionToken: session.token,
|
|
446
|
-
stream: clonedStream,
|
|
447
|
-
events: {}
|
|
448
|
-
});
|
|
449
|
-
await startRecording({
|
|
450
|
-
videoRecordingId: session.videoRecordingId,
|
|
451
|
-
type: "selfie",
|
|
452
|
-
resolution,
|
|
453
|
-
hasAudio
|
|
454
|
-
});
|
|
455
|
-
return {
|
|
456
|
-
token: session.token,
|
|
457
|
-
sessionId: session.sessionId,
|
|
458
|
-
videoRecordingId: session.videoRecordingId,
|
|
459
|
-
connection,
|
|
460
|
-
resolution,
|
|
461
|
-
hasAudio
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
async function stopRecording(session) {
|
|
465
|
-
try {
|
|
466
|
-
await stopRecording$1(session.videoRecordingId);
|
|
467
|
-
} finally {
|
|
468
|
-
await session.connection.disconnect();
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
async function initializeDeepsightSession(options) {
|
|
472
|
-
const { loadDeepsightSession } = await import("./deepsightLoader-Dwr1zKFa.esm.js");
|
|
473
|
-
return loadDeepsightSession({
|
|
474
|
-
ds: options.ds,
|
|
475
|
-
storage: options.storage
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
//#endregion
|
|
479
|
-
//#region src/internal/faceCapture/onDeviceFaceResults.ts
|
|
480
|
-
/**
|
|
481
|
-
* On-device face-results submission helpers.
|
|
482
|
-
*
|
|
483
|
-
* When a SELFIE or AUTHENTICATION module has
|
|
484
|
-
* `onDeviceFaceResultsSubmissionEnabled: true`, face analysis runs entirely
|
|
485
|
-
* inside the WASM `OnDeviceSelfieWorkflow` pipeline. Captured images are
|
|
486
|
-
* never uploaded — only the staged face-results JSON is POSTed via the WASM
|
|
487
|
-
* `WebApi` to `/omni/add/face-results`. The C++ side encrypts that JSON via
|
|
488
|
-
* `SessionEncryptor`, so the per-request `createWasmApi` encryption pipeline
|
|
489
|
-
* is not engaged on this path.
|
|
490
|
-
*
|
|
491
|
-
* Note: even though the per-request encryption pipeline is skipped, the
|
|
492
|
-
* on-device endpoint (`/omni/add/face-results`) is only served on the
|
|
493
|
-
* E2EE-provisioned host — callers must still configure `setup()` with the
|
|
494
|
-
* dedicated E2EE `apiURL` and `encryption: true`. See `SetupOptions.encryption`.
|
|
495
|
-
*
|
|
496
|
-
* These helpers are deliberately variant-agnostic: both the selfie and auth
|
|
497
|
-
* state machine variants delegate their `prepareFaceUpload`, `uploadFace`,
|
|
498
|
-
* and `processFace` actors here to share behavior. See the "Runtime modes
|
|
499
|
-
* within a module" section of `docs/patterns/XSTATE.md` for the broader
|
|
500
|
-
* pattern.
|
|
501
|
-
*/
|
|
502
|
-
const isOnDeviceMode = (config) => config.onDeviceFaceResultsSubmissionEnabled === true;
|
|
503
|
-
/**
|
|
504
|
-
* The default (non-on-device) prepare-upload body shared by selfie and auth.
|
|
505
|
-
* Prepares any recording metadata required by the image upload, runs deepsight
|
|
506
|
-
* virtual-camera + frame checks, tracks the capture attempt, and encrypts the
|
|
507
|
-
* captured image. Scoped multipart recordings pause while an attempt is being
|
|
508
|
-
* uploaded, resume after a rejection, and are finalized by the state machine
|
|
509
|
-
* after backend acceptance.
|
|
510
|
-
*
|
|
511
|
-
* Lifted out of `faceCaptureSetup.ts`'s base `prepareFaceUpload` actor so the
|
|
512
|
-
* default path can be reused by both variants while leaving room for an
|
|
513
|
-
* on-device branch alongside it.
|
|
514
|
-
*/
|
|
515
|
-
async function defaultPrepareFaceUpload(ctx) {
|
|
516
|
-
const sessionToken = getToken();
|
|
517
|
-
const recordingId = (await ctx.recordingService?.prepareUpload())?.recordingId ?? null;
|
|
518
|
-
try {
|
|
519
|
-
if (ctx.deepsightService) await Promise.all([ctx.deepsightService.performVirtualCameraCheck(sessionToken, "SELFIE"), ctx.deepsightService.analyzeFrame(ctx.capturedImage.getImageData())]);
|
|
520
|
-
} catch (error) {
|
|
521
|
-
trueSightLog("warning", "deepsight", "faceScan", `deepsight selfie analysis failed error=${String(error)}`);
|
|
522
|
-
}
|
|
523
|
-
const logs = ctx.deepsightService?.getPipelineState() ?? "";
|
|
524
|
-
ctx.dependencies.trackCaptureAttemptFinished?.({ logs });
|
|
525
|
-
return {
|
|
526
|
-
encryptedBase64Image: await encryptSelfieImage({
|
|
527
|
-
canvas: ctx.capturedImage,
|
|
528
|
-
dependencies: ctx.dependencies
|
|
529
|
-
}),
|
|
530
|
-
recordingId
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* On-device prepare-upload. No recording to stop (the recording service is
|
|
535
|
-
* never created when the flag is on), no image encryption needed.
|
|
536
|
-
*
|
|
537
|
-
* Behavior depends on which capture path got us here:
|
|
538
|
-
*
|
|
539
|
-
* - **Auto-capture path**: the WASM `OnDeviceSelfiePipeline` has been
|
|
540
|
-
* consuming every video frame via `processFrame()` and aggregating
|
|
541
|
-
* results across them. When it picks a best-shot, the C++
|
|
542
|
-
* `OnDeviceSelfieWorkflow::createOnCaptureHandler` calls
|
|
543
|
-
* `WebApi::setFaceResults(...)` automatically — staging strong,
|
|
544
|
-
* aggregated `BestShotData` for the subsequent `postFaceResults` call.
|
|
545
|
-
* We must NOT call `processPhoto` here: `applyFaceResults` would
|
|
546
|
-
* overwrite that staged state with a weaker single-frame analysis of a
|
|
547
|
-
* post-capture snapshot (camera state has already changed: autocapture
|
|
548
|
-
* freeze, stream pause, post-detection latency), and the server then
|
|
549
|
-
* rejects the submission as "image quality too low".
|
|
550
|
-
*
|
|
551
|
-
* - **Manual-capture path**: the auto-capture timer expired without a
|
|
552
|
-
* successful best-shot, so the C++ pipeline has nothing staged. We
|
|
553
|
-
* need to run a single-frame analysis on the manually captured canvas
|
|
554
|
-
* via `processPhoto`, which itself calls
|
|
555
|
-
* `OnDeviceSelfieWorkflow::applyFaceResults` → `WebApi::setFaceResults`
|
|
556
|
-
* to stage results. Mirrors V1 (`packages/incode-welcome/src/camera/useSelfie.ts`)
|
|
557
|
-
* where `processPhoto` is only invoked from `handleManualCapture`.
|
|
558
|
-
*
|
|
559
|
-
* Returns sentinel values for `encryptedBase64Image` and `recordingId` so
|
|
560
|
-
* the existing FaceCaptureContext shape remains stable; downstream actors
|
|
561
|
-
* for the on-device path simply ignore them.
|
|
562
|
-
*/
|
|
563
|
-
async function prepareOnDeviceFaceUpload(ctx) {
|
|
564
|
-
if (!ctx.capturedImage) throw new Error("On-device capture requires a captured image canvas");
|
|
565
|
-
if (!ctx.provider) throw new Error("On-device capture requires the FaceDetectionProvider to be initialized");
|
|
566
|
-
if (ctx.manualCaptureTriggered) {
|
|
567
|
-
await yieldUntilNextPaint();
|
|
568
|
-
await sleep(350);
|
|
569
|
-
ctx.provider.processPhoto(ctx.capturedImage.canvas);
|
|
570
|
-
}
|
|
571
|
-
return {
|
|
572
|
-
encryptedBase64Image: "",
|
|
573
|
-
recordingId: null
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
/**
|
|
577
|
-
* POSTs the staged on-device face-results JSON to `/omni/add/face-results`
|
|
578
|
-
* through the WASM `WebApi`. Used as the `uploadFace` actor body for both
|
|
579
|
-
* selfie and auth variants when on-device mode is enabled.
|
|
580
|
-
*
|
|
581
|
-
* The C++ `WebApi` handles `SessionEncryptor` encryption and the actual
|
|
582
|
-
* HTTP via the WASM `WebClient` — so callers don't need to thread the
|
|
583
|
-
* session-encryption details through JS.
|
|
584
|
-
*/
|
|
585
|
-
async function postOnDeviceFaceResults(ctx, signal) {
|
|
586
|
-
const provider = ctx.provider;
|
|
587
|
-
if (!provider) throw new Error("On-device upload requires the FaceDetectionProvider to be initialized");
|
|
588
|
-
const sessionToken = getToken();
|
|
589
|
-
return await provider.postFaceResults({
|
|
590
|
-
headers: sessionToken ? { "X-Incode-Hardware-Id": sessionToken } : void 0,
|
|
591
|
-
timeout: 3e4
|
|
592
|
-
}) ?? {};
|
|
593
|
-
}
|
|
594
|
-
//#endregion
|
|
595
|
-
export { encryptSelfieImage as a, sendLabelInspectionEvent as c, stopRecording as d, stopStream as f, prepareOnDeviceFaceUpload as i, startDetection as l, isOnDeviceMode as n, initializeCamera as o, FaceDetectionProvider as p, postOnDeviceFaceResults as r, initializeDeepsightSession as s, defaultPrepareFaceUpload as t, startRecordingSession as u };
|
|
474
|
+
export { sendLabelInspectionEvent as a, stopRecording as c, initializeDeepsightSession as i, stopStream as l, encryptSelfieImage as n, startDetection as o, initializeCamera as r, startRecordingSession as s, FaceDetectionProvider as t, isOnDeviceMode as u };
|