@aws-amplify/ui-react-liveness 3.3.9 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/FaceLivenessDetector/FaceLivenessDetectorCore.mjs +4 -2
- package/dist/esm/components/FaceLivenessDetector/LivenessCheck/CameraSelector.mjs +13 -0
- package/dist/esm/components/FaceLivenessDetector/LivenessCheck/LivenessCameraModule.mjs +50 -28
- package/dist/esm/components/FaceLivenessDetector/LivenessCheck/LivenessCheck.mjs +5 -4
- package/dist/esm/components/FaceLivenessDetector/service/machine/machine.mjs +247 -314
- package/dist/esm/components/FaceLivenessDetector/service/utils/ColorSequenceDisplay/ColorSequenceDisplay.mjs +140 -0
- package/dist/esm/components/FaceLivenessDetector/service/utils/StreamRecorder/StreamRecorder.mjs +171 -0
- package/dist/esm/components/FaceLivenessDetector/service/utils/TelemetryReporter/TelemetryReporter.mjs +27 -0
- package/dist/esm/components/FaceLivenessDetector/service/utils/constants.mjs +30 -7
- package/dist/esm/components/FaceLivenessDetector/service/utils/createRequestStreamGenerator/createRequestStreamGenerator.mjs +32 -0
- package/dist/esm/components/FaceLivenessDetector/service/utils/createRequestStreamGenerator/utils.mjs +148 -0
- package/dist/esm/components/FaceLivenessDetector/service/utils/createStreamingClient/Signer.mjs +2 -3
- package/dist/esm/components/FaceLivenessDetector/service/utils/createStreamingClient/createStreamingClient.mjs +36 -6
- package/dist/esm/components/FaceLivenessDetector/service/utils/createStreamingClient/resolveCredentials.mjs +7 -6
- package/dist/esm/components/FaceLivenessDetector/service/utils/getFaceMatchStateInLivenessOval.mjs +9 -5
- package/dist/esm/components/FaceLivenessDetector/service/utils/liveness.mjs +19 -34
- package/dist/esm/components/FaceLivenessDetector/service/utils/{eventUtils.mjs → responseStreamEvent.mjs} +2 -2
- package/dist/esm/components/FaceLivenessDetector/service/utils/sessionInformation.mjs +45 -0
- package/dist/esm/components/FaceLivenessDetector/shared/DefaultStartScreenComponents.mjs +3 -2
- package/dist/esm/components/FaceLivenessDetector/shared/FaceLivenessErrorModal.mjs +4 -2
- package/dist/esm/components/FaceLivenessDetector/shared/Hint.mjs +4 -7
- package/dist/esm/components/FaceLivenessDetector/types/classNames.mjs +3 -0
- package/dist/esm/components/FaceLivenessDetector/utils/device.mjs +12 -12
- package/dist/esm/index.mjs +12 -0
- package/dist/esm/version.mjs +1 -1
- package/dist/index.js +956 -775
- package/dist/styles.css +17 -2
- package/dist/types/components/FaceLivenessDetector/LivenessCheck/CameraSelector.d.ts +8 -0
- package/dist/types/components/FaceLivenessDetector/LivenessCheck/LivenessCameraModule.d.ts +1 -0
- package/dist/types/components/FaceLivenessDetector/index.d.ts +1 -0
- package/dist/types/components/FaceLivenessDetector/service/types/machine.d.ts +37 -24
- package/dist/types/components/FaceLivenessDetector/service/utils/ColorSequenceDisplay/ColorSequenceDisplay.d.ts +55 -0
- package/dist/types/components/FaceLivenessDetector/service/utils/ColorSequenceDisplay/index.d.ts +2 -0
- package/dist/types/components/FaceLivenessDetector/service/utils/StreamRecorder/StreamRecorder.d.ts +15 -0
- package/dist/types/components/FaceLivenessDetector/service/utils/StreamRecorder/index.d.ts +1 -0
- package/dist/types/components/FaceLivenessDetector/service/utils/TelemetryReporter/TelemetryReporter.d.ts +8 -0
- package/dist/types/components/FaceLivenessDetector/service/utils/TelemetryReporter/index.d.ts +2 -0
- package/dist/types/components/FaceLivenessDetector/service/utils/constants.d.ts +27 -3
- package/dist/types/components/FaceLivenessDetector/service/utils/createRequestStreamGenerator/createRequestStreamGenerator.d.ts +15 -0
- package/dist/types/components/FaceLivenessDetector/service/utils/createRequestStreamGenerator/index.d.ts +2 -0
- package/dist/types/components/FaceLivenessDetector/service/utils/createRequestStreamGenerator/utils.d.ts +30 -0
- package/dist/types/components/FaceLivenessDetector/service/utils/createStreamingClient/Signer.d.ts +0 -1
- package/dist/types/components/FaceLivenessDetector/service/utils/createStreamingClient/createStreamingClient.d.ts +27 -5
- package/dist/types/components/FaceLivenessDetector/service/utils/createStreamingClient/index.d.ts +1 -0
- package/dist/types/components/FaceLivenessDetector/service/utils/getFaceMatchStateInLivenessOval.d.ts +3 -4
- package/dist/types/components/FaceLivenessDetector/service/utils/index.d.ts +7 -4
- package/dist/types/components/FaceLivenessDetector/service/utils/liveness.d.ts +15 -26
- package/dist/types/components/FaceLivenessDetector/service/utils/{eventUtils.d.ts → responseStreamEvent.d.ts} +1 -1
- package/dist/types/components/FaceLivenessDetector/service/utils/sessionInformation.d.ts +7 -0
- package/dist/types/components/FaceLivenessDetector/service/utils/types.d.ts +21 -0
- package/dist/types/components/FaceLivenessDetector/types/classNames.d.ts +3 -0
- package/dist/types/components/FaceLivenessDetector/utils/device.d.ts +1 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +8 -8
- package/dist/esm/components/FaceLivenessDetector/service/utils/freshnessColorDisplay.mjs +0 -131
- package/dist/esm/components/FaceLivenessDetector/service/utils/streamProvider.mjs +0 -126
- package/dist/esm/components/FaceLivenessDetector/service/utils/videoRecorder.mjs +0 -108
- package/dist/types/components/FaceLivenessDetector/service/types/service.d.ts +0 -5
- package/dist/types/components/FaceLivenessDetector/service/utils/freshnessColorDisplay.d.ts +0 -21
- package/dist/types/components/FaceLivenessDetector/service/utils/streamProvider.d.ts +0 -42
- package/dist/types/components/FaceLivenessDetector/service/utils/videoRecorder.d.ts +0 -27
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fetchAuthSession } from 'aws-amplify/auth';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const isValidCredentialsProvider = (credentialsProvider) => typeof credentialsProvider === 'function';
|
|
4
4
|
// the return interface of `fetchAuthSession` includes `credentials` as
|
|
5
5
|
// optional, but `credentials` is always returned. If `fetchAuthSession`
|
|
6
6
|
// is called for an unauthenticated end user, values of `accessKeyId`
|
|
@@ -15,13 +15,14 @@ const isCredentials = (credentials) => !!(credentials?.accessKeyId && credential
|
|
|
15
15
|
* @returns {Promise<AwsCredentials | AwsCredentialProvider>} `credentials` object or valid `credentialsProvider` callback
|
|
16
16
|
*/
|
|
17
17
|
async function resolveCredentials(credentialsProvider) {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
if (credentialsProvider && !hasCredentialsProvider) {
|
|
18
|
+
const hasValidCredentialsProvider = isValidCredentialsProvider(credentialsProvider);
|
|
19
|
+
// provided `credentialsProvider` is not valid
|
|
20
|
+
if (credentialsProvider && !hasValidCredentialsProvider) {
|
|
23
21
|
throw new Error('Invalid credentialsProvider');
|
|
24
22
|
}
|
|
23
|
+
if (hasValidCredentialsProvider) {
|
|
24
|
+
return credentialsProvider;
|
|
25
|
+
}
|
|
25
26
|
try {
|
|
26
27
|
const result = (await fetchAuthSession()).credentials;
|
|
27
28
|
if (isCredentials(result)) {
|
package/dist/esm/components/FaceLivenessDetector/service/utils/getFaceMatchStateInLivenessOval.mjs
CHANGED
|
@@ -5,10 +5,9 @@ import { FACE_MATCH_RANGE_MAX, FACE_MATCH_WEIGHT_MAX, FACE_MATCH_WEIGHT_MIN, FAC
|
|
|
5
5
|
/**
|
|
6
6
|
* Returns the state of the provided face with respect to the provided liveness oval.
|
|
7
7
|
*/
|
|
8
|
-
function getFaceMatchStateInLivenessOval({ face, ovalDetails, initialFaceIntersection,
|
|
8
|
+
function getFaceMatchStateInLivenessOval({ face, ovalDetails, initialFaceIntersection, parsedSessionInformation, frameHeight, }) {
|
|
9
9
|
let faceMatchState;
|
|
10
|
-
const challengeConfig =
|
|
11
|
-
?.ChallengeConfig;
|
|
10
|
+
const challengeConfig = parsedSessionInformation.Challenge.ChallengeConfig;
|
|
12
11
|
if (!challengeConfig ||
|
|
13
12
|
!challengeConfig.OvalIouThreshold ||
|
|
14
13
|
!challengeConfig.OvalIouHeightThreshold ||
|
|
@@ -17,8 +16,13 @@ function getFaceMatchStateInLivenessOval({ face, ovalDetails, initialFaceInterse
|
|
|
17
16
|
!challengeConfig.FaceIouWidthThreshold) {
|
|
18
17
|
throw new Error('Challenge information not returned from session information.');
|
|
19
18
|
}
|
|
20
|
-
const { OvalIouThreshold, FaceIouHeightThreshold, FaceIouWidthThreshold } = challengeConfig;
|
|
21
|
-
const faceBoundingBox = generateBboxFromLandmarks(
|
|
19
|
+
const { OvalIouThreshold, FaceIouHeightThreshold, FaceIouWidthThreshold, OvalHeightWidthRatio, } = challengeConfig;
|
|
20
|
+
const faceBoundingBox = generateBboxFromLandmarks({
|
|
21
|
+
ovalHeightWidthRatio: OvalHeightWidthRatio,
|
|
22
|
+
face,
|
|
23
|
+
oval: ovalDetails,
|
|
24
|
+
frameHeight,
|
|
25
|
+
});
|
|
22
26
|
const minFaceX = faceBoundingBox.left;
|
|
23
27
|
const maxFaceX = faceBoundingBox.right;
|
|
24
28
|
const minFaceY = faceBoundingBox.top;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IlluminationState, FaceMatchState } from '../types/liveness.mjs';
|
|
2
2
|
import { LivenessErrorState } from '../types/error.mjs';
|
|
3
|
-
import { PUPIL_DISTANCE_WEIGHT, FACE_HEIGHT_WEIGHT
|
|
3
|
+
import { OVAL_HEIGHT_WIDTH_RATIO, PUPIL_DISTANCE_WEIGHT, FACE_HEIGHT_WEIGHT } from './constants.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Returns the random number between min and max
|
|
@@ -45,9 +45,8 @@ function getIntersectionOverUnion(box1, box2) {
|
|
|
45
45
|
* Returns the details of a randomly generated liveness oval
|
|
46
46
|
* from SDK
|
|
47
47
|
*/
|
|
48
|
-
function getOvalDetailsFromSessionInformation({
|
|
49
|
-
const ovalParameters =
|
|
50
|
-
?.OvalParameters;
|
|
48
|
+
function getOvalDetailsFromSessionInformation({ parsedSessionInformation, videoWidth, }) {
|
|
49
|
+
const ovalParameters = parsedSessionInformation.Challenge.OvalParameters;
|
|
51
50
|
if (!ovalParameters ||
|
|
52
51
|
!ovalParameters.CenterX ||
|
|
53
52
|
!ovalParameters.CenterY ||
|
|
@@ -69,7 +68,7 @@ function getOvalDetailsFromSessionInformation({ sessionInformation, videoWidth,
|
|
|
69
68
|
/**
|
|
70
69
|
* Returns the details of a statically generated liveness oval based on the video dimensions
|
|
71
70
|
*/
|
|
72
|
-
function getStaticLivenessOvalDetails({ width, height, widthSeed = 1.0, centerXSeed = 0.5, centerYSeed = 0.5, ratioMultiplier = 0.8, }) {
|
|
71
|
+
function getStaticLivenessOvalDetails({ width, height, widthSeed = 1.0, centerXSeed = 0.5, centerYSeed = 0.5, ratioMultiplier = 0.8, ovalHeightWidthRatio = OVAL_HEIGHT_WIDTH_RATIO, }) {
|
|
73
72
|
const videoHeight = height;
|
|
74
73
|
let videoWidth = width;
|
|
75
74
|
const ovalRatio = widthSeed * ratioMultiplier;
|
|
@@ -83,7 +82,7 @@ function getStaticLivenessOvalDetails({ width, height, widthSeed = 1.0, centerXS
|
|
|
83
82
|
videoWidth = (3 / 4) * videoHeight;
|
|
84
83
|
}
|
|
85
84
|
const ovalWidth = ovalRatio * videoWidth;
|
|
86
|
-
const ovalHeight =
|
|
85
|
+
const ovalHeight = ovalHeightWidthRatio * ovalWidth;
|
|
87
86
|
return {
|
|
88
87
|
flippedCenterX: Math.floor(videoWidth - centerX),
|
|
89
88
|
centerX: Math.floor(centerX),
|
|
@@ -146,7 +145,7 @@ function drawStaticOval(canvasEl, videoEl, videoMediaStream) {
|
|
|
146
145
|
const ovalDetails = getStaticLivenessOvalDetails({
|
|
147
146
|
width: width,
|
|
148
147
|
height: height,
|
|
149
|
-
ratioMultiplier: 0.
|
|
148
|
+
ratioMultiplier: 0.3,
|
|
150
149
|
});
|
|
151
150
|
ovalDetails.flippedCenterX = width - ovalDetails.centerX;
|
|
152
151
|
// Compute scaleFactor which is how much our video element is scaled
|
|
@@ -180,7 +179,7 @@ function getPupilDistanceAndFaceHeight(face) {
|
|
|
180
179
|
const faceHeight = Math.sqrt((eyeCenter[0] - mouth[0]) ** 2 + (eyeCenter[1] - mouth[1]) ** 2);
|
|
181
180
|
return { pupilDistance, faceHeight };
|
|
182
181
|
}
|
|
183
|
-
function generateBboxFromLandmarks(face, oval, frameHeight) {
|
|
182
|
+
function generateBboxFromLandmarks({ ovalHeightWidthRatio = OVAL_HEIGHT_WIDTH_RATIO, face, oval, frameHeight, }) {
|
|
184
183
|
const { leftEye, rightEye, nose, leftEar, rightEar } = face;
|
|
185
184
|
const { height: ovalHeight, centerY } = oval;
|
|
186
185
|
const ovalTop = centerY - ovalHeight / 2;
|
|
@@ -200,7 +199,7 @@ function generateBboxFromLandmarks(face, oval, frameHeight) {
|
|
|
200
199
|
centerFaceY = eyeCenter[1];
|
|
201
200
|
}
|
|
202
201
|
const faceWidth = ocularWidth;
|
|
203
|
-
const faceHeight =
|
|
202
|
+
const faceHeight = ovalHeightWidthRatio * faceWidth;
|
|
204
203
|
const top = Math.max(centerFaceY - faceHeight / 2, 0);
|
|
205
204
|
const bottom = Math.min(centerFaceY + faceHeight / 2, frameHeight);
|
|
206
205
|
const left = Math.min(centerFaceX - ocularWidth / 2, rightEar[0]);
|
|
@@ -319,11 +318,11 @@ function fillOverlayCanvasFractional({ overlayCanvas, prevColor, nextColor, vide
|
|
|
319
318
|
throw new Error('Cannot find Overlay Canvas.');
|
|
320
319
|
}
|
|
321
320
|
}
|
|
322
|
-
const
|
|
323
|
-
function getColorsSequencesFromSessionInformation(
|
|
324
|
-
const
|
|
321
|
+
const isColorSequence = (obj) => !!obj;
|
|
322
|
+
function getColorsSequencesFromSessionInformation(parsedSessionInformation) {
|
|
323
|
+
const colorSequenceFromServerChallenge = parsedSessionInformation.Challenge
|
|
325
324
|
.ColorSequences ?? [];
|
|
326
|
-
const colorSequences =
|
|
325
|
+
const colorSequences = colorSequenceFromServerChallenge.map(({ FreshnessColor, DownscrollDuration: downscrollDuration, FlatDisplayDuration: flatDisplayDuration, }) => {
|
|
327
326
|
const colorArray = FreshnessColor.RGB;
|
|
328
327
|
const color = `rgb(${colorArray[0]},${colorArray[1]},${colorArray[2]})`;
|
|
329
328
|
return typeof color !== 'undefined' &&
|
|
@@ -336,13 +335,7 @@ function getColorsSequencesFromSessionInformation(sessionInformation) {
|
|
|
336
335
|
}
|
|
337
336
|
: undefined;
|
|
338
337
|
});
|
|
339
|
-
return colorSequences.filter(
|
|
340
|
-
}
|
|
341
|
-
function getRGBArrayFromColorString(colorStr) {
|
|
342
|
-
return colorStr
|
|
343
|
-
.slice(colorStr.indexOf('(') + 1, colorStr.indexOf(')'))
|
|
344
|
-
.split(',')
|
|
345
|
-
.map((str) => parseInt(str));
|
|
338
|
+
return colorSequences.filter(isColorSequence);
|
|
346
339
|
}
|
|
347
340
|
async function getFaceMatchState(faceDetector, videoEl) {
|
|
348
341
|
const detectedFaces = await faceDetector.detectFaces(videoEl);
|
|
@@ -366,7 +359,9 @@ async function getFaceMatchState(faceDetector, videoEl) {
|
|
|
366
359
|
}
|
|
367
360
|
return faceMatchState;
|
|
368
361
|
}
|
|
369
|
-
async function isFaceDistanceBelowThreshold({ faceDetector, videoEl, ovalDetails, reduceThreshold = false,
|
|
362
|
+
async function isFaceDistanceBelowThreshold({ parsedSessionInformation, faceDetector, videoEl, ovalDetails, reduceThreshold = false, }) {
|
|
363
|
+
const challengeConfig = parsedSessionInformation.Challenge.ChallengeConfig;
|
|
364
|
+
const { FaceDistanceThresholdMin, FaceDistanceThreshold } = challengeConfig;
|
|
370
365
|
const detectedFaces = await faceDetector.detectFaces(videoEl);
|
|
371
366
|
let detectedFace;
|
|
372
367
|
let isDistanceBelowThreshold = false;
|
|
@@ -390,10 +385,8 @@ async function isFaceDistanceBelowThreshold({ faceDetector, videoEl, ovalDetails
|
|
|
390
385
|
isDistanceBelowThreshold =
|
|
391
386
|
calibratedPupilDistance / width <
|
|
392
387
|
(!reduceThreshold
|
|
393
|
-
?
|
|
394
|
-
:
|
|
395
|
-
? REDUCED_THRESHOLD_MOBILE
|
|
396
|
-
: REDUCED_THRESHOLD);
|
|
388
|
+
? FaceDistanceThresholdMin
|
|
389
|
+
: FaceDistanceThreshold);
|
|
397
390
|
if (!isDistanceBelowThreshold) {
|
|
398
391
|
error = LivenessErrorState.FACE_DISTANCE_ERROR;
|
|
399
392
|
}
|
|
@@ -408,13 +401,5 @@ async function isFaceDistanceBelowThreshold({ faceDetector, videoEl, ovalDetails
|
|
|
408
401
|
}
|
|
409
402
|
return { isDistanceBelowThreshold, error };
|
|
410
403
|
}
|
|
411
|
-
function getBoundingBox({ deviceHeight, deviceWidth, height, width, top, left, }) {
|
|
412
|
-
return {
|
|
413
|
-
Height: height / deviceHeight,
|
|
414
|
-
Width: width / deviceWidth,
|
|
415
|
-
Top: top / deviceHeight,
|
|
416
|
-
Left: left / deviceWidth,
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
404
|
|
|
420
|
-
export { clearOvalCanvas, drawLivenessOvalInCanvas, drawStaticOval, estimateIllumination, fillOverlayCanvasFractional, generateBboxFromLandmarks,
|
|
405
|
+
export { clearOvalCanvas, drawLivenessOvalInCanvas, drawStaticOval, estimateIllumination, fillOverlayCanvasFractional, generateBboxFromLandmarks, getColorsSequencesFromSessionInformation, getFaceMatchState, getIntersectionOverUnion, getOvalBoundingBox, getOvalDetailsFromSessionInformation, getStaticLivenessOvalDetails, isCameraDeviceVirtual, isFaceDistanceBelowThreshold };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WEBSOCKET_CONNECTION_TIMEOUT_MESSAGE } from './createStreamingClient/CustomWebSocketFetchHandler.mjs';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const isServerSessionInformationEvent = (value) => {
|
|
4
4
|
return !!value
|
|
5
5
|
?.ServerSessionInformationEvent;
|
|
6
6
|
};
|
|
@@ -33,4 +33,4 @@ const isInvalidSignatureRegionException = (error) => {
|
|
|
33
33
|
return (name === 'InvalidSignatureException' && message.includes('valid region'));
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
export { isConnectionTimeoutError, isDisconnectionEvent, isInternalServerExceptionEvent, isInvalidSignatureRegionException,
|
|
36
|
+
export { isConnectionTimeoutError, isDisconnectionEvent, isInternalServerExceptionEvent, isInvalidSignatureRegionException, isServerSessionInformationEvent, isServiceQuotaExceededExceptionEvent, isThrottlingExceptionEvent, isValidationExceptionEvent };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { FACE_MOVEMENT_AND_LIGHT_CHALLENGE, FACE_MOVEMENT_CHALLENGE } from './constants.mjs';
|
|
2
|
+
|
|
3
|
+
const isFaceMovementAndLightChallenge = (value) => {
|
|
4
|
+
return (value?.Challenge?.Name ===
|
|
5
|
+
'FaceMovementAndLightChallenge');
|
|
6
|
+
};
|
|
7
|
+
const isFaceMovementChallenge = (value) => {
|
|
8
|
+
return (value?.Challenge?.Name ===
|
|
9
|
+
'FaceMovementChallenge');
|
|
10
|
+
};
|
|
11
|
+
const isFaceMovementAndLightServerChallenge = (value) => {
|
|
12
|
+
return !!value
|
|
13
|
+
?.FaceMovementAndLightChallenge;
|
|
14
|
+
};
|
|
15
|
+
const isFaceMovementServerChallenge = (value) => {
|
|
16
|
+
return !!value
|
|
17
|
+
?.FaceMovementChallenge;
|
|
18
|
+
};
|
|
19
|
+
const createSessionInfoFromServerSessionInformation = (serverSessionInformation) => {
|
|
20
|
+
let challenge;
|
|
21
|
+
if (isFaceMovementAndLightServerChallenge(serverSessionInformation.Challenge)) {
|
|
22
|
+
challenge = {
|
|
23
|
+
...serverSessionInformation.Challenge.FaceMovementAndLightChallenge,
|
|
24
|
+
Name: FACE_MOVEMENT_AND_LIGHT_CHALLENGE.type,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
else if (isFaceMovementServerChallenge(serverSessionInformation.Challenge)) {
|
|
28
|
+
challenge = {
|
|
29
|
+
...serverSessionInformation.Challenge.FaceMovementChallenge,
|
|
30
|
+
Name: FACE_MOVEMENT_CHALLENGE.type,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
throw new Error('Unsupported challenge type returned from session information.');
|
|
35
|
+
}
|
|
36
|
+
if (!challenge.ChallengeConfig ||
|
|
37
|
+
!challenge.ChallengeConfig.FaceDistanceThreshold ||
|
|
38
|
+
!challenge.ChallengeConfig.FaceDistanceThresholdMin ||
|
|
39
|
+
!challenge.ChallengeConfig.OvalHeightWidthRatio) {
|
|
40
|
+
throw new Error('Challenge config not returned from session information.');
|
|
41
|
+
}
|
|
42
|
+
return { ...serverSessionInformation, Challenge: challenge };
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export { createSessionInfoFromServerSessionInformation, isFaceMovementAndLightChallenge, isFaceMovementAndLightServerChallenge, isFaceMovementChallenge, isFaceMovementServerChallenge };
|
|
@@ -9,9 +9,10 @@ import '@tensorflow-models/face-detection';
|
|
|
9
9
|
import '@tensorflow/tfjs-backend-wasm';
|
|
10
10
|
import '@tensorflow/tfjs-backend-cpu';
|
|
11
11
|
import '@aws-amplify/core/internals/utils';
|
|
12
|
-
import '
|
|
12
|
+
import '../service/utils/constants.mjs';
|
|
13
|
+
import '../service/utils/ColorSequenceDisplay/ColorSequenceDisplay.mjs';
|
|
13
14
|
import '../service/utils/createStreamingClient/createStreamingClient.mjs';
|
|
14
|
-
import '../service/utils/
|
|
15
|
+
import '../service/utils/StreamRecorder/StreamRecorder.mjs';
|
|
15
16
|
import '@xstate/react';
|
|
16
17
|
import '../providers/FaceLivenessDetectorProvider.mjs';
|
|
17
18
|
import { LivenessClassNames } from '../types/classNames.mjs';
|
|
@@ -9,9 +9,11 @@ import '@tensorflow-models/face-detection';
|
|
|
9
9
|
import '@tensorflow/tfjs-backend-wasm';
|
|
10
10
|
import '@tensorflow/tfjs-backend-cpu';
|
|
11
11
|
import '@aws-amplify/core/internals/utils';
|
|
12
|
-
import '
|
|
12
|
+
import '../service/utils/constants.mjs';
|
|
13
|
+
import '../service/utils/ColorSequenceDisplay/ColorSequenceDisplay.mjs';
|
|
14
|
+
import '@aws-amplify/ui';
|
|
13
15
|
import '../service/utils/createStreamingClient/createStreamingClient.mjs';
|
|
14
|
-
import '../service/utils/
|
|
16
|
+
import '../service/utils/StreamRecorder/StreamRecorder.mjs';
|
|
15
17
|
import { Toast } from './Toast.mjs';
|
|
16
18
|
import { Overlay } from './Overlay.mjs';
|
|
17
19
|
import { defaultErrorDisplayText } from '../displayText.mjs';
|
|
@@ -7,12 +7,13 @@ import '@tensorflow-models/face-detection';
|
|
|
7
7
|
import '@tensorflow/tfjs-backend-wasm';
|
|
8
8
|
import '@tensorflow/tfjs-backend-cpu';
|
|
9
9
|
import '@aws-amplify/core/internals/utils';
|
|
10
|
-
import '
|
|
10
|
+
import '../service/utils/constants.mjs';
|
|
11
|
+
import '../service/utils/ColorSequenceDisplay/ColorSequenceDisplay.mjs';
|
|
12
|
+
import '@aws-amplify/ui';
|
|
11
13
|
import '../service/utils/createStreamingClient/createStreamingClient.mjs';
|
|
12
|
-
import '../service/utils/
|
|
14
|
+
import '../service/utils/StreamRecorder/StreamRecorder.mjs';
|
|
13
15
|
import { useLivenessActor } from '../hooks/useLivenessActor.mjs';
|
|
14
16
|
import { createLivenessSelector, useLivenessSelector } from '../hooks/useLivenessSelector.mjs';
|
|
15
|
-
import '@aws-amplify/ui';
|
|
16
17
|
import { Toast } from './Toast.mjs';
|
|
17
18
|
import { ToastWithLoader } from './ToastWithLoader.mjs';
|
|
18
19
|
|
|
@@ -41,7 +42,6 @@ const Hint = ({ hintDisplayText }) => {
|
|
|
41
42
|
state.matches('detectFaceDistanceBeforeRecording');
|
|
42
43
|
const isStartView = state.matches('start') || state.matches('userCancel');
|
|
43
44
|
const isRecording = state.matches('recording');
|
|
44
|
-
const isNotRecording = state.matches('notRecording');
|
|
45
45
|
const isUploading = state.matches('uploading');
|
|
46
46
|
const isCheckSuccessful = state.matches('checkSucceeded');
|
|
47
47
|
const isCheckFailed = state.matches('checkFailed');
|
|
@@ -81,9 +81,6 @@ const Hint = ({ hintDisplayText }) => {
|
|
|
81
81
|
isFaceFarEnoughBeforeRecordingState === false) {
|
|
82
82
|
return React.createElement(DefaultToast, { text: hintDisplayText.hintTooCloseText });
|
|
83
83
|
}
|
|
84
|
-
if (isNotRecording) {
|
|
85
|
-
return (React.createElement(ToastWithLoader, { displayText: hintDisplayText.hintConnectingText }));
|
|
86
|
-
}
|
|
87
84
|
if (isUploading) {
|
|
88
85
|
return (React.createElement(React.Fragment, null,
|
|
89
86
|
React.createElement(VisuallyHidden, { "aria-live": "assertive" }, hintDisplayText.hintCheckCompleteText),
|
|
@@ -3,6 +3,8 @@ var LivenessClassNames;
|
|
|
3
3
|
LivenessClassNames["CameraModule"] = "amplify-liveness-camera-module";
|
|
4
4
|
LivenessClassNames["CancelContainer"] = "amplify-liveness-cancel-container";
|
|
5
5
|
LivenessClassNames["CancelButton"] = "amplify-liveness-cancel-button";
|
|
6
|
+
LivenessClassNames["CenteredLoader"] = "amplify-liveness-centered-loader";
|
|
7
|
+
LivenessClassNames["ConnectingLoader"] = "amplify-liveness-connecting-loader";
|
|
6
8
|
LivenessClassNames["CountdownContainer"] = "amplify-liveness-countdown-container";
|
|
7
9
|
LivenessClassNames["DescriptionBullet"] = "amplify-liveness-description-bullet";
|
|
8
10
|
LivenessClassNames["DescriptionBulletIndex"] = "amplify-liveness-description-bullet__index";
|
|
@@ -42,6 +44,7 @@ var LivenessClassNames;
|
|
|
42
44
|
LivenessClassNames["Toast"] = "amplify-liveness-toast";
|
|
43
45
|
LivenessClassNames["ToastContainer"] = "amplify-liveness-toast__container";
|
|
44
46
|
LivenessClassNames["ToastMessage"] = "amplify-liveness-toast__message";
|
|
47
|
+
LivenessClassNames["UserFacingVideo"] = "amplify-liveness-video--user-facing";
|
|
45
48
|
LivenessClassNames["Video"] = "amplify-liveness-video";
|
|
46
49
|
LivenessClassNames["VideoAnchor"] = "amplify-liveness-video-anchor";
|
|
47
50
|
})(LivenessClassNames || (LivenessClassNames = {}));
|
|
@@ -11,6 +11,17 @@ function isMobileScreen() {
|
|
|
11
11
|
/Android|iPhone|iPad/i.test(navigator.userAgent) || isNewerIpad();
|
|
12
12
|
return isMobileDevice;
|
|
13
13
|
}
|
|
14
|
+
async function isDeviceUserFacing(deviceId) {
|
|
15
|
+
const devices = await navigator.mediaDevices?.enumerateDevices();
|
|
16
|
+
// Find the video input device with the matching deviceId
|
|
17
|
+
const videoDevice = devices?.find((device) => device.deviceId === deviceId && device.kind === 'videoinput');
|
|
18
|
+
if (videoDevice) {
|
|
19
|
+
// Check if the device label contains the word "back"
|
|
20
|
+
return !videoDevice.label.toLowerCase().includes('back');
|
|
21
|
+
}
|
|
22
|
+
// If the device is not found or not a video input device, return false
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
14
25
|
/**
|
|
15
26
|
* Use window.matchMedia to direct landscape orientation
|
|
16
27
|
* screen.orientation is not supported in Safari so we will use
|
|
@@ -20,16 +31,5 @@ function isMobileScreen() {
|
|
|
20
31
|
function getLandscapeMediaQuery() {
|
|
21
32
|
return window.matchMedia('(orientation: landscape)');
|
|
22
33
|
}
|
|
23
|
-
// minor version 146+ is confirmed to have the fix https://issues.chromium.org/issues/343199623#comment34
|
|
24
|
-
function isAndroidChromeWithBrokenH264() {
|
|
25
|
-
const groups = /Chrome\/125\.[0-9]+\.[0-9]+\.([0-9]+)/i.exec(navigator.userAgent);
|
|
26
|
-
if (!groups) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
const minorVersion = groups[1];
|
|
30
|
-
return (/Android/i.test(navigator.userAgent) &&
|
|
31
|
-
/Chrome\/125/i.test(navigator.userAgent) &&
|
|
32
|
-
parseInt(minorVersion) < 146);
|
|
33
|
-
}
|
|
34
34
|
|
|
35
|
-
export { getLandscapeMediaQuery,
|
|
35
|
+
export { getLandscapeMediaQuery, isDeviceUserFacing, isMobileScreen };
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
1
|
export { default as FaceLivenessDetector } from './components/FaceLivenessDetector/FaceLivenessDetector.mjs';
|
|
2
2
|
export { default as FaceLivenessDetectorCore } from './components/FaceLivenessDetector/FaceLivenessDetectorCore.mjs';
|
|
3
|
+
import './components/FaceLivenessDetector/service/machine/machine.mjs';
|
|
4
|
+
import './components/FaceLivenessDetector/service/types/liveness.mjs';
|
|
5
|
+
import '@tensorflow/tfjs-core';
|
|
6
|
+
import '@tensorflow-models/face-detection';
|
|
7
|
+
import '@tensorflow/tfjs-backend-wasm';
|
|
8
|
+
import '@tensorflow/tfjs-backend-cpu';
|
|
9
|
+
import '@aws-amplify/core/internals/utils';
|
|
10
|
+
import './components/FaceLivenessDetector/service/utils/constants.mjs';
|
|
11
|
+
import './components/FaceLivenessDetector/service/utils/ColorSequenceDisplay/ColorSequenceDisplay.mjs';
|
|
12
|
+
import '@aws-amplify/ui';
|
|
13
|
+
import './components/FaceLivenessDetector/service/utils/createStreamingClient/createStreamingClient.mjs';
|
|
14
|
+
import './components/FaceLivenessDetector/service/utils/StreamRecorder/StreamRecorder.mjs';
|
package/dist/esm/version.mjs
CHANGED