@aws-amplify/ui-react-liveness 3.4.6 → 3.5.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.
- package/dist/esm/components/FaceLivenessDetector/service/machine/machine.mjs +89 -13
- package/dist/esm/components/FaceLivenessDetector/service/types/error.mjs +1 -0
- package/dist/esm/version.mjs +1 -1
- package/dist/index.js +90 -13
- package/dist/types/components/FaceLivenessDetector/service/machine/machine.d.ts +2 -1
- package/dist/types/components/FaceLivenessDetector/service/types/error.d.ts +1 -0
- package/dist/types/components/FaceLivenessDetector/service/types/liveness.d.ts +15 -3
- package/dist/types/components/FaceLivenessDetector/service/types/machine.d.ts +1 -1
- package/dist/types/components/FaceLivenessDetector/service/utils/liveness.d.ts +1 -0
- package/dist/types/components/FaceLivenessDetector/shared/Hint.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +4 -4
|
@@ -19,6 +19,17 @@ import { TelemetryReporter } from '../utils/TelemetryReporter/TelemetryReporter.
|
|
|
19
19
|
const CAMERA_ID_KEY = 'AmplifyLivenessCameraId';
|
|
20
20
|
const DEFAULT_FACE_FIT_TIMEOUT = 7000;
|
|
21
21
|
let responseStream;
|
|
22
|
+
// Helper function to get selected device info
|
|
23
|
+
const getSelectedDeviceInfo = (context) => {
|
|
24
|
+
const selected = context.videoAssociatedParams?.selectableDevices?.find((d) => d.deviceId === context.videoAssociatedParams?.selectedDeviceId);
|
|
25
|
+
return selected
|
|
26
|
+
? {
|
|
27
|
+
deviceId: selected.deviceId,
|
|
28
|
+
groupId: selected.groupId,
|
|
29
|
+
label: selected.label ?? '',
|
|
30
|
+
}
|
|
31
|
+
: undefined;
|
|
32
|
+
};
|
|
22
33
|
const responseStreamActor = async (callback) => {
|
|
23
34
|
try {
|
|
24
35
|
const stream = await responseStream;
|
|
@@ -79,6 +90,9 @@ const responseStreamActor = async (callback) => {
|
|
|
79
90
|
}
|
|
80
91
|
}
|
|
81
92
|
};
|
|
93
|
+
function getLastSelectedCameraId() {
|
|
94
|
+
return localStorage.getItem(CAMERA_ID_KEY);
|
|
95
|
+
}
|
|
82
96
|
function setLastSelectedCameraId(deviceId) {
|
|
83
97
|
localStorage.setItem(CAMERA_ID_KEY, deviceId);
|
|
84
98
|
}
|
|
@@ -631,6 +645,9 @@ const livenessMachine = createMachine({
|
|
|
631
645
|
if (event.data.message.includes('15 fps')) {
|
|
632
646
|
errorState = LivenessErrorState.CAMERA_FRAMERATE_ERROR;
|
|
633
647
|
}
|
|
648
|
+
else if (event.data.message.includes(LivenessErrorState.DEFAULT_CAMERA_NOT_FOUND_ERROR)) {
|
|
649
|
+
errorState = LivenessErrorState.DEFAULT_CAMERA_NOT_FOUND_ERROR;
|
|
650
|
+
}
|
|
634
651
|
else {
|
|
635
652
|
errorState = LivenessErrorState.CAMERA_ACCESS_ERROR;
|
|
636
653
|
}
|
|
@@ -640,15 +657,26 @@ const livenessMachine = createMachine({
|
|
|
640
657
|
state: errorState,
|
|
641
658
|
error: error,
|
|
642
659
|
};
|
|
643
|
-
context.componentProps.onError?.(livenessError);
|
|
660
|
+
context.componentProps.onError?.(livenessError, getSelectedDeviceInfo(context));
|
|
644
661
|
return errorState;
|
|
645
662
|
},
|
|
646
663
|
}),
|
|
647
664
|
callMobileLandscapeWarningCallback: assign({
|
|
648
665
|
errorState: () => LivenessErrorState.MOBILE_LANDSCAPE_ERROR,
|
|
649
666
|
}),
|
|
667
|
+
getSelectedDeviceInfo: (context) => getSelectedDeviceInfo(context),
|
|
650
668
|
callUserCancelCallback: (context) => {
|
|
651
|
-
context.componentProps
|
|
669
|
+
const { onUserCancel } = context.componentProps ?? {};
|
|
670
|
+
if (!onUserCancel) {
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
try {
|
|
674
|
+
onUserCancel();
|
|
675
|
+
}
|
|
676
|
+
catch (callbackError) {
|
|
677
|
+
// eslint-disable-next-line no-console
|
|
678
|
+
console.error('Error in onUserCancel callback:', callbackError);
|
|
679
|
+
}
|
|
652
680
|
},
|
|
653
681
|
callUserTimeoutCallback: (context) => {
|
|
654
682
|
const error = new Error(context.errorMessage ?? 'Client Timeout');
|
|
@@ -657,14 +685,14 @@ const livenessMachine = createMachine({
|
|
|
657
685
|
state: context.errorState,
|
|
658
686
|
error: error,
|
|
659
687
|
};
|
|
660
|
-
context.componentProps.onError?.(livenessError);
|
|
688
|
+
context.componentProps.onError?.(livenessError, getSelectedDeviceInfo(context));
|
|
661
689
|
},
|
|
662
690
|
callErrorCallback: (context, event) => {
|
|
663
691
|
const livenessError = {
|
|
664
692
|
state: context.errorState,
|
|
665
693
|
error: event.data?.error || event.data,
|
|
666
694
|
};
|
|
667
|
-
context.componentProps.onError?.(livenessError);
|
|
695
|
+
context.componentProps.onError?.(livenessError, getSelectedDeviceInfo(context));
|
|
668
696
|
},
|
|
669
697
|
cleanUpResources: (context) => {
|
|
670
698
|
const { freshnessColorEl } = context.freshnessColorAssociatedParams;
|
|
@@ -775,10 +803,42 @@ const livenessMachine = createMachine({
|
|
|
775
803
|
services: {
|
|
776
804
|
async checkVirtualCameraAndGetStream(context) {
|
|
777
805
|
const { videoConstraints } = context.videoAssociatedParams;
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
806
|
+
const { componentProps } = context;
|
|
807
|
+
let targetDeviceId;
|
|
808
|
+
let cameraNotFound = false;
|
|
809
|
+
if (componentProps?.config?.deviceId) {
|
|
810
|
+
targetDeviceId = componentProps.config.deviceId;
|
|
811
|
+
}
|
|
812
|
+
else {
|
|
813
|
+
targetDeviceId = getLastSelectedCameraId() ?? undefined;
|
|
814
|
+
}
|
|
815
|
+
const initialStream = await navigator.mediaDevices
|
|
816
|
+
.getUserMedia({
|
|
817
|
+
video: {
|
|
818
|
+
...videoConstraints,
|
|
819
|
+
...(targetDeviceId
|
|
820
|
+
? { deviceId: { exact: targetDeviceId } }
|
|
821
|
+
: {}),
|
|
822
|
+
},
|
|
781
823
|
audio: false,
|
|
824
|
+
})
|
|
825
|
+
.catch((error) => {
|
|
826
|
+
if (error instanceof DOMException &&
|
|
827
|
+
(error.name === 'NotFoundError' ||
|
|
828
|
+
error.name === 'OverconstrainedError')) {
|
|
829
|
+
// Mark camera as not found when a specific target device (either provided via props
|
|
830
|
+
// or previously selected/saved as default) cannot be accessed.
|
|
831
|
+
if (targetDeviceId && !cameraNotFound) {
|
|
832
|
+
cameraNotFound = true;
|
|
833
|
+
}
|
|
834
|
+
return navigator.mediaDevices.getUserMedia({
|
|
835
|
+
video: {
|
|
836
|
+
...videoConstraints,
|
|
837
|
+
},
|
|
838
|
+
audio: false,
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
throw error;
|
|
782
842
|
});
|
|
783
843
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
784
844
|
const realVideoDevices = devices
|
|
@@ -792,7 +852,7 @@ const livenessMachine = createMachine({
|
|
|
792
852
|
.getTracks()
|
|
793
853
|
.filter((track) => {
|
|
794
854
|
const settings = track.getSettings();
|
|
795
|
-
return settings.frameRate >= 15;
|
|
855
|
+
return (settings.frameRate ?? 0) >= 15;
|
|
796
856
|
});
|
|
797
857
|
if (tracksWithMoreThan15Fps.length < 1) {
|
|
798
858
|
throw new Error('No camera found with more than 15 fps');
|
|
@@ -811,11 +871,16 @@ const livenessMachine = createMachine({
|
|
|
811
871
|
});
|
|
812
872
|
}
|
|
813
873
|
setLastSelectedCameraId(deviceId);
|
|
814
|
-
|
|
874
|
+
const result = {
|
|
815
875
|
stream: realVideoDeviceStream,
|
|
816
876
|
selectedDeviceId: initialStreamDeviceId,
|
|
817
877
|
selectableDevices: realVideoDevices,
|
|
818
878
|
};
|
|
879
|
+
// If a specific camera was requested but not found, trigger a specific error
|
|
880
|
+
if (cameraNotFound) {
|
|
881
|
+
throw new Error(LivenessErrorState.DEFAULT_CAMERA_NOT_FOUND_ERROR);
|
|
882
|
+
}
|
|
883
|
+
return result;
|
|
819
884
|
},
|
|
820
885
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
821
886
|
async openLivenessStreamConnection(context) {
|
|
@@ -1068,11 +1133,22 @@ const livenessMachine = createMachine({
|
|
|
1068
1133
|
livenessStreamProvider.dispatchStreamEvent({ type: 'streamStop' });
|
|
1069
1134
|
},
|
|
1070
1135
|
async getLiveness(context) {
|
|
1071
|
-
const { onAnalysisComplete } = context.componentProps;
|
|
1072
|
-
|
|
1073
|
-
|
|
1136
|
+
const { onAnalysisComplete } = context.componentProps ?? {};
|
|
1137
|
+
if (!onAnalysisComplete) {
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
try {
|
|
1141
|
+
const deviceInfo = getSelectedDeviceInfo(context);
|
|
1142
|
+
await onAnalysisComplete(deviceInfo);
|
|
1143
|
+
}
|
|
1144
|
+
catch (callbackError) {
|
|
1145
|
+
// eslint-disable-next-line no-console
|
|
1146
|
+
console.error('Error in onAnalysisComplete callback:', callbackError);
|
|
1147
|
+
// Rethrow to allow the state machine to handle the error
|
|
1148
|
+
throw callbackError;
|
|
1149
|
+
}
|
|
1074
1150
|
},
|
|
1075
1151
|
},
|
|
1076
1152
|
});
|
|
1077
1153
|
|
|
1078
|
-
export { livenessMachine };
|
|
1154
|
+
export { getSelectedDeviceInfo, livenessMachine };
|
|
@@ -11,6 +11,7 @@ const LivenessErrorState = {
|
|
|
11
11
|
FACE_DISTANCE_ERROR: 'FACE_DISTANCE_ERROR',
|
|
12
12
|
MOBILE_LANDSCAPE_ERROR: 'MOBILE_LANDSCAPE_ERROR',
|
|
13
13
|
MULTIPLE_FACES_ERROR: 'MULTIPLE_FACES_ERROR',
|
|
14
|
+
DEFAULT_CAMERA_NOT_FOUND_ERROR: 'DEFAULT_CAMERA_NOT_FOUND_ERROR',
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
export { LivenessErrorState };
|
package/dist/esm/version.mjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -92,6 +92,7 @@ const LivenessErrorState = {
|
|
|
92
92
|
FACE_DISTANCE_ERROR: 'FACE_DISTANCE_ERROR',
|
|
93
93
|
MOBILE_LANDSCAPE_ERROR: 'MOBILE_LANDSCAPE_ERROR',
|
|
94
94
|
MULTIPLE_FACES_ERROR: 'MULTIPLE_FACES_ERROR',
|
|
95
|
+
DEFAULT_CAMERA_NOT_FOUND_ERROR: 'DEFAULT_CAMERA_NOT_FOUND_ERROR',
|
|
95
96
|
};
|
|
96
97
|
|
|
97
98
|
// Face distance is calculated as pupilDistance / ovalWidth.
|
|
@@ -1055,7 +1056,7 @@ function createRequestStreamGenerator(stream) {
|
|
|
1055
1056
|
};
|
|
1056
1057
|
}
|
|
1057
1058
|
|
|
1058
|
-
const VERSION = '3.
|
|
1059
|
+
const VERSION = '3.5.0';
|
|
1059
1060
|
|
|
1060
1061
|
const BASE_USER_AGENT = `ui-react-liveness/${VERSION}`;
|
|
1061
1062
|
const getLivenessUserAgent = () => {
|
|
@@ -1610,6 +1611,17 @@ const STATIC_VIDEO_CONSTRAINTS = {
|
|
|
1610
1611
|
const CAMERA_ID_KEY = 'AmplifyLivenessCameraId';
|
|
1611
1612
|
const DEFAULT_FACE_FIT_TIMEOUT = 7000;
|
|
1612
1613
|
let responseStream;
|
|
1614
|
+
// Helper function to get selected device info
|
|
1615
|
+
const getSelectedDeviceInfo = (context) => {
|
|
1616
|
+
const selected = context.videoAssociatedParams?.selectableDevices?.find((d) => d.deviceId === context.videoAssociatedParams?.selectedDeviceId);
|
|
1617
|
+
return selected
|
|
1618
|
+
? {
|
|
1619
|
+
deviceId: selected.deviceId,
|
|
1620
|
+
groupId: selected.groupId,
|
|
1621
|
+
label: selected.label ?? '',
|
|
1622
|
+
}
|
|
1623
|
+
: undefined;
|
|
1624
|
+
};
|
|
1613
1625
|
const responseStreamActor = async (callback) => {
|
|
1614
1626
|
try {
|
|
1615
1627
|
const stream = await responseStream;
|
|
@@ -1670,6 +1682,9 @@ const responseStreamActor = async (callback) => {
|
|
|
1670
1682
|
}
|
|
1671
1683
|
}
|
|
1672
1684
|
};
|
|
1685
|
+
function getLastSelectedCameraId() {
|
|
1686
|
+
return localStorage.getItem(CAMERA_ID_KEY);
|
|
1687
|
+
}
|
|
1673
1688
|
function setLastSelectedCameraId(deviceId) {
|
|
1674
1689
|
localStorage.setItem(CAMERA_ID_KEY, deviceId);
|
|
1675
1690
|
}
|
|
@@ -2222,6 +2237,9 @@ const livenessMachine = xstate.createMachine({
|
|
|
2222
2237
|
if (event.data.message.includes('15 fps')) {
|
|
2223
2238
|
errorState = LivenessErrorState.CAMERA_FRAMERATE_ERROR;
|
|
2224
2239
|
}
|
|
2240
|
+
else if (event.data.message.includes(LivenessErrorState.DEFAULT_CAMERA_NOT_FOUND_ERROR)) {
|
|
2241
|
+
errorState = LivenessErrorState.DEFAULT_CAMERA_NOT_FOUND_ERROR;
|
|
2242
|
+
}
|
|
2225
2243
|
else {
|
|
2226
2244
|
errorState = LivenessErrorState.CAMERA_ACCESS_ERROR;
|
|
2227
2245
|
}
|
|
@@ -2231,15 +2249,26 @@ const livenessMachine = xstate.createMachine({
|
|
|
2231
2249
|
state: errorState,
|
|
2232
2250
|
error: error,
|
|
2233
2251
|
};
|
|
2234
|
-
context.componentProps.onError?.(livenessError);
|
|
2252
|
+
context.componentProps.onError?.(livenessError, getSelectedDeviceInfo(context));
|
|
2235
2253
|
return errorState;
|
|
2236
2254
|
},
|
|
2237
2255
|
}),
|
|
2238
2256
|
callMobileLandscapeWarningCallback: xstate.assign({
|
|
2239
2257
|
errorState: () => LivenessErrorState.MOBILE_LANDSCAPE_ERROR,
|
|
2240
2258
|
}),
|
|
2259
|
+
getSelectedDeviceInfo: (context) => getSelectedDeviceInfo(context),
|
|
2241
2260
|
callUserCancelCallback: (context) => {
|
|
2242
|
-
context.componentProps
|
|
2261
|
+
const { onUserCancel } = context.componentProps ?? {};
|
|
2262
|
+
if (!onUserCancel) {
|
|
2263
|
+
return;
|
|
2264
|
+
}
|
|
2265
|
+
try {
|
|
2266
|
+
onUserCancel();
|
|
2267
|
+
}
|
|
2268
|
+
catch (callbackError) {
|
|
2269
|
+
// eslint-disable-next-line no-console
|
|
2270
|
+
console.error('Error in onUserCancel callback:', callbackError);
|
|
2271
|
+
}
|
|
2243
2272
|
},
|
|
2244
2273
|
callUserTimeoutCallback: (context) => {
|
|
2245
2274
|
const error = new Error(context.errorMessage ?? 'Client Timeout');
|
|
@@ -2248,14 +2277,14 @@ const livenessMachine = xstate.createMachine({
|
|
|
2248
2277
|
state: context.errorState,
|
|
2249
2278
|
error: error,
|
|
2250
2279
|
};
|
|
2251
|
-
context.componentProps.onError?.(livenessError);
|
|
2280
|
+
context.componentProps.onError?.(livenessError, getSelectedDeviceInfo(context));
|
|
2252
2281
|
},
|
|
2253
2282
|
callErrorCallback: (context, event) => {
|
|
2254
2283
|
const livenessError = {
|
|
2255
2284
|
state: context.errorState,
|
|
2256
2285
|
error: event.data?.error || event.data,
|
|
2257
2286
|
};
|
|
2258
|
-
context.componentProps.onError?.(livenessError);
|
|
2287
|
+
context.componentProps.onError?.(livenessError, getSelectedDeviceInfo(context));
|
|
2259
2288
|
},
|
|
2260
2289
|
cleanUpResources: (context) => {
|
|
2261
2290
|
const { freshnessColorEl } = context.freshnessColorAssociatedParams;
|
|
@@ -2366,10 +2395,42 @@ const livenessMachine = xstate.createMachine({
|
|
|
2366
2395
|
services: {
|
|
2367
2396
|
async checkVirtualCameraAndGetStream(context) {
|
|
2368
2397
|
const { videoConstraints } = context.videoAssociatedParams;
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2398
|
+
const { componentProps } = context;
|
|
2399
|
+
let targetDeviceId;
|
|
2400
|
+
let cameraNotFound = false;
|
|
2401
|
+
if (componentProps?.config?.deviceId) {
|
|
2402
|
+
targetDeviceId = componentProps.config.deviceId;
|
|
2403
|
+
}
|
|
2404
|
+
else {
|
|
2405
|
+
targetDeviceId = getLastSelectedCameraId() ?? undefined;
|
|
2406
|
+
}
|
|
2407
|
+
const initialStream = await navigator.mediaDevices
|
|
2408
|
+
.getUserMedia({
|
|
2409
|
+
video: {
|
|
2410
|
+
...videoConstraints,
|
|
2411
|
+
...(targetDeviceId
|
|
2412
|
+
? { deviceId: { exact: targetDeviceId } }
|
|
2413
|
+
: {}),
|
|
2414
|
+
},
|
|
2372
2415
|
audio: false,
|
|
2416
|
+
})
|
|
2417
|
+
.catch((error) => {
|
|
2418
|
+
if (error instanceof DOMException &&
|
|
2419
|
+
(error.name === 'NotFoundError' ||
|
|
2420
|
+
error.name === 'OverconstrainedError')) {
|
|
2421
|
+
// Mark camera as not found when a specific target device (either provided via props
|
|
2422
|
+
// or previously selected/saved as default) cannot be accessed.
|
|
2423
|
+
if (targetDeviceId && !cameraNotFound) {
|
|
2424
|
+
cameraNotFound = true;
|
|
2425
|
+
}
|
|
2426
|
+
return navigator.mediaDevices.getUserMedia({
|
|
2427
|
+
video: {
|
|
2428
|
+
...videoConstraints,
|
|
2429
|
+
},
|
|
2430
|
+
audio: false,
|
|
2431
|
+
});
|
|
2432
|
+
}
|
|
2433
|
+
throw error;
|
|
2373
2434
|
});
|
|
2374
2435
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
2375
2436
|
const realVideoDevices = devices
|
|
@@ -2383,7 +2444,7 @@ const livenessMachine = xstate.createMachine({
|
|
|
2383
2444
|
.getTracks()
|
|
2384
2445
|
.filter((track) => {
|
|
2385
2446
|
const settings = track.getSettings();
|
|
2386
|
-
return settings.frameRate >= 15;
|
|
2447
|
+
return (settings.frameRate ?? 0) >= 15;
|
|
2387
2448
|
});
|
|
2388
2449
|
if (tracksWithMoreThan15Fps.length < 1) {
|
|
2389
2450
|
throw new Error('No camera found with more than 15 fps');
|
|
@@ -2402,11 +2463,16 @@ const livenessMachine = xstate.createMachine({
|
|
|
2402
2463
|
});
|
|
2403
2464
|
}
|
|
2404
2465
|
setLastSelectedCameraId(deviceId);
|
|
2405
|
-
|
|
2466
|
+
const result = {
|
|
2406
2467
|
stream: realVideoDeviceStream,
|
|
2407
2468
|
selectedDeviceId: initialStreamDeviceId,
|
|
2408
2469
|
selectableDevices: realVideoDevices,
|
|
2409
2470
|
};
|
|
2471
|
+
// If a specific camera was requested but not found, trigger a specific error
|
|
2472
|
+
if (cameraNotFound) {
|
|
2473
|
+
throw new Error(LivenessErrorState.DEFAULT_CAMERA_NOT_FOUND_ERROR);
|
|
2474
|
+
}
|
|
2475
|
+
return result;
|
|
2410
2476
|
},
|
|
2411
2477
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
2412
2478
|
async openLivenessStreamConnection(context) {
|
|
@@ -2659,9 +2725,20 @@ const livenessMachine = xstate.createMachine({
|
|
|
2659
2725
|
livenessStreamProvider.dispatchStreamEvent({ type: 'streamStop' });
|
|
2660
2726
|
},
|
|
2661
2727
|
async getLiveness(context) {
|
|
2662
|
-
const { onAnalysisComplete } = context.componentProps;
|
|
2663
|
-
|
|
2664
|
-
|
|
2728
|
+
const { onAnalysisComplete } = context.componentProps ?? {};
|
|
2729
|
+
if (!onAnalysisComplete) {
|
|
2730
|
+
return;
|
|
2731
|
+
}
|
|
2732
|
+
try {
|
|
2733
|
+
const deviceInfo = getSelectedDeviceInfo(context);
|
|
2734
|
+
await onAnalysisComplete(deviceInfo);
|
|
2735
|
+
}
|
|
2736
|
+
catch (callbackError) {
|
|
2737
|
+
// eslint-disable-next-line no-console
|
|
2738
|
+
console.error('Error in onAnalysisComplete callback:', callbackError);
|
|
2739
|
+
// Rethrow to allow the state machine to handle the error
|
|
2740
|
+
throw callbackError;
|
|
2741
|
+
}
|
|
2665
2742
|
},
|
|
2666
2743
|
},
|
|
2667
2744
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { LivenessContext, LivenessEvent } from '../types';
|
|
1
|
+
import type { LivenessContext, LivenessEvent, DeviceInfo } from '../types';
|
|
2
|
+
export declare const getSelectedDeviceInfo: (context: LivenessContext) => DeviceInfo | undefined;
|
|
2
3
|
export declare const livenessMachine: import("xstate").StateMachine<LivenessContext, any, LivenessEvent, {
|
|
3
4
|
value: any;
|
|
4
5
|
context: LivenessContext;
|
|
@@ -12,5 +12,6 @@ export declare const LivenessErrorState: {
|
|
|
12
12
|
readonly FACE_DISTANCE_ERROR: "FACE_DISTANCE_ERROR";
|
|
13
13
|
readonly MOBILE_LANDSCAPE_ERROR: "MOBILE_LANDSCAPE_ERROR";
|
|
14
14
|
readonly MULTIPLE_FACES_ERROR: "MULTIPLE_FACES_ERROR";
|
|
15
|
+
readonly DEFAULT_CAMERA_NOT_FOUND_ERROR: "DEFAULT_CAMERA_NOT_FOUND_ERROR";
|
|
15
16
|
};
|
|
16
17
|
export type ErrorState = keyof typeof LivenessErrorState;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { AwsCredentialProvider } from './credentials';
|
|
2
2
|
import type { ErrorState } from './error';
|
|
3
|
+
export interface DeviceInfo {
|
|
4
|
+
deviceId: string;
|
|
5
|
+
groupId: string;
|
|
6
|
+
label: string;
|
|
7
|
+
}
|
|
3
8
|
/**
|
|
4
9
|
* The props for the FaceLivenessDetectorCore which allows for full configuration of auth
|
|
5
10
|
*/
|
|
@@ -11,8 +16,9 @@ export interface FaceLivenessDetectorCoreProps {
|
|
|
11
16
|
/**
|
|
12
17
|
* Callback that signals when the liveness session has completed analysis.
|
|
13
18
|
* At this point a request can be made to GetFaceLivenessSessionResults.
|
|
19
|
+
* @param deviceInfo Information about the selected device
|
|
14
20
|
*/
|
|
15
|
-
onAnalysisComplete: () => Promise<void>;
|
|
21
|
+
onAnalysisComplete: (deviceInfo?: DeviceInfo) => Promise<void>;
|
|
16
22
|
/**
|
|
17
23
|
* The AWS region to stream the video to, for current regional support see the documentation here: FIXME LINK
|
|
18
24
|
*/
|
|
@@ -22,9 +28,11 @@ export interface FaceLivenessDetectorCoreProps {
|
|
|
22
28
|
*/
|
|
23
29
|
onUserCancel?: () => void;
|
|
24
30
|
/**
|
|
25
|
-
* Callback called when there is error
|
|
31
|
+
* Callback called when there is an error on any step
|
|
32
|
+
* @param livenessError The error that occurred
|
|
33
|
+
* @param deviceInfo Information about the selected device, if available
|
|
26
34
|
*/
|
|
27
|
-
onError?: (livenessError: LivenessError) => void;
|
|
35
|
+
onError?: (livenessError: LivenessError, deviceInfo?: DeviceInfo) => void;
|
|
28
36
|
/**
|
|
29
37
|
* Optional parameter for the disabling the Start/Get Ready Screen, default: false
|
|
30
38
|
*/
|
|
@@ -44,6 +52,10 @@ export type FaceLivenessDetectorProps = Omit<FaceLivenessDetectorCoreProps, 'con
|
|
|
44
52
|
config?: FaceLivenessDetectorConfig;
|
|
45
53
|
};
|
|
46
54
|
export interface FaceLivenessDetectorCoreConfig {
|
|
55
|
+
/**
|
|
56
|
+
* Optional device ID to pre-select a camera
|
|
57
|
+
*/
|
|
58
|
+
deviceId?: string;
|
|
47
59
|
/**
|
|
48
60
|
* overrides the Wasm backend binary CDN path
|
|
49
61
|
* default is https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@3.11.0/dist/.
|
|
@@ -66,7 +66,7 @@ export interface LivenessContext {
|
|
|
66
66
|
shouldDisconnect: boolean | undefined;
|
|
67
67
|
videoAssociatedParams: VideoAssociatedParams | undefined;
|
|
68
68
|
}
|
|
69
|
-
export type LivenessEventTypes = 'BEGIN' | 'CONNECTION_TIMEOUT' | 'START_RECORDING' | 'TIMEOUT' | 'ERROR' | 'CANCEL' | 'SET_SESSION_INFO' | 'DISCONNECT_EVENT' | 'SET_DOM_AND_CAMERA_DETAILS' | 'UPDATE_DEVICE_AND_STREAM' | 'SERVER_ERROR' | 'RUNTIME_ERROR' | 'RETRY_CAMERA_CHECK' | 'MOBILE_LANDSCAPE_WARNING';
|
|
69
|
+
export type LivenessEventTypes = 'BEGIN' | 'CONNECTION_TIMEOUT' | 'START_RECORDING' | 'TIMEOUT' | 'ERROR' | 'CANCEL' | 'SET_SESSION_INFO' | 'DISCONNECT_EVENT' | 'SET_DOM_AND_CAMERA_DETAILS' | 'UPDATE_DEVICE_AND_STREAM' | 'CAMERA_NOT_FOUND' | 'SERVER_ERROR' | 'RUNTIME_ERROR' | 'RETRY_CAMERA_CHECK' | 'MOBILE_LANDSCAPE_WARNING';
|
|
70
70
|
export type LivenessEventData = Record<PropertyKey, any>;
|
|
71
71
|
export interface LivenessEvent {
|
|
72
72
|
type: LivenessEventTypes;
|
|
@@ -76,6 +76,7 @@ export declare const LivenessErrorStateStringMap: {
|
|
|
76
76
|
CAMERA_ACCESS_ERROR: string;
|
|
77
77
|
MOBILE_LANDSCAPE_ERROR: string;
|
|
78
78
|
FRESHNESS_TIMEOUT: string;
|
|
79
|
+
DEFAULT_CAMERA_NOT_FOUND_ERROR: string;
|
|
79
80
|
};
|
|
80
81
|
interface FillOverlayCanvasFractionalInput {
|
|
81
82
|
overlayCanvas: HTMLCanvasElement;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { IlluminationState, FaceMatchState } from '../service';
|
|
3
3
|
import type { HintDisplayText } from '../displayText';
|
|
4
|
-
export declare const selectErrorState: import("../hooks").LivenessSelectorFn<"CONNECTION_TIMEOUT" | "TIMEOUT" | "RUNTIME_ERROR" | "FRESHNESS_TIMEOUT" | "SERVER_ERROR" | "CAMERA_FRAMERATE_ERROR" | "CAMERA_ACCESS_ERROR" | "FACE_DISTANCE_ERROR" | "MOBILE_LANDSCAPE_ERROR" | "MULTIPLE_FACES_ERROR" | undefined>;
|
|
4
|
+
export declare const selectErrorState: import("../hooks").LivenessSelectorFn<"CONNECTION_TIMEOUT" | "TIMEOUT" | "RUNTIME_ERROR" | "FRESHNESS_TIMEOUT" | "SERVER_ERROR" | "CAMERA_FRAMERATE_ERROR" | "CAMERA_ACCESS_ERROR" | "FACE_DISTANCE_ERROR" | "MOBILE_LANDSCAPE_ERROR" | "MULTIPLE_FACES_ERROR" | "DEFAULT_CAMERA_NOT_FOUND_ERROR" | undefined>;
|
|
5
5
|
export declare const selectFaceMatchState: import("../hooks").LivenessSelectorFn<FaceMatchState | undefined>;
|
|
6
6
|
export declare const selectIlluminationState: import("../hooks").LivenessSelectorFn<IlluminationState | undefined>;
|
|
7
7
|
export declare const selectIsFaceFarEnoughBeforeRecording: import("../hooks").LivenessSelectorFn<boolean | undefined>;
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "3.
|
|
1
|
+
export declare const VERSION = "3.5.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aws-amplify/ui-react-liveness",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/esm/index.mjs",
|
|
6
6
|
"exports": {
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
"react-dom": "^16.14 || ^17 || ^18 || ^19"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@aws-amplify/ui": "6.
|
|
52
|
-
"@aws-amplify/ui-react": "6.13.
|
|
51
|
+
"@aws-amplify/ui": "6.13.0",
|
|
52
|
+
"@aws-amplify/ui-react": "6.13.2",
|
|
53
53
|
"@aws-sdk/client-rekognitionstreaming": "3.828.0",
|
|
54
54
|
"@aws-sdk/util-format-url": "3.609.0",
|
|
55
55
|
"@smithy/eventstream-serde-browser": "^4.0.4",
|
|
@@ -85,4 +85,4 @@
|
|
|
85
85
|
"limit": "225 kB"
|
|
86
86
|
}
|
|
87
87
|
]
|
|
88
|
-
}
|
|
88
|
+
}
|