@sekyro/web 0.1.0-rc.3 → 0.1.0-rc.5
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/CHANGELOG.md +30 -0
- package/README.md +44 -0
- package/dist/{capture-session-v3-CvIfcwST.d.ts → capture-session-v3-Okq0EQHG.d.ts} +38 -2
- package/dist/{capture-session-v3-COIO_F2w.d.cts → capture-session-v3-UQU_WjO2.d.cts} +38 -2
- package/dist/{chunk-FIXX2AXC.js → chunk-SGDXLAXR.js} +309 -10
- package/dist/chunk-SGDXLAXR.js.map +1 -0
- package/dist/{chunk-7TC6TOZ4.js → chunk-TG5IE552.js} +37 -4
- package/dist/chunk-TG5IE552.js.map +1 -0
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/core/index.cjs +36 -3
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +1 -1
- package/dist/{create-verification-CswF2As-.d.ts → create-verification-CA-3szPI.d.cts} +108 -8
- package/dist/{create-verification-CP18eq1Q.d.cts → create-verification-c98uAxbl.d.ts} +108 -8
- package/dist/{hosted-client-BpvBqu9f.d.cts → hosted-client-DWzCRYJK.d.cts} +14 -1
- package/dist/{hosted-client-BpvBqu9f.d.ts → hosted-client-DWzCRYJK.d.ts} +14 -1
- package/dist/index.cjs +384 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -3
- package/dist/index.d.ts +25 -3
- package/dist/index.js +61 -4
- package/dist/index.js.map +1 -1
- package/dist/internal/index.cjs +261 -11
- package/dist/internal/index.cjs.map +1 -1
- package/dist/internal/index.d.cts +4 -4
- package/dist/internal/index.d.ts +4 -4
- package/dist/internal/index.js +12 -2
- package/dist/internal/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-7TC6TOZ4.js.map +0 -1
- package/dist/chunk-FIXX2AXC.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
|
-
export { C as
|
|
1
|
+
export { C as CameraFacing, a as CaptureChannel, b as CaptureEngineId, c as CaptureError, d as CaptureErrorKind, e as CaptureState, f as CapturedArtifacts, D as DEFAULT_API_ORIGIN, G as GateHint, g as GateUpdate, L as LivenessAssetsStatus, h as LivenessCaptureEvents, i as LivenessCaptureHandle, j as LivenessCaptureOptions, k as LivenessStartOptions, P as PreloadLivenessAssetsOptions, R as ReasonCode, S as SdkFailureReason, V as Verification, l as VerificationEvents, m as VerificationLocale, n as VerificationOptions, o as VerificationResult, p as VerificationStatus, q as createLivenessCapture, r as createVerification, s as getLivenessAssetsStatus, t as preloadLivenessAssets, u as releaseLivenessAssets, v as subscribeLivenessAssets } from './create-verification-CA-3szPI.cjs';
|
|
2
2
|
export { OpenHostedOptions, PopupBlocked, PopupHandle, SEKYRO_EVENTS, SekyroEvent, SekyroEventName, openHosted } from './popup/index.cjs';
|
|
3
3
|
export { HostedApiError, KNOWN_CODES, KnownCode, isKnownCode } from './client/index.cjs';
|
|
4
|
-
export { C as CheckReason, a as CheckState, b as CheckType, D as DocReason, F as FaceMatchReason, H as HostedOtpView, c as HostedSessionView, d as HostedStepView, L as LivenessReason, P as PhoneOtpReason, e as PopulationReason, S as SessionOutcome, f as SessionStatus } from './hosted-client-
|
|
5
|
-
import './capture-session-v3-COIO_F2w.cjs';
|
|
4
|
+
export { C as CheckReason, a as CheckState, b as CheckType, D as DocReason, F as FaceMatchReason, H as HostedOtpView, c as HostedSessionView, d as HostedStepView, L as LivenessReason, P as PhoneOtpReason, e as PopulationReason, S as SessionOutcome, f as SessionStatus } from './hosted-client-DWzCRYJK.cjs';
|
|
6
5
|
import './detect-worker-CKXHlXx9.cjs';
|
|
6
|
+
import './capture-session-v3-UQU_WjO2.cjs';
|
|
7
|
+
|
|
8
|
+
/** Camera permission as the Permissions API reports it; `'unknown'` where it cannot tell. */
|
|
9
|
+
type CameraPermissionState = "granted" | "prompt" | "denied" | "unknown";
|
|
10
|
+
/** One-shot camera permission read. */
|
|
11
|
+
declare function queryCameraPermission(): Promise<CameraPermissionState>;
|
|
12
|
+
/**
|
|
13
|
+
* Subscribe to camera-permission changes; returns the unsubscribe function.
|
|
14
|
+
* Unlike {@link subscribeLivenessAssets}, it DOES emit the current state first
|
|
15
|
+
* (as soon as the Permissions API answers — asynchronously, `'unknown'` where
|
|
16
|
+
* unsupported), then on every change. Not a `useSyncExternalStore` source:
|
|
17
|
+
* there is no synchronous snapshot — drive a `useState` from it.
|
|
18
|
+
*/
|
|
19
|
+
declare function subscribeCameraPermission(listener: (state: CameraPermissionState) => void): () => void;
|
|
20
|
+
/**
|
|
21
|
+
* Whether a front/back choice makes sense: phones and tablets (UA, incl. iPadOS's
|
|
22
|
+
* desktop UA) always have both; otherwise ≥ 2 `videoinput` devices. Before a
|
|
23
|
+
* permission was ever granted some desktops report a single placeholder — the
|
|
24
|
+
* in-capture switch remains available either way.
|
|
25
|
+
*/
|
|
26
|
+
declare function hasMultipleCameras(): Promise<boolean>;
|
|
27
|
+
|
|
28
|
+
export { type CameraPermissionState, hasMultipleCameras, queryCameraPermission, subscribeCameraPermission };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
|
-
export { C as
|
|
1
|
+
export { C as CameraFacing, a as CaptureChannel, b as CaptureEngineId, c as CaptureError, d as CaptureErrorKind, e as CaptureState, f as CapturedArtifacts, D as DEFAULT_API_ORIGIN, G as GateHint, g as GateUpdate, L as LivenessAssetsStatus, h as LivenessCaptureEvents, i as LivenessCaptureHandle, j as LivenessCaptureOptions, k as LivenessStartOptions, P as PreloadLivenessAssetsOptions, R as ReasonCode, S as SdkFailureReason, V as Verification, l as VerificationEvents, m as VerificationLocale, n as VerificationOptions, o as VerificationResult, p as VerificationStatus, q as createLivenessCapture, r as createVerification, s as getLivenessAssetsStatus, t as preloadLivenessAssets, u as releaseLivenessAssets, v as subscribeLivenessAssets } from './create-verification-c98uAxbl.js';
|
|
2
2
|
export { OpenHostedOptions, PopupBlocked, PopupHandle, SEKYRO_EVENTS, SekyroEvent, SekyroEventName, openHosted } from './popup/index.js';
|
|
3
3
|
export { HostedApiError, KNOWN_CODES, KnownCode, isKnownCode } from './client/index.js';
|
|
4
|
-
export { C as CheckReason, a as CheckState, b as CheckType, D as DocReason, F as FaceMatchReason, H as HostedOtpView, c as HostedSessionView, d as HostedStepView, L as LivenessReason, P as PhoneOtpReason, e as PopulationReason, S as SessionOutcome, f as SessionStatus } from './hosted-client-
|
|
5
|
-
import './capture-session-v3-CvIfcwST.js';
|
|
4
|
+
export { C as CheckReason, a as CheckState, b as CheckType, D as DocReason, F as FaceMatchReason, H as HostedOtpView, c as HostedSessionView, d as HostedStepView, L as LivenessReason, P as PhoneOtpReason, e as PopulationReason, S as SessionOutcome, f as SessionStatus } from './hosted-client-DWzCRYJK.js';
|
|
6
5
|
import './detect-worker-CKXHlXx9.js';
|
|
6
|
+
import './capture-session-v3-Okq0EQHG.js';
|
|
7
|
+
|
|
8
|
+
/** Camera permission as the Permissions API reports it; `'unknown'` where it cannot tell. */
|
|
9
|
+
type CameraPermissionState = "granted" | "prompt" | "denied" | "unknown";
|
|
10
|
+
/** One-shot camera permission read. */
|
|
11
|
+
declare function queryCameraPermission(): Promise<CameraPermissionState>;
|
|
12
|
+
/**
|
|
13
|
+
* Subscribe to camera-permission changes; returns the unsubscribe function.
|
|
14
|
+
* Unlike {@link subscribeLivenessAssets}, it DOES emit the current state first
|
|
15
|
+
* (as soon as the Permissions API answers — asynchronously, `'unknown'` where
|
|
16
|
+
* unsupported), then on every change. Not a `useSyncExternalStore` source:
|
|
17
|
+
* there is no synchronous snapshot — drive a `useState` from it.
|
|
18
|
+
*/
|
|
19
|
+
declare function subscribeCameraPermission(listener: (state: CameraPermissionState) => void): () => void;
|
|
20
|
+
/**
|
|
21
|
+
* Whether a front/back choice makes sense: phones and tablets (UA, incl. iPadOS's
|
|
22
|
+
* desktop UA) always have both; otherwise ≥ 2 `videoinput` devices. Before a
|
|
23
|
+
* permission was ever granted some desktops report a single placeholder — the
|
|
24
|
+
* in-capture switch remains available either way.
|
|
25
|
+
*/
|
|
26
|
+
declare function hasMultipleCameras(): Promise<boolean>;
|
|
27
|
+
|
|
28
|
+
export { type CameraPermissionState, hasMultipleCameras, queryCameraPermission, subscribeCameraPermission };
|
package/dist/index.js
CHANGED
|
@@ -5,9 +5,13 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
DEFAULT_API_ORIGIN,
|
|
7
7
|
createLivenessCapture,
|
|
8
|
-
createVerification
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
createVerification,
|
|
9
|
+
getLivenessAssetsStatus,
|
|
10
|
+
preloadLivenessAssets,
|
|
11
|
+
releaseLivenessAssets,
|
|
12
|
+
subscribeLivenessAssets
|
|
13
|
+
} from "./chunk-SGDXLAXR.js";
|
|
14
|
+
import "./chunk-TG5IE552.js";
|
|
11
15
|
import {
|
|
12
16
|
HostedApiError,
|
|
13
17
|
KNOWN_CODES,
|
|
@@ -15,6 +19,52 @@ import {
|
|
|
15
19
|
} from "./chunk-YVFF4Q4G.js";
|
|
16
20
|
import "./chunk-NWF46H7K.js";
|
|
17
21
|
import "./chunk-MWNFSNMP.js";
|
|
22
|
+
|
|
23
|
+
// src/capture/camera-probe.ts
|
|
24
|
+
async function permissionStatus() {
|
|
25
|
+
try {
|
|
26
|
+
if (typeof navigator === "undefined" || typeof navigator.permissions?.query !== "function") return null;
|
|
27
|
+
return await navigator.permissions.query({ name: "camera" });
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function asState(state) {
|
|
33
|
+
return state === "granted" || state === "prompt" || state === "denied" ? state : "unknown";
|
|
34
|
+
}
|
|
35
|
+
async function queryCameraPermission() {
|
|
36
|
+
const status = await permissionStatus();
|
|
37
|
+
return status === null ? "unknown" : asState(status.state);
|
|
38
|
+
}
|
|
39
|
+
function subscribeCameraPermission(listener) {
|
|
40
|
+
let stopped = false;
|
|
41
|
+
let status = null;
|
|
42
|
+
const onChange = () => {
|
|
43
|
+
if (!stopped && status !== null) listener(asState(status.state));
|
|
44
|
+
};
|
|
45
|
+
void permissionStatus().then((resolved) => {
|
|
46
|
+
if (stopped) return;
|
|
47
|
+
status = resolved;
|
|
48
|
+
listener(resolved === null ? "unknown" : asState(resolved.state));
|
|
49
|
+
resolved?.addEventListener?.("change", onChange);
|
|
50
|
+
});
|
|
51
|
+
return () => {
|
|
52
|
+
stopped = true;
|
|
53
|
+
status?.removeEventListener?.("change", onChange);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
async function hasMultipleCameras() {
|
|
57
|
+
if (typeof navigator === "undefined") return false;
|
|
58
|
+
const ua = String(navigator.userAgent ?? "");
|
|
59
|
+
if (/Android|iPhone|iPad|iPod/i.test(ua)) return true;
|
|
60
|
+
if (/Macintosh/.test(ua) && (navigator.maxTouchPoints ?? 0) > 1) return true;
|
|
61
|
+
try {
|
|
62
|
+
const devices = await navigator.mediaDevices?.enumerateDevices?.() ?? [];
|
|
63
|
+
return devices.filter((device) => device.kind === "videoinput").length >= 2;
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
18
68
|
export {
|
|
19
69
|
DEFAULT_API_ORIGIN,
|
|
20
70
|
HostedApiError,
|
|
@@ -22,7 +72,14 @@ export {
|
|
|
22
72
|
SEKYRO_EVENTS,
|
|
23
73
|
createLivenessCapture,
|
|
24
74
|
createVerification,
|
|
75
|
+
getLivenessAssetsStatus,
|
|
76
|
+
hasMultipleCameras,
|
|
25
77
|
isKnownCode,
|
|
26
|
-
openHosted
|
|
78
|
+
openHosted,
|
|
79
|
+
preloadLivenessAssets,
|
|
80
|
+
queryCameraPermission,
|
|
81
|
+
releaseLivenessAssets,
|
|
82
|
+
subscribeCameraPermission,
|
|
83
|
+
subscribeLivenessAssets
|
|
27
84
|
};
|
|
28
85
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/capture/camera-probe.ts"],"sourcesContent":["// Camera probes for pre-capture UI (spec D6, D7). Every function is SSR-safe and\n// never throws: a missing / throwing API (Safari < 16 on {name:'camera'},\n// Firefox) degrades to 'unknown' / false.\n\n/** Camera permission as the Permissions API reports it; `'unknown'` where it cannot tell. */\nexport type CameraPermissionState = \"granted\" | \"prompt\" | \"denied\" | \"unknown\";\n\nasync function permissionStatus(): Promise<PermissionStatus | null> {\n try {\n if (typeof navigator === \"undefined\" || typeof navigator.permissions?.query !== \"function\") return null;\n return await navigator.permissions.query({ name: \"camera\" as PermissionName });\n } catch {\n return null;\n }\n}\n\nfunction asState(state: string): CameraPermissionState {\n return state === \"granted\" || state === \"prompt\" || state === \"denied\" ? state : \"unknown\";\n}\n\n/** One-shot camera permission read. */\nexport async function queryCameraPermission(): Promise<CameraPermissionState> {\n const status = await permissionStatus();\n return status === null ? \"unknown\" : asState(status.state);\n}\n\n/**\n * Subscribe to camera-permission changes; returns the unsubscribe function.\n * Unlike {@link subscribeLivenessAssets}, it DOES emit the current state first\n * (as soon as the Permissions API answers — asynchronously, `'unknown'` where\n * unsupported), then on every change. Not a `useSyncExternalStore` source:\n * there is no synchronous snapshot — drive a `useState` from it.\n */\nexport function subscribeCameraPermission(listener: (state: CameraPermissionState) => void): () => void {\n let stopped = false;\n let status: PermissionStatus | null = null;\n const onChange = (): void => {\n if (!stopped && status !== null) listener(asState(status.state));\n };\n void permissionStatus().then((resolved) => {\n if (stopped) return;\n status = resolved;\n listener(resolved === null ? \"unknown\" : asState(resolved.state));\n resolved?.addEventListener?.(\"change\", onChange);\n });\n return () => {\n stopped = true;\n status?.removeEventListener?.(\"change\", onChange);\n };\n}\n\n/**\n * Whether a front/back choice makes sense: phones and tablets (UA, incl. iPadOS's\n * desktop UA) always have both; otherwise ≥ 2 `videoinput` devices. Before a\n * permission was ever granted some desktops report a single placeholder — the\n * in-capture switch remains available either way.\n */\nexport async function hasMultipleCameras(): Promise<boolean> {\n if (typeof navigator === \"undefined\") return false;\n const ua = String(navigator.userAgent ?? \"\");\n if (/Android|iPhone|iPad|iPod/i.test(ua)) return true;\n if (/Macintosh/.test(ua) && (navigator.maxTouchPoints ?? 0) > 1) return true;\n try {\n const devices = (await navigator.mediaDevices?.enumerateDevices?.()) ?? [];\n return devices.filter((device) => device.kind === \"videoinput\").length >= 2;\n } catch {\n return false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAOA,eAAe,mBAAqD;AAClE,MAAI;AACF,QAAI,OAAO,cAAc,eAAe,OAAO,UAAU,aAAa,UAAU,WAAY,QAAO;AACnG,WAAO,MAAM,UAAU,YAAY,MAAM,EAAE,MAAM,SAA2B,CAAC;AAAA,EAC/E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,QAAQ,OAAsC;AACrD,SAAO,UAAU,aAAa,UAAU,YAAY,UAAU,WAAW,QAAQ;AACnF;AAGA,eAAsB,wBAAwD;AAC5E,QAAM,SAAS,MAAM,iBAAiB;AACtC,SAAO,WAAW,OAAO,YAAY,QAAQ,OAAO,KAAK;AAC3D;AASO,SAAS,0BAA0B,UAA8D;AACtG,MAAI,UAAU;AACd,MAAI,SAAkC;AACtC,QAAM,WAAW,MAAY;AAC3B,QAAI,CAAC,WAAW,WAAW,KAAM,UAAS,QAAQ,OAAO,KAAK,CAAC;AAAA,EACjE;AACA,OAAK,iBAAiB,EAAE,KAAK,CAAC,aAAa;AACzC,QAAI,QAAS;AACb,aAAS;AACT,aAAS,aAAa,OAAO,YAAY,QAAQ,SAAS,KAAK,CAAC;AAChE,cAAU,mBAAmB,UAAU,QAAQ;AAAA,EACjD,CAAC;AACD,SAAO,MAAM;AACX,cAAU;AACV,YAAQ,sBAAsB,UAAU,QAAQ;AAAA,EAClD;AACF;AAQA,eAAsB,qBAAuC;AAC3D,MAAI,OAAO,cAAc,YAAa,QAAO;AAC7C,QAAM,KAAK,OAAO,UAAU,aAAa,EAAE;AAC3C,MAAI,4BAA4B,KAAK,EAAE,EAAG,QAAO;AACjD,MAAI,YAAY,KAAK,EAAE,MAAM,UAAU,kBAAkB,KAAK,EAAG,QAAO;AACxE,MAAI;AACF,UAAM,UAAW,MAAM,UAAU,cAAc,mBAAmB,KAAM,CAAC;AACzE,WAAO,QAAQ,OAAO,CAAC,WAAW,OAAO,SAAS,YAAY,EAAE,UAAU;AAAA,EAC5E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
package/dist/internal/index.cjs
CHANGED
|
@@ -1105,6 +1105,8 @@ __export(internal_exports, {
|
|
|
1105
1105
|
IN_CIRCLE_FACTOR: () => IN_CIRCLE_FACTOR,
|
|
1106
1106
|
MRZ_BAND_DEFAULTS: () => MRZ_BAND_DEFAULTS,
|
|
1107
1107
|
MR_DOC_CATALOG: () => MR_DOC_CATALOG,
|
|
1108
|
+
PRELOAD_BLAZE_INIT_TIMEOUT_MS: () => PRELOAD_BLAZE_INIT_TIMEOUT_MS,
|
|
1109
|
+
PRELOAD_BUDGET_MS: () => PRELOAD_BUDGET_MS,
|
|
1108
1110
|
PROCESSING_POLL_DELAY_MS: () => PROCESSING_POLL_DELAY_MS,
|
|
1109
1111
|
PROCESSING_POLL_MAX: () => PROCESSING_POLL_MAX,
|
|
1110
1112
|
REGISTRY_RETRY_DELAY_MS: () => REGISTRY_RETRY_DELAY_MS,
|
|
@@ -1129,14 +1131,17 @@ __export(internal_exports, {
|
|
|
1129
1131
|
mapGuidanceHint: () => mapGuidanceHint,
|
|
1130
1132
|
mapSessionResult: () => mapSessionResult,
|
|
1131
1133
|
mergeSessionView: () => mergeSessionView,
|
|
1134
|
+
preloadedDetectorFactory: () => preloadedDetectorFactory,
|
|
1132
1135
|
quadAreaFrac: () => quadAreaFrac,
|
|
1133
1136
|
quadBounds: () => quadBounds,
|
|
1134
1137
|
quadIou: () => quadIou,
|
|
1135
1138
|
quadTiltRatio: () => quadTiltRatio,
|
|
1136
1139
|
randomUuid: () => randomUuid,
|
|
1140
|
+
resetLivenessAssetsForTests: () => resetLivenessAssetsForTests,
|
|
1137
1141
|
resetTurnstileForTests: () => resetTurnstileForTests,
|
|
1138
1142
|
runLivenessFlow: () => runLivenessFlow,
|
|
1139
1143
|
runSubmission: () => runSubmission,
|
|
1144
|
+
setPreloadLoaderForTests: () => setPreloadLoaderForTests,
|
|
1140
1145
|
specularFraction: () => specularFraction,
|
|
1141
1146
|
stepOf: () => stepOf,
|
|
1142
1147
|
warmDocDetector: () => warmDocDetector
|
|
@@ -2556,7 +2561,8 @@ var FaceGateV3 = class {
|
|
|
2556
2561
|
p: this.p,
|
|
2557
2562
|
factors,
|
|
2558
2563
|
guidanceKey: this.guidanceOf(factors, quality, q),
|
|
2559
|
-
ready
|
|
2564
|
+
ready,
|
|
2565
|
+
accepted: q >= this.t.Q_GOOD
|
|
2560
2566
|
};
|
|
2561
2567
|
}
|
|
2562
2568
|
geometryOf(observation, input) {
|
|
@@ -2675,6 +2681,11 @@ var CaptureSessionV3 = class {
|
|
|
2675
2681
|
this.profiler = null;
|
|
2676
2682
|
this.lastGuidanceKey = null;
|
|
2677
2683
|
this.positioningStartedAt = 0;
|
|
2684
|
+
// Face-capture timing marks of the CURRENT attempt (engine clock; reset per run).
|
|
2685
|
+
this.cameraRequestedAt = null;
|
|
2686
|
+
this.cameraReadyAt = null;
|
|
2687
|
+
this.faceAcquiredAt = null;
|
|
2688
|
+
this.captureCompleteAt = null;
|
|
2678
2689
|
this.fired = false;
|
|
2679
2690
|
this.carriedDegrade = 0;
|
|
2680
2691
|
this.carriedMeans = [];
|
|
@@ -2701,10 +2712,15 @@ var CaptureSessionV3 = class {
|
|
|
2701
2712
|
handler(payload);
|
|
2702
2713
|
}
|
|
2703
2714
|
}
|
|
2704
|
-
async start() {
|
|
2715
|
+
async start(options = {}) {
|
|
2716
|
+
if (options.facingMode !== void 0) this.facing = options.facingMode;
|
|
2705
2717
|
this.attempt += 1;
|
|
2706
2718
|
await this.run(this.attempt);
|
|
2707
2719
|
}
|
|
2720
|
+
/** The camera the current/next attempt requests (start option, switchCamera toggles). */
|
|
2721
|
+
get facingMode() {
|
|
2722
|
+
return this.facing;
|
|
2723
|
+
}
|
|
2708
2724
|
/** Full reset + camera restart — the documented recovery path (v1 parity). */
|
|
2709
2725
|
retry() {
|
|
2710
2726
|
this.teardownAttempt();
|
|
@@ -2729,6 +2745,10 @@ var CaptureSessionV3 = class {
|
|
|
2729
2745
|
this.lastGuidanceKey = null;
|
|
2730
2746
|
this.carriedDegrade = 0;
|
|
2731
2747
|
this.carriedMeans = [];
|
|
2748
|
+
this.cameraRequestedAt = null;
|
|
2749
|
+
this.cameraReadyAt = null;
|
|
2750
|
+
this.faceAcquiredAt = null;
|
|
2751
|
+
this.captureCompleteAt = null;
|
|
2732
2752
|
this.setState("preflight");
|
|
2733
2753
|
const preflight = cameraPreflight();
|
|
2734
2754
|
if (preflight !== "OK") {
|
|
@@ -2738,6 +2758,7 @@ var CaptureSessionV3 = class {
|
|
|
2738
2758
|
this.setState("acquiring");
|
|
2739
2759
|
const getUserMedia = options.getUserMedia ?? ((constraints) => navigator.mediaDevices.getUserMedia(constraints));
|
|
2740
2760
|
let stream;
|
|
2761
|
+
this.cameraRequestedAt = this.now();
|
|
2741
2762
|
try {
|
|
2742
2763
|
stream = await getUserMedia(buildCaptureConstraints(detectIsMobile(), this.facing));
|
|
2743
2764
|
} catch (err) {
|
|
@@ -2753,6 +2774,7 @@ var CaptureSessionV3 = class {
|
|
|
2753
2774
|
options.video.srcObject = stream;
|
|
2754
2775
|
await options.video.play().catch(() => void 0);
|
|
2755
2776
|
if (attempt !== this.attempt) return;
|
|
2777
|
+
this.cameraReadyAt = this.now();
|
|
2756
2778
|
if (this.detector === null) {
|
|
2757
2779
|
const ladderOptions = {
|
|
2758
2780
|
...options.v3AssetBaseUrl !== void 0 ? { v3AssetBaseUrl: options.v3AssetBaseUrl } : {}
|
|
@@ -2852,6 +2874,7 @@ var CaptureSessionV3 = class {
|
|
|
2852
2874
|
frameWidth: video.videoWidth,
|
|
2853
2875
|
frameHeight: video.videoHeight
|
|
2854
2876
|
});
|
|
2877
|
+
if (tick.accepted && this.faceAcquiredAt === null) this.faceAcquiredAt = tick.at;
|
|
2855
2878
|
this.emit("checks", {
|
|
2856
2879
|
engine: "v3",
|
|
2857
2880
|
progress: tick.p,
|
|
@@ -2865,6 +2888,7 @@ var CaptureSessionV3 = class {
|
|
|
2865
2888
|
}
|
|
2866
2889
|
if (tick.ready && this.stateValue === "positioning") {
|
|
2867
2890
|
this.fired = true;
|
|
2891
|
+
this.captureCompleteAt = tick.at;
|
|
2868
2892
|
void this.fire(attempt);
|
|
2869
2893
|
}
|
|
2870
2894
|
}
|
|
@@ -2959,7 +2983,21 @@ var CaptureSessionV3 = class {
|
|
|
2959
2983
|
finishCapture(artifacts) {
|
|
2960
2984
|
this.stopTracks();
|
|
2961
2985
|
this.setState("captured");
|
|
2962
|
-
this.
|
|
2986
|
+
const timing = this.captureTiming();
|
|
2987
|
+
this.emit("artifacts", timing === void 0 ? artifacts : { ...artifacts, timing });
|
|
2988
|
+
}
|
|
2989
|
+
/** The attempt's capture-phase timing (whole ms, ≥ 0); undefined when no mark landed. */
|
|
2990
|
+
captureTiming() {
|
|
2991
|
+
const span = (from, to) => from !== null && to !== null ? Math.max(0, Math.round(to - from)) : void 0;
|
|
2992
|
+
const cameraReadyMs = span(this.cameraRequestedAt, this.cameraReadyAt);
|
|
2993
|
+
const faceAcquireMs = span(this.cameraReadyAt, this.faceAcquiredAt);
|
|
2994
|
+
const captureMs = span(this.faceAcquiredAt, this.captureCompleteAt);
|
|
2995
|
+
const timing = {
|
|
2996
|
+
...cameraReadyMs !== void 0 ? { cameraReadyMs } : {},
|
|
2997
|
+
...faceAcquireMs !== void 0 ? { faceAcquireMs } : {},
|
|
2998
|
+
...captureMs !== void 0 ? { captureMs } : {}
|
|
2999
|
+
};
|
|
3000
|
+
return Object.keys(timing).length > 0 ? timing : void 0;
|
|
2963
3001
|
}
|
|
2964
3002
|
// ── defaults for the canvas-bound seams ────────────────────────────────────
|
|
2965
3003
|
async defaultKeyframe(video) {
|
|
@@ -3090,6 +3128,179 @@ function createEmitter() {
|
|
|
3090
3128
|
};
|
|
3091
3129
|
}
|
|
3092
3130
|
|
|
3131
|
+
// src/capture/preload.ts
|
|
3132
|
+
var PRELOAD_BLAZE_INIT_TIMEOUT_MS = 12e4;
|
|
3133
|
+
var PRELOAD_BUDGET_MS = 13e4;
|
|
3134
|
+
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("@sekyro/web.preload.v1");
|
|
3135
|
+
function registry() {
|
|
3136
|
+
const host = globalThis;
|
|
3137
|
+
host[REGISTRY_KEY] ?? (host[REGISTRY_KEY] = /* @__PURE__ */ new Map());
|
|
3138
|
+
return host[REGISTRY_KEY];
|
|
3139
|
+
}
|
|
3140
|
+
function normalizeBase(assetBaseUrl) {
|
|
3141
|
+
const base = (assetBaseUrl ?? DEFAULT_V3_ASSET_BASE_URL).replace(/\/+$/, "");
|
|
3142
|
+
return base === "" ? "/" : base;
|
|
3143
|
+
}
|
|
3144
|
+
function setStatus(entry, next) {
|
|
3145
|
+
if (entry.status === next) return;
|
|
3146
|
+
entry.status = next;
|
|
3147
|
+
for (const listener of [...entry.listeners]) listener(next);
|
|
3148
|
+
}
|
|
3149
|
+
var defaultLoader = (base) => createDetector({ preferred: ["blaze"], v3AssetBaseUrl: base, blazeInitTimeoutMs: PRELOAD_BLAZE_INIT_TIMEOUT_MS });
|
|
3150
|
+
var loader = defaultLoader;
|
|
3151
|
+
function setPreloadLoaderForTests(next) {
|
|
3152
|
+
loader = next ?? defaultLoader;
|
|
3153
|
+
}
|
|
3154
|
+
function resetLivenessAssetsForTests() {
|
|
3155
|
+
for (const entry of registry().values()) entry.detector?.destroy();
|
|
3156
|
+
registry().clear();
|
|
3157
|
+
loader = defaultLoader;
|
|
3158
|
+
}
|
|
3159
|
+
function begin(entry, base) {
|
|
3160
|
+
if ((entry.status === "loading" || entry.status === "ready") && entry.promise !== null) return entry.promise;
|
|
3161
|
+
setStatus(entry, "loading");
|
|
3162
|
+
const detectorPromise = new Promise((resolve) => resolve(loader(base)));
|
|
3163
|
+
entry.detectorPromise = detectorPromise;
|
|
3164
|
+
let timer;
|
|
3165
|
+
const budget = new Promise((_2, reject) => {
|
|
3166
|
+
timer = setTimeout(() => {
|
|
3167
|
+
detectorPromise.then((late) => late.destroy(), () => void 0);
|
|
3168
|
+
reject(new Error(`detector preload exceeded ${PRELOAD_BUDGET_MS} ms`));
|
|
3169
|
+
}, PRELOAD_BUDGET_MS);
|
|
3170
|
+
});
|
|
3171
|
+
const settled = Promise.race([detectorPromise, budget]).then(
|
|
3172
|
+
(detector) => {
|
|
3173
|
+
if (entry.detectorPromise !== detectorPromise) {
|
|
3174
|
+
detector.destroy();
|
|
3175
|
+
return entry.status;
|
|
3176
|
+
}
|
|
3177
|
+
entry.detector = detector;
|
|
3178
|
+
setStatus(entry, "ready");
|
|
3179
|
+
return "ready";
|
|
3180
|
+
},
|
|
3181
|
+
(err) => {
|
|
3182
|
+
if (entry.detectorPromise === detectorPromise) {
|
|
3183
|
+
entry.detectorPromise = null;
|
|
3184
|
+
entry.detector = null;
|
|
3185
|
+
setStatus(entry, "failed");
|
|
3186
|
+
console.warn("[@sekyro/web] face-detector preload failed:", err);
|
|
3187
|
+
}
|
|
3188
|
+
return entry.status;
|
|
3189
|
+
}
|
|
3190
|
+
);
|
|
3191
|
+
const promise = settled.finally(() => clearTimeout(timer));
|
|
3192
|
+
entry.promise = promise;
|
|
3193
|
+
entry.scheduled?.settle(promise);
|
|
3194
|
+
return promise;
|
|
3195
|
+
}
|
|
3196
|
+
function nonOwningView(shared) {
|
|
3197
|
+
return {
|
|
3198
|
+
get tier() {
|
|
3199
|
+
return shared.tier;
|
|
3200
|
+
},
|
|
3201
|
+
get fallbackReason() {
|
|
3202
|
+
return shared.fallbackReason;
|
|
3203
|
+
},
|
|
3204
|
+
detect: (...args) => shared.detect(...args),
|
|
3205
|
+
destroy: () => {
|
|
3206
|
+
}
|
|
3207
|
+
};
|
|
3208
|
+
}
|
|
3209
|
+
function preloadedDetectorFactory(assetBaseUrl) {
|
|
3210
|
+
const base = normalizeBase(assetBaseUrl);
|
|
3211
|
+
const entry = registry().get(base);
|
|
3212
|
+
if (entry === void 0 || entry.detector === null && entry.detectorPromise === null && entry.scheduled === null) {
|
|
3213
|
+
return void 0;
|
|
3214
|
+
}
|
|
3215
|
+
return async () => {
|
|
3216
|
+
if (entry.scheduled !== null) void begin(entry, base);
|
|
3217
|
+
let waitingOn = entry.promise;
|
|
3218
|
+
while (entry.detector === null && waitingOn !== null) {
|
|
3219
|
+
await waitingOn;
|
|
3220
|
+
if (entry.promise === waitingOn) break;
|
|
3221
|
+
waitingOn = entry.promise;
|
|
3222
|
+
}
|
|
3223
|
+
return entry.detector !== null ? nonOwningView(entry.detector) : createDetector({ v3AssetBaseUrl: base });
|
|
3224
|
+
};
|
|
3225
|
+
}
|
|
3226
|
+
|
|
3227
|
+
// src/capture/wake-lock.ts
|
|
3228
|
+
function wakeLockApi() {
|
|
3229
|
+
if (typeof navigator === "undefined" || !("wakeLock" in navigator)) return null;
|
|
3230
|
+
const api = navigator.wakeLock;
|
|
3231
|
+
return typeof api?.request === "function" ? api : null;
|
|
3232
|
+
}
|
|
3233
|
+
function isVisible() {
|
|
3234
|
+
return typeof document === "undefined" || document.visibilityState === "visible";
|
|
3235
|
+
}
|
|
3236
|
+
function releaseQuietly(sentinel) {
|
|
3237
|
+
try {
|
|
3238
|
+
void sentinel.release().catch(() => void 0);
|
|
3239
|
+
} catch {
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
function createScreenWakeLock(options = {}) {
|
|
3243
|
+
if (options.enabled === false) return { setActive: () => void 0 };
|
|
3244
|
+
let wanted = false;
|
|
3245
|
+
let sentinel = null;
|
|
3246
|
+
let inFlight = false;
|
|
3247
|
+
let listening = false;
|
|
3248
|
+
const acquire = () => {
|
|
3249
|
+
if (!wanted || inFlight || sentinel !== null && !sentinel.released) return;
|
|
3250
|
+
const api = wakeLockApi();
|
|
3251
|
+
if (api === null || !isVisible()) return;
|
|
3252
|
+
let request;
|
|
3253
|
+
try {
|
|
3254
|
+
request = api.request("screen");
|
|
3255
|
+
} catch {
|
|
3256
|
+
return;
|
|
3257
|
+
}
|
|
3258
|
+
inFlight = true;
|
|
3259
|
+
request.then(
|
|
3260
|
+
(granted) => {
|
|
3261
|
+
inFlight = false;
|
|
3262
|
+
if (!wanted) {
|
|
3263
|
+
releaseQuietly(granted);
|
|
3264
|
+
return;
|
|
3265
|
+
}
|
|
3266
|
+
sentinel = granted;
|
|
3267
|
+
granted.addEventListener?.("release", () => {
|
|
3268
|
+
if (sentinel === granted) sentinel = null;
|
|
3269
|
+
});
|
|
3270
|
+
},
|
|
3271
|
+
() => {
|
|
3272
|
+
inFlight = false;
|
|
3273
|
+
}
|
|
3274
|
+
);
|
|
3275
|
+
};
|
|
3276
|
+
const onVisibilityChange = () => {
|
|
3277
|
+
if (isVisible()) acquire();
|
|
3278
|
+
};
|
|
3279
|
+
const listen = (on) => {
|
|
3280
|
+
if (typeof document === "undefined" || on === listening) return;
|
|
3281
|
+
listening = on;
|
|
3282
|
+
if (on) document.addEventListener("visibilitychange", onVisibilityChange);
|
|
3283
|
+
else document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
3284
|
+
};
|
|
3285
|
+
return {
|
|
3286
|
+
setActive: (active) => {
|
|
3287
|
+
wanted = active;
|
|
3288
|
+
if (active) {
|
|
3289
|
+
if (wakeLockApi() === null) return;
|
|
3290
|
+
listen(true);
|
|
3291
|
+
acquire();
|
|
3292
|
+
return;
|
|
3293
|
+
}
|
|
3294
|
+
listen(false);
|
|
3295
|
+
if (sentinel !== null) {
|
|
3296
|
+
const held = sentinel;
|
|
3297
|
+
sentinel = null;
|
|
3298
|
+
releaseQuietly(held);
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
};
|
|
3302
|
+
}
|
|
3303
|
+
|
|
3093
3304
|
// src/capture/create-liveness-capture.ts
|
|
3094
3305
|
function mapGuidanceHint(key) {
|
|
3095
3306
|
switch (key) {
|
|
@@ -3153,12 +3364,22 @@ function createLivenessCaptureInternal(options, internals = {}) {
|
|
|
3153
3364
|
const now = internals.now ?? (() => performance.now());
|
|
3154
3365
|
const emitter = createEmitter();
|
|
3155
3366
|
const degraded = !isMediaRecorderSupported();
|
|
3367
|
+
const hostSeams = internals.engineOptions;
|
|
3368
|
+
const preloadAware = hostSeams?.createDetector === void 0 && hostSeams?.createWorker === void 0 ? {
|
|
3369
|
+
createDetector: () => {
|
|
3370
|
+
const warmed = preloadedDetectorFactory(options.assetBaseUrl);
|
|
3371
|
+
return warmed !== void 0 ? warmed() : createDetector(
|
|
3372
|
+
options.assetBaseUrl !== void 0 ? { v3AssetBaseUrl: options.assetBaseUrl } : {}
|
|
3373
|
+
);
|
|
3374
|
+
}
|
|
3375
|
+
} : {};
|
|
3156
3376
|
const engineOptions = {
|
|
3157
3377
|
video: options.video,
|
|
3158
3378
|
mode: degraded ? "photo" : "clip",
|
|
3159
3379
|
...options.facing !== void 0 ? { facingMode: options.facing } : {},
|
|
3160
3380
|
...options.assetBaseUrl !== void 0 ? { v3AssetBaseUrl: options.assetBaseUrl } : {},
|
|
3161
|
-
...internals.engineOptions ?? {}
|
|
3381
|
+
...internals.engineOptions ?? {},
|
|
3382
|
+
...preloadAware
|
|
3162
3383
|
};
|
|
3163
3384
|
const engine = internals.createEngine?.(engineOptions) ?? new CaptureSessionV3(engineOptions);
|
|
3164
3385
|
let state = "idle";
|
|
@@ -3176,8 +3397,10 @@ function createLivenessCaptureInternal(options, internals = {}) {
|
|
|
3176
3397
|
frameHeight = options.video.videoHeight;
|
|
3177
3398
|
}
|
|
3178
3399
|
};
|
|
3400
|
+
const wakeLock = createScreenWakeLock({ enabled: options.keepScreenAwake !== false });
|
|
3179
3401
|
const setState = (next) => {
|
|
3180
3402
|
state = next;
|
|
3403
|
+
wakeLock.setActive(next === "starting" || next === "gating" || next === "recording");
|
|
3181
3404
|
emitter.emit("state", next);
|
|
3182
3405
|
};
|
|
3183
3406
|
const emitGate = () => emitter.emit("gate", { progress, hint, faceDetected });
|
|
@@ -3234,7 +3457,12 @@ function createLivenessCaptureInternal(options, internals = {}) {
|
|
|
3234
3457
|
height: options.video.videoHeight || frameHeight,
|
|
3235
3458
|
...clipMs !== void 0 ? { clipMs } : {},
|
|
3236
3459
|
captureChannel: detectIsMobile() ? "mobile" : "desktop",
|
|
3237
|
-
...degraded ? { degraded: "NO_RECORDER" } : {}
|
|
3460
|
+
...degraded ? { degraded: "NO_RECORDER" } : {},
|
|
3461
|
+
engine: "v3",
|
|
3462
|
+
// Face-capture timing: the engine's marks, forwarded flat (absent → absent).
|
|
3463
|
+
...artifacts.timing?.cameraReadyMs !== void 0 ? { cameraReadyMs: artifacts.timing.cameraReadyMs } : {},
|
|
3464
|
+
...artifacts.timing?.faceAcquireMs !== void 0 ? { faceAcquireMs: artifacts.timing.faceAcquireMs } : {},
|
|
3465
|
+
...artifacts.timing?.captureMs !== void 0 ? { captureMs: artifacts.timing.captureMs } : {}
|
|
3238
3466
|
});
|
|
3239
3467
|
}),
|
|
3240
3468
|
engine.on("error", ({ kind, retryable }) => {
|
|
@@ -3246,11 +3474,12 @@ function createLivenessCaptureInternal(options, internals = {}) {
|
|
|
3246
3474
|
return state;
|
|
3247
3475
|
},
|
|
3248
3476
|
on: (event, handler) => emitter.on(event, handler),
|
|
3249
|
-
start: () => engine.start(),
|
|
3477
|
+
start: (startOptions) => engine.start(startOptions?.facing !== void 0 ? { facingMode: startOptions.facing } : {}),
|
|
3250
3478
|
retry: () => engine.retry(),
|
|
3251
3479
|
switchCamera: () => engine.switchCamera(),
|
|
3252
3480
|
destroy: () => {
|
|
3253
3481
|
for (const unsubscribe of unsubscribes) unsubscribe();
|
|
3482
|
+
wakeLock.setActive(false);
|
|
3254
3483
|
engine.destroy();
|
|
3255
3484
|
emitter.clear();
|
|
3256
3485
|
}
|
|
@@ -3733,7 +3962,12 @@ function buildLivenessSubmit(deps, clip, bareMime) {
|
|
|
3733
3962
|
deps.onPhase("checking");
|
|
3734
3963
|
return client.submitCheck(
|
|
3735
3964
|
"liveness",
|
|
3736
|
-
{
|
|
3965
|
+
{
|
|
3966
|
+
clipKey,
|
|
3967
|
+
attestation,
|
|
3968
|
+
captureChannel: deps.artifacts.captureChannel,
|
|
3969
|
+
capture: captureInputOf(deps.artifacts)
|
|
3970
|
+
},
|
|
3737
3971
|
{ idempotencyKey }
|
|
3738
3972
|
);
|
|
3739
3973
|
},
|
|
@@ -3744,6 +3978,17 @@ function buildLivenessSubmit(deps, clip, bareMime) {
|
|
|
3744
3978
|
}
|
|
3745
3979
|
);
|
|
3746
3980
|
}
|
|
3981
|
+
function captureInputOf(artifacts) {
|
|
3982
|
+
return {
|
|
3983
|
+
...artifacts.engine !== void 0 ? { engine: artifacts.engine } : {},
|
|
3984
|
+
width: artifacts.width,
|
|
3985
|
+
height: artifacts.height,
|
|
3986
|
+
...artifacts.clipMs !== void 0 ? { clipMs: artifacts.clipMs } : {},
|
|
3987
|
+
...artifacts.cameraReadyMs !== void 0 ? { cameraReadyMs: artifacts.cameraReadyMs } : {},
|
|
3988
|
+
...artifacts.faceAcquireMs !== void 0 ? { faceAcquireMs: artifacts.faceAcquireMs } : {},
|
|
3989
|
+
...artifacts.captureMs !== void 0 ? { captureMs: artifacts.captureMs } : {}
|
|
3990
|
+
};
|
|
3991
|
+
}
|
|
3747
3992
|
function buildFaceMatchSubmit(deps, keyframe) {
|
|
3748
3993
|
let imageKey = null;
|
|
3749
3994
|
return () => runSubmission(deps, async (client, idempotencyKey) => {
|
|
@@ -3942,7 +4187,7 @@ function createVerificationInternal(options, internals) {
|
|
|
3942
4187
|
}
|
|
3943
4188
|
emitter.emit("result", result);
|
|
3944
4189
|
};
|
|
3945
|
-
let
|
|
4190
|
+
let registry2 = null;
|
|
3946
4191
|
let registryFailed = false;
|
|
3947
4192
|
let registryUnbound = false;
|
|
3948
4193
|
const submitRegistry = () => runSubmission(
|
|
@@ -3977,8 +4222,8 @@ function createVerificationInternal(options, internals) {
|
|
|
3977
4222
|
if (view !== null && isTerminalView(view)) emitResult(mapSessionResult(view, { autoRetry }));
|
|
3978
4223
|
};
|
|
3979
4224
|
const startRegistry = () => {
|
|
3980
|
-
|
|
3981
|
-
return
|
|
4225
|
+
registry2 ?? (registry2 = runRegistry());
|
|
4226
|
+
return registry2;
|
|
3982
4227
|
};
|
|
3983
4228
|
const getAttestation = async () => {
|
|
3984
4229
|
const current = await ensureView();
|
|
@@ -4093,7 +4338,7 @@ function createVerificationInternal(options, internals) {
|
|
|
4093
4338
|
return inner.state;
|
|
4094
4339
|
},
|
|
4095
4340
|
on: (event, handler) => inner.on(event, handler),
|
|
4096
|
-
start: () => inner.start(),
|
|
4341
|
+
start: (startOptions) => inner.start(startOptions),
|
|
4097
4342
|
retry: () => inner.retry(),
|
|
4098
4343
|
switchCamera: () => inner.switchCamera(),
|
|
4099
4344
|
destroy: () => {
|
|
@@ -4140,6 +4385,8 @@ function createVerificationInternal(options, internals) {
|
|
|
4140
4385
|
IN_CIRCLE_FACTOR,
|
|
4141
4386
|
MRZ_BAND_DEFAULTS,
|
|
4142
4387
|
MR_DOC_CATALOG,
|
|
4388
|
+
PRELOAD_BLAZE_INIT_TIMEOUT_MS,
|
|
4389
|
+
PRELOAD_BUDGET_MS,
|
|
4143
4390
|
PROCESSING_POLL_DELAY_MS,
|
|
4144
4391
|
PROCESSING_POLL_MAX,
|
|
4145
4392
|
REGISTRY_RETRY_DELAY_MS,
|
|
@@ -4164,14 +4411,17 @@ function createVerificationInternal(options, internals) {
|
|
|
4164
4411
|
mapGuidanceHint,
|
|
4165
4412
|
mapSessionResult,
|
|
4166
4413
|
mergeSessionView,
|
|
4414
|
+
preloadedDetectorFactory,
|
|
4167
4415
|
quadAreaFrac,
|
|
4168
4416
|
quadBounds,
|
|
4169
4417
|
quadIou,
|
|
4170
4418
|
quadTiltRatio,
|
|
4171
4419
|
randomUuid,
|
|
4420
|
+
resetLivenessAssetsForTests,
|
|
4172
4421
|
resetTurnstileForTests,
|
|
4173
4422
|
runLivenessFlow,
|
|
4174
4423
|
runSubmission,
|
|
4424
|
+
setPreloadLoaderForTests,
|
|
4175
4425
|
specularFraction,
|
|
4176
4426
|
stepOf,
|
|
4177
4427
|
warmDocDetector
|