Веб-компонента Lite
Обзор
Веб-компонента является ключевой частью системы BAF, представляя собой пользовательский интерфейс, используемый для сбора данных о пользователе, выполнения биометрических проверок и отправки данных на сервер. Он интегрируется в существующую систему со стороны интерфейса и служит дополнительным уровнем биометрической верификации пользователя.
Установка веб-компоненты
Веб-компонента поставляется в виде TGZ-архива tdvc-face-onboarding. Он также требует библиотеку tdvc, которая поставляется отдельно в виде архива.
Переместите архивы в корневую папку вашего проекта и добавьте следующие строки в ваш package.json в раздел dependencies:
"@tdvc/face-onboarding": "file:tdvc-face-onboarding-{version}.tgz"Версия архива может отличаться. Пример итогового package.json:
"dependencies": {
"@tdvc/face-onboarding": "file:tdvc-face-onboarding-1.0.0.tgz"
}Выполните команду
npm install, которая установит библиотеку в ваш проект.Для корректной работы веб-компоненты необходимо добавить ряд файлов в каталог, где хранятся статические ресурсы вашего проекта, обычно это каталог public. После установки пакета переместите папки images и networks из /node_modules/@tdvc/face-onboarding/ и файл frame_handler_worker.js из /node_modules/@tdvc/face-onboarding/dist в каталог public.
Импорт и использование веб-компоненты
- Импортируйте библиотеку и стили для нее.
- Определите конфигурацию веб-компоненты.
- Запустите проект.
Пример инициализации компонента
import tdvc, { IWebComponent, LiteComponentSettingsFromClient, LiteValidationResult } from '@tdvc/face-onboarding';
import '@tdvc/face-onboarding/dist/css/style.css';
import './style.css';
let lib: IWebComponent;
const configuration: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
callbacks: {
onValidate: (data: LiteValidationResult) => {
console.log('On validation callback', data);
},
},
};
function run() {
lib = new tdvc.Lite(configuration);
}
window.onload = () => {
run();
};
window.onbeforeunload = async () => {
await lib.destroy();
};
Как это работает
Поведение веб-компоненты определяется его конфигурационными настройками и может соответствующим образом изменяться. Полный алгоритм выглядит следующим образом:
Инициализация веб-компоненты
Веб-компонента получает конфигурацию от фронтенда проекта и проверяет её.
Веб-компонента получает доступ к веб-камере устройства пользователя
Веб-компонента запрашивает доступ к веб-камере пользователя. Если устройство найдено и доступ предоставлен, он отображает видеопоток; в противном случае выводится сообщение об ошибке. Если доступно несколько устройств, пользователю предоставляется возможность выбрать, какое из них использовать.
Биометрическая проверка "Motion Control"
Веб-компонента генерирует последовательность команд для выполнения пользователем перед камерой. Эти команды включают: поворот головы влево, поворот головы вправо, поднятие головы, приближение к камере и отдаление от камеры.
Во время этой проверки захватываются кадры, содержащие лицо пользователя. Эти кадры затем используются для дополнительных проверок на стороне сервера, таких как определение живости лица, оценка качества изображения и другие.
Биометрическая верификация лица пользователя
Это вспомогательный этап, который активируется, когда биометрическая проверка "Motion Control" отключена.
Веб-компонента фиксирует положение головы пользователя и извлекает кадры, содержащие лицо пользователя, которые затем используются для дополнительных проверок на стороне сервера, таких как определение живости лица, оценка качества изображения и другие.
Проверка собранных данных и результатов биометрических проверок
Веб-компонента получает результат биометрических оценок для наилучшего кадра (bestshot) лица, и если на вход компонента было передано изображение для сравнения, выполняет сравнение схожести лиц.
Настройки веб-компоненты
Общие настройки
Поле
mountElementиспользуется для указания ID HTML-элемента, в который будет встроена веб-компонента. При установке значения убедитесь, что элемент с этим идентификатором существует в DOM, иначе инициализация будет прервана и будет сгенерирована ошибка, которую можно просмотреть в терминале браузера.Поле
baseUrlиспользуется для указания URL-адреса BAF API. Если передать значение "/", то запросы будут отправляться на хост, на котором развернута веб-компонента. Значение должно быть действительным URL-адресом.Поле
authenticationTokenиспользуется для передачи JWT-токена, который будет использоваться сервером для аутентификации компонента. JWT-токен передаётся внутри запросов и помогает серверу определить, что интеграция использовалась проверенным пользователем.Поле
externalLinkиспользуется для группировки попыток по единому идентификатору.
Пример конфигурации с общими настройками веб-компоненты
import { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const configuration: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
};
Настройки аутентификации
- Поле
authenticationTokenиспользуется для передачи JWT-токена, который будет использоваться сервером для аутентификации компонента. JWT-токен передаётся внутри запросов и помогает серверу определить, что интеграция использовалась проверенным пользователем.
Настройки детектора лиц
Поле
networksPathиспользуется для определения пути к ресурсам, необходимым для инициализации детектора лиц. Значение по умолчанию: '/networks/'.Поле
faceModelSettingsиспользуется для определения настроек детектора лиц. Содержит настройкиmodelEnabled,timeToStartRecordиangleСalculation.Поле
modelEnabledиспользуется для включения или отключения детектора лиц. Если детектор выключен, все процессы, связанные с обнаружением, будут отключены. Например, если обнаружение отключено, проверка Motion Control будет пропущена, вместо динамического определения положения лица будет использоваться статическое.Поле
timeToStartRecordиспользуется, когда детектор выключен, чтобы дать пользователю время занять необходимое положение в кадре перед началом биометрических проверок. Указывает время в миллисекундах.Поле
angleСalculationиспользуется для вычисления углов поворота лица и определения вращения лица. Содержит настройкуangles.Поле
anglesиспользуется для определения граничных значений положения лица. Содержит настройкиleft,rightиup.Поле
leftиспользуется для определения, при каком угле поворота лица пользователя компонент должен считать, что голова пользователя повернута влево.Поле
rightиспользуется для определения, при каком угле поворота лица пользователя компонент должен считать, что голова пользователя повернута вправо.Поле
upиспользуется для определения, при каком угле поворота лица пользователя компонент должен считать, что голова пользователя поднята вверх.
Поле
detectorOptionsиспользуется для определения опций детектора лиц. Содержит настройкиdelegateиminFaceDetectionConfidence.- Поле
delegateиспользуется для определения, какой процессор будет использоваться для обработки кадра. Допустимые значения: CPU, GPU и AUTO. По умолчанию AUTO. В автоматическом режиме компонент сначала попытается инициализировать детектор на GPU, а в случае неудачи — переинициализировать его на CPU. - Поле
minFaceDetectionConfidenceиспользуется для определения порога уверенности обнаружения. Если обнаружение имеет уверенность ниже установленного, оно не будет обрабатываться компонентом. По умолчанию 0.3.
- Поле
Поле
heathcheckImagePathиспользуется для определения пути к ресурсам, необходимым для проверки работоспособности детектора лиц. Значение по умолчанию: '/images/face_detector/face.jpg'.
Пример конфигурации с настройками детектора лиц
import tdvc, { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
networksPath: '/networks/',
faceModelSettings: {
modelEnabled: true,
timeToStartRecord: 10_000,
angleСalculation: {
angles: {
left: 25,
right: 25,
up: 25,
},
},
detectorOptions: { delegate: tdvc.FaceDetectorDelegateMode.AUTO, minFaceDetectionConfidence: 0.3 },
heathcheckImagePath: '/images/face_detector/face.jpg',
},
};
Настройки заявителя
- Поле
applicantPhotoиспользуется для определения изображения, которое будет использоваться при сравнении лиц вместе с наилучшим кадром (bestshot). Значение должно быть в формате строки base64.
Пример настройки applicantPhoto
import { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
applicantPhoto: 'data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAJYAlgDASIAAhEBAxEB/8QAHAABAAEFAQEAAAAAAAAAAAAAAAQCAwUGBwEI/8QAQRAAAQQBAwMDAgQEBAQFAwUAAQACA...',
};
Настройки камеры
Поле
cameraSettingsиспользуется для определения настроек камеры. Содержит настройкиcameraResolution,cameraId,autoSubmitиpermissionInBrowserTimeout.Поле
cameraResolutionиспользуется для настройки разрешения камеры. Чем выше разрешение, тем больше ресурсов устройства будет использоваться при обработке кадров. Принимает значения "fhd" для Full HD, "hd" для HD и "sd" для SD.Поле
cameraIdиспользуется для указания ID конкретной камеры, которую следует использовать. Может быть полезно, если камера имеет несколько режимов работы и требуется использовать конкретный режим, или если устройство имеет несколько камер и нужно использовать конкретную.Поле
autoSubmitиспользуется для пропуска выбора камеры, если устройство имеет более одной камеры. Обратите внимание, что если true, веб-компонента будет использовать первую доступную камеру, а порядок камер может меняться.Поле
permissionInBrowserTimeoutиспользуется для определения времени ожидания подтверждения доступа к камере. По умолчанию 30 000 миллисекунд. По истечении установленного времени, если пользователь не подтверждает доступ к камере, будет сгенерирована ошибка «Not allowed access to camera». Если установлено 0, ограничение времени на подтверждение отсутствует.
Пример конфигурации с cameraSettings
import tdvc, { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
cameraSettings: {
autoSubmit: true,
cameraResolution: tdvc.CameraResolutions.HD,
permissionInBrowserTimeout:10_000
},
};
Пример конфигурации с настройкой cameraId
import { ComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: ComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
integrationId: '225c74bb-4eb1-4c81-9199-832dff3806eb',
cameraSettings: {
cameraId: '3eef5faa7a2f81c50e5fc30c2362bc4be0d208c86a8cdb0642f2194cc25492ac',
},
};
Настройки Motion Control
Поле
motionControlиспользуется для определения настроек Motion Control. Содержит настройкиenabled,faceBorder,imagesHints,description.Поле
enabledиспользуется для включения или отключения Motion Control. По умолчанию true.Поле
faceBorderсодержит настройки для определения положения лица во время проверки. Граница лица может вычисляться на основе детекции лица (динамический режим) или на основе разрешения видеопотока (статический режим). Содержит настройкиallowableAccuracyError,faceWidthCoefficientsиautodetected.Поле
allowableAccuracyErrorиспользуется для вычисления погрешности размера между обнаруженным лицом и границей лица. Содержит настройкиxиy. Значения указываются в процентах от 1 до 100, рекомендуемое соотношение 2/3. По умолчаниюx= 20,y= 30.Поле
faceWidthCoefficientsиспользуется для вычисления размера границы лица на основе ширины максимального разрешения камеры. То есть ширина границы лица вычисляется как максимальная ширина камеры коэффициент для разрешения / 100, а высота кадра вычисляется как ширина границы лица 3/2 для сохранения соотношения 2/3. Содержит настройкиfullHd,hdиsd, которые содержат коэффициент для разрешения в процентах. По умолчаниюfullHd= 20,hd= 24,sd= 33. Используется только в статическом режиме.Поле
autodetectedиспользуется для настройки процесса определения начального положения лица с помощью детекции лица. Содержит настройкиenabled,frameCheckLimit,availableDeviation,framePaddingиfaceSize.Поле
enabledиспользуется для переключения режима границы лица. Если true, то граница будет вычисляться на основе детекции лица, иначе — на основе разрешения камеры. По умолчанию true.Поле
frameCheckLimitиспользуется для установки количества кадров, на которых лицо должно присутствовать и находиться в определённом положении с учётом погрешности, чтобы зафиксировать начальное положение лица перед биометрическими проверками. Обратите внимание, что на разных устройствах время проверки может отличаться в зависимости от производительности устройства. По умолчанию 60.Поле
availableDeviationиспользуется для определения допустимой погрешности, которая используется при вычислении динамической границы лица, с которой положение текущего обнаруженного лица может отклоняться от расчётного начального положения лица. По умолчанию 20.Поле
framePaddingиспользуется для определения расстояния от границ кадра, при котором детекция лица сбросит процесс определения начального положения. Необходимо для исключения ситуаций, когда начальное положение находится на краю кадра или за его пределами. Содержит настройкиhorizontalиvertical. По умолчаниюhorizontal= 10,vertical= 10.Поле
faceSizeиспользуется для определения минимальных и максимальных допустимых размеров (в пикселях) обнаруженного лица. Необходимо для контроля расстояния лица до камеры и предотвращения ситуаций, когда лицо слишком маленькое или слишком большое. Содержит настройкиminиmax, каждая из которых содержит настройкиwidthиheight. По умолчаниюmin= {width: 120, height: 140},max= {width: 360, height: 520}.
Поле
patternSettingsиспользуется для определения настроек действий Motion Control. Содержит настройкиenableSaveFrames,autoGeneration,autoGenerationPatternActionsList,autoGenerationPatternLengthиspecifiedPatternList.Поле
enableSaveFramesиспользуется для включения или отключения режима сохранения кадров лиц, которые были проверены. Кадр сохраняется для каждого действия, прошедшего проверку. По умолчанию false.Поле
autoGenerationиспользуется для включения или отключения режима случайной генерации действий Motion Control. По умолчанию true.Поле
autoGenerationPatternActionsListиспользуется для определения массива действий, которые будут использоваться при автоматической генерации. По умолчанию [MotionControlActions.LEFT, MotionControlActions.RIGHT].Поле
autoGenerationPatternLengthиспользуется для определения количества действий для прохождения Motion Control. По умолчанию 3.Поле
specifiedPatternListиспользуется для определения наборов действий, которые будут использоваться, когда режим автоматической генерации действий выключен. По умолчанию [[MotionControlActions.LEFT, MotionControlActions.RIGHT], [MotionControlActions.RIGHT, MotionControlActions.LEFT]].
Поле
imagesHintsиспользуется для настройки GIF-подсказок для действий Motion Control. Содержит настройкиenabledиresourcesPath.Поле
enabledиспользуется для включения или отключения GIF-подсказок для действий Motion Control. По умолчанию false.Поле
resourcesPathиспользуется для определения пути к папке, содержащей GIF-изображения. Папка должна содержать изображения с именами "left", "right", "up", "center", "farther" и "closer" с расширением gif. Значение по умолчанию: "/images/motion_control_gif_hint/".
Поле
descriptionиспользуется для настройки отображения блока с описанием проверки Motion Control. Содержит настройкиenabledиautoSubmit.Поле
enabledиспользуется для включения или отключения описания Motion Control. По умолчанию true.Поле
autoSubmitиспользуется для настройки автоматического перехода через заданный промежуток времени. Содержит настройкиenabledиtimer.Поле
enabledиспользуется для включения или отключения автоматического перехода. По умолчанию false.Поле
timerиспользуется для установки времени ожидания в миллисекундах, по истечении которого будет выполнен переход, если пользователь не выполнит переход самостоятельно. Значение должно быть больше 0. По умолчанию 30 000.
Пример конфигурации с настройками enabled для Motion Control
import { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
motionControl: {
enabled: true,
},
}
Пример конфигурации с настройкой faceBorder для статической границы лица
import { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
motionControl: {
faceBorder: {
faceWidthCoefficients: {
fullHd: 20,
hd: 24,
sd: 33,
},
allowableAccuracyError: {
x: 20,
y: 30,
},
autodetected: {
enabled: false,
},
},
},
}
Пример конфигурации с настройкой faceBorder для динамической границы лица
import { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
motionControl: {
faceBorder: {
autodetected: {
enabled: true,
frameCheckLimit: 60,
availableDeviation: 20,
framePadding: {
horizontal: 10,
vertical: 10,
},
faceSize: {
min: {
width: 120,
height: 140,
},
max: {
width: 360,
height: 520,
},
},
},
},
},
}
Пример конфигурации с настройками сохранения кадров шаблонов
import { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
motionControl: {
patternSettings: {
enableSaveFrames: true,
},
},
}
Пример конфигурации с настройками автоматической генерации шаблонов
import tdvc, { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
motionControl: {
patternSettings: {
autoGeneration: true,
autoGenerationPatternLength: 3,
autoGenerationPatternActionsList: [
tdvc.MotionControlActions.LEFT,
tdvc.MotionControlActions.RIGHT,
tdvc.MotionControlActions.UP,
tdvc.MotionControlActions.FARTHER,
tdvc.MotionControlActions.CLOSER,
],
},
},
}
Пример конфигурации без автоматической генерации шаблонов
import tdvc, { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
motionControl: {
patternSettings: {
autoGeneration: false,
specifiedPatternList: [
[tdvc.MotionControlActions.LEFT, tdvc.MotionControlActions.RIGHT],
[tdvc.MotionControlActions.LEFT, tdvc.MotionControlActions.LEFT],
[tdvc.MotionControlActions.UP],
],
},
},
}
Пример конфигурации с настройками imageHints
import { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
motionControl: {
imagesHints: {
enabled: true,
resourcesPath: "/path_to_images"
}
},
}
Пример конфигурации с настройками description
import { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
motionControl: {
description: {
enabled: true,
autoSubmit: {
enabled: true,
timer: 30_000,
},
},
},
}
Пример конфигурации с настройками таймера
import { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
motionControl: {
description: {
enabled: true,
autoSubmit: {
enabled: true,
timer: 30_000,
},
},
},
}
Настройки биометрической проверки лица пользователя
Поле
faceBestshotSettingsиспользуется для определения настроек биометрической проверки лица пользователя. Параметр содержит настройкуfaceBorder.Поле
faceBorderсодержит настройки для определения положения лица во время проверки. Граница лица может вычисляться на основе детекции лица (динамический режим) или на основе разрешения видеопотока (статический режим). Параметр содержит настройкиallowableAccuracyError,faceWidthCoefficientsиautodetected.Поле
allowableAccuracyErrorиспользуется для вычисления погрешности размера между обнаруженным лицом и границей лица. Содержит настройкиxиy. Значения указываются в процентах от 1 до 100, рекомендуемое соотношение 2/3. По умолчаниюx= 20,y= 30.Поле
faceWidthCoefficientsиспользуется для вычисления размера границы лица на основе ширины максимального разрешения камеры. То есть ширина границы лица вычисляется как максимальная ширина камеры коэффициент для разрешения / 100, а высота кадра вычисляется как ширина границы лица 3/2 для сохранения соотношения 2/3. Содержит настройкиfullHd,hdиsd, которые содержат коэффициент для разрешения в процентах. По умолчаниюfullHd= 20,hd= 24,sd= 33. Используется только в статическом режиме.Поле
autodetectedиспользуется для настройки процесса определения начального положения лица с помощью детекции лица. Параметр содержит настройкиenabled,frameCheckLimit,availableDeviation,framePaddingиfaceSize.Поле
enabledиспользуется для переключения режима границы лица. Если true, граница будет вычисляться на основе детекции лица, иначе — на основе разрешения камеры. Значение по умолчанию — true.Поле
frameCheckLimitиспользуется для установки количества кадров, на которых лицо должно присутствовать и находиться в определённом положении с учётом погрешности, чтобы зафиксировать начальное положение лица перед биометрическими проверками. Обратите внимание, что на разных устройствах время проверки может отличаться в зависимости от производительности устройства. Значение по умолчанию — 60.Поле
availableDeviationиспользуется для определения допустимой погрешности, которая используется при вычислении динамической границы лица, с которой положение текущего обнаруженного лица может отклоняться от расчётного начального положения лица. Значение по умолчанию — 20.Поле
framePaddingиспользуется для определения расстояния от границ кадра, при котором детекция лица сбросит процесс определения начального положения. Необходимо для исключения ситуаций, когда начальное положение находится на краю кадра или за его пределами. Параметр содержит настройкиhorizontalиvertical. По умолчаниюhorizontal= 10,vertical= 10.Поле
faceSizeиспользуется для определения минимальных и максимальных допустимых размеров (в пикселях) обнаруженного лица. Необходимо для контроля расстояния лица до камеры и предотвращения ситуаций, когда лицо слишком маленькое или слишком большое. Параметр содержит настройкиminиmax, каждая из которых содержит поляwidthиheight. По умолчаниюmin= {width: 120, height: 140},max= {width: 360, height: 520}.
Пример конфигурации с настройкой faceBorder для статической границы лица
import { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
faceBestshotSettings: {
faceBorder: {
faceWidthCoefficients: {
fullHd: 20,
hd: 24,
sd: 33,
},
allowableAccuracyError: {
x: 20,
y: 30,
},
autodetected: {
enabled: false,
},
},
},
}
Пример конфигурации с настройкой faceBorder для динамической границы лица
import { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
faceBestshotSettings: {
faceBorder: {
autodetected: {
enabled: true,
frameCheckLimit: 60,
availableDeviation: 20,
framePadding: {
horizontal: 10,
vertical: 10,
},
faceSize: {
min: {
width: 120,
height: 140,
},
max: {
width: 360,
height: 520,
},
},
},
},
},
}
Локализация
По умолчанию веб-компонента поддерживает две локализации: английскую (en) и русскую (ru), при этом язык интерфейса по умолчанию — английский. Локализация компонента может быть изменена через конфигурацию при инициализации веб-компоненты. Для этого укажите поля language и locales в конфигурации.
Поле language используется для определения языка интерфейса, принимает значение типа string. Если значение не указано или для указанного значения нет локалей, будет использовано значение "en".
Поле locales используется как объект для изменения стандартных текстов интерфейса. При определении пользовательских локалей имейте в виду, что компонент будет использовать только переданный объект, поэтому в нём необходимо указать все необходимые локали для всех требуемых языков. Для более точного понимания ознакомьтесь с примерами ниже.
Актуальный объект локализации для английского языка
const en = {
PreparingEnvironment: 'Preparing environment',
MessageCode: 'Message code: ',
SomeError: 'An error occurred, please try again later',
Stages: {
Initialization: {
SelectCamera: {
TextHints: {
CheckingWebcamOperation: 'Check the webcam for proper operation and image quality',
},
Preloader: {
RequestingAccessToCamera: 'Requesting access to the camera',
},
ContinueButton: 'Continue',
BackButton: 'Back',
},
Description: {
MotionControl: {
Heading: 'Checking Motion Control',
Text: 'To pass the inspection successfully, you need to perform several actions. First, you need to determine the initial position of the face. To do this, fix the face in a position that is convenient for you and so that the mask is displayed for a few seconds while the counter is filling up under the player. After determining the starting position, you need to perform a number of actions in the order generated by the system. Actions are commands: turn your head to the right/left, raise your head, approach/move away. The action is considered completed when the frame around the face changes its color.',
},
ContinueButton: 'Continue',
},
Errors: {
InvalidTokenError: 'The request was not executed because the token used is invalid',
InvalidMotionControlAttemptCountError:
'Configuration error. The motionControl.attemptsCount field must be greater than zero',
EnabledMotionControlWithoutFaceModelError:
'Configuration error. If faceModelSettings.modelEnabled is false, then motionControl.enabled must also be false',
TimeToStartRecordLessThenOneSecondError:
'Configuration error. The timeToStartRecord value must be at least 1000ms',
NoBaseUrlError: 'Base URL of server not specified in the component configuration',
PrepareEnvironmentForBiometricInspectionTimeoutError:
'The waiting time for the initialization of biometric verification services has been exceeded',
InitializationProcessingVideoStremWorkerError: 'Error initializing the video frame processing service',
InitializationFaceDetectionServiceError: 'Error initializing the face detection service',
NotSupportedMediaDevicesError: 'The browser does not support the Media Devices API',
AbortAccessToCameraError: 'The attempt to access the camera was aborted',
DocumentIsNotFullyActiveError: 'HTML document is not fully active',
NotAllowedAccessToCameraError: 'Not allowed access to camera',
TimeoutAccessToCameraError: 'The waiting time for permission to access the camera has been exceeded',
NotFoundCameraError: 'No camera was found',
NotReadableCameraError: 'The camera is unavailable because it is already in use by another process',
OverconstrainedCameraError: 'No camera satisfying the constraints of the system is found',
CameraSecurityError: 'The HTML document does not meet the minimum security requirements for camera use',
NoVideoTrackError: 'There is no data about the video stream from the camera',
NoCameraCapabilitiesInfoError:
'Information about possible camera settings does not contain the required parameters',
MediaStreamIsUndefinedError: 'There is no video stream data',
WebComponentError: 'An error occurred, please try again later',
ConnectionEstablishmentError: 'An error occurred when establishing the connection',
InactiveVideoTrackError: 'The video track of the camera is inactive',
EndedVideoTrackError: 'The video track of the camera is has been ended',
DisabledVideoTrackError: 'The video track of the camera is disabled',
NoWebGLSupportError: 'WebGL is unavailable in the current browser configuration',
FaceDetectorRunningError: 'The device does not meet the requirements necessary to start the detector',
NoFaceDetectorError: 'No face detector in the system',
NotSupportedDelegationModeError: 'Unsupported detector delegate mode',
NoTestFaceDetectorImageError: 'No test image was found to test the operability of the face detector',
UnsupportFaceDetectorError:
'The face detector cannot be started because the device does not support any of the possible operating modes',
NotSupportedWebglApiError: 'WebGL API is unavailable in the current browser configuration',
HardwareAccelerationUnavailableError:
'Hardware Acceleration is disabled or not supported by the browser',
WebSocketTimeoutConnectionError: 'The connection to the server was closed due to inactivity',
WaitResponseWorkerTimeoutError: 'The waiting time for a response from the worker has expired',
InvalidAuthenticationTokenError: 'Invalid authentication token format',
},
},
BiomertricalChecks: {
IdentifyFacePosition: {
TextHints: {
MoveFaceOnCenter:
'Please position yourself so that your face is in the center of the circle on the screen',
IDontSeeYou: 'You are not visible',
FaceOutsideFrame:
'Please position yourself so that your face is in the center of the on the screen',
LookAtCamera: 'Please, turn your face to the camera',
LittleFace: 'Move closer to the camera',
BigFace: 'Move further away from the camera',
DontMove: "Please don't move",
CheckPosition: 'Checking position',
TimerBeforeRun: 'Before recording starts',
},
},
MotionControl: {
TextHints: {
AttemptFailed: 'Motion Control attempt failed',
SendingDataToServer: 'Sending data to the server',
Command: {
TurnLeft: 'Turn left',
TurnRight: 'Turn right',
TurnUp: 'Lift your chin up while continuing to look at the screen',
LookAtCenter: 'Look into the camera',
Closer: 'Move closer to the camera',
Farther: 'Move further away from the camera',
Normal: 'Return to the original position',
},
},
},
Errors: {
InvalidTokenError: 'The request was not executed because the token used is invalid',
SlowEnternet: 'Your internet connection is slow. Image quality assessment may take long',
InCorrectCamera: 'The selected camera is not available or does not meet the minimum requirements',
NoCamera: 'No cameras available',
NoPermission:
'Permission to access the camera is not obtained. For further work, allow access to the camera in your browser settings',
MoreFaces: 'Many faces in the frame',
SafariError: 'Unfortunately, your browser is temporarily not supported at the moment',
ServerError: 'The server is temporarily unavailable',
ServerConfigError: 'Error on the server',
NotSupportedApiError: 'Your browser does not support the required function',
TransportError: 'An unexpected error occurred while running the check',
NotSupportedVideoFormatError: "This browser haven't supported needed video mime type",
VideoStreamResolutionIsUndefinedError: 'The resolution of the video stream is not defined',
InvalidVideoStreamResolutionValueError:
'The resolution of the video stream contains invalid values, the width or height of the video stream cannot be equal to 0',
InvalidVideoPreviewResolutionValueError:
'The resolution of the video preview contains invalid values, the width or height of the video preview cannot be equal to 0',
InvalidFrameDataForDetectionError: 'Incorrect frame data for face detection',
CaptureFaceBestshotTimeoutError: 'Frame collection waiting time exceeded',
InvalidMotionControlPatternError: 'Invalid Motion Control pattern',
NoSupportedVideoCodecError: 'The video codec supported by the system is not detected',
WaitResponseWorkerTimeoutError: 'The waiting time for a response from the worker has expired',
BrowserNotSupportedWorkerApi: "This browser doesn't support Worker API",
DeepfakeValidationError: 'Deepfake check failed',
CameraFpsNotDefinedError: 'The frame rate of the video stream is not defined',
TransmissionTimeoutError: 'The waiting time for a response from the server has been exceeded',
InvalidFacesAmountOnFrameError: 'No face or too many faces found',
InvalidMessageFormatError: 'Invalid message format',
UndefinedLocalizedMessagesError: 'There are no localized messages for the selected language',
InvalidVideoDataError: 'Invalid video data',
WebComponentError: 'An error occurred, please try again later',
NotSupportedVideoEncoderApiError: "The browser doesn't support Video Encoder API",
LivenessTransportConnectionTimeoutError:
'The connection to the server was closed due to an internal error or exceeding the waiting time',
InactiveVideoTrackError: 'The video track from the camera is inactive',
120004: 'FPS too low. Please try again',
120005: 'Error on the server. Please try again',
120006: 'Error on the server. Please try again',
120007: 'Error on the server. Please try again',
120008: 'Error on the server. Please try again',
120009: 'Please check the quality of your internet connection and try again',
120044: 'No reference frames found',
120052: 'Error on the server. Please try again',
120053: 'Error on the server. Please try again',
120054: 'Error on the server. Please try again',
120055: 'Error while sending a message via DataChannel',
120057: 'Error in obtaining Motion Control pattern',
120060: 'Error on the server. Please try again',
120061: 'No face or multiple faces detected while taking reference image. Please try again',
180001: 'Invalid websocket message format',
180003: 'Requesting a video recording of an unsupported type',
180004: 'There was an error on the server while recording video',
180005: 'Video processing time has exceeded the limit',
180006: 'Error in operation of WebSocket connection',
190003: 'The size of data sent to the server exceeds the allowed size',
NoWebGLSupportError: 'The device does not support WebGL technology',
FaceDetectorRunningError: 'The device does not meet the requirements necessary to start the detector',
NoFaceDetectorError: 'No face detector in the system',
WebSocketTimeoutConnectionError: 'The connection to the server was closed due to inactivity',
},
},
ValidateFlowResult: {
SendingDataToServer: 'Sending data to the server',
Success: {
Register: 'Registration completed successfully',
Authorize: 'Authorization completed successfully',
},
Errors: {
InvalidTokenError: 'The request was not executed because the token used is invalid',
AntispoofingValidationError: 'Liveness check failed',
RegistrationMatchingFailedError: 'An applicant with such biometrics already exists',
AuthorizationMatchingFailedError: 'No applicant with this biometric was found',
LowImageQualityError: 'Poor image quality',
NoFacesFound: 'No face found in the image',
FacesDontBelongApplicant: 'Face matching check failed',
MoreFaces: 'Many faces in the frame',
ServerError: 'The server is temporarily unavailable',
ServerConfigError: 'Error on the server',
"Face profile wasn't saved": "Face profile wasn't saved",
'Face profiles not found': 'Face profiles not found',
'Face authorization was failed': 'Face authorization was failed',
'Invalid endeavor info': 'Invalid endeavor info',
'Endeavor external link not equal to applicant': 'Applicant ID consistency error',
'Endeavor id is null when required': 'Endeavor id is null when required',
'No faces found on image': 'No faces found on image',
'Multiple faces found on image': 'Multiple faces found on image',
'Error on the server': 'Error on the server',
'Motion control video is not captured': 'Motion control video is not captured',
'Motion control video reference template is not captured':
'Motion control video reference template is not captured',
NotSupportedApiError: 'Your browser does not support the required function',
TransportError: 'An unexpected error occurred while running the check',
NotSupportedVideoFormatError: "This browser haven't supported needed video mime type",
VideoStreamResolutionIsUndefinedError: 'The resolution of the video stream is not defined',
InvalidVideoStreamResolutionValueError:
'The resolution of the video stream contains invalid values, the width or height of the video stream cannot be equal to 0',
InvalidVideoPreviewResolutionValueError:
'The resolution of the video preview contains invalid values, the width or height of the video preview cannot be equal to 0',
InvalidFrameDataForDetectionError: 'Incorrect frame data for face detection',
CaptureFaceBestshotTimeoutError: 'Frame collection waiting time exceeded',
InvalidMotionControlPatternError: 'Invalid Motion Control pattern',
NoSupportedVideoCodecError: 'The video codec supported by the system is not detected',
WaitResponseWorkerTimeoutError: 'The waiting time for a response from the worker has expired',
BrowserNotSupportedWorkerApi: "This browser doesn't support Worker API",
DeepfakeValidationError: 'Deepfake check failed',
CameraFpsNotDefinedError: 'The frame rate of the video stream is not defined',
TransmissionTimeoutError: 'The waiting time for a response from the server has been exceeded',
InvalidFacesAmountOnFrameError: 'No face or too many faces found',
InvalidMessageFormatError: 'Invalid message format',
UndefinedLocalizedMessagesError: 'There are no localized messages for the selected language',
ValidationTimeHasExpiredError: 'Validation time has expired',
ApplicantBlockedError: 'The applicant is blocked',
WebComponentError: 'An error occurred, please try again later',
InvalidEndeavorInfoError: 'The attempt contains invalid data',
LivenessTransportConnectionTimeoutError:
'The connection to the server was closed due to an internal error or exceeding the waiting time',
InvalidOriginBlobError: 'Cannot parse origin photo',
NoFaceOnOriginalPhotoError: 'The original photo does not contain a face',
TooManyFacesOnOriginalPhotoError: 'The original photo contain a more than one face',
NoFaceOnBestshotError: 'The bestshot does not contain a face',
TooManyFacesOnBestshotsError: 'The bestshot contains a more than one face',
120004: 'FPS too low. Please try again',
120005: 'Error on the server. Please try again',
120006: 'Error on the server. Please try again',
120007: 'Error on the server. Please try again',
120008: 'Error on the server. Please try again',
120009: 'Please check the quality of your internet connection and try again',
120029: 'Error on the server. Please try again',
120044: 'No reference frames found',
120052: 'Error on the server. Please try again',
120053: 'Error on the server. Please try again',
120054: 'Error on the server. Please try again',
120055: 'Error while sending a message via DataChannel',
120057: 'Error in obtaining Motion Control pattern',
120060: 'Error on the server. Please try again',
120061: 'No face or multiple faces detected while taking reference image. Please try again',
180001: 'Invalid websocket message format',
180003: 'Requesting a video recording of an unsupported type',
180004: 'There was an error on the server while recording video',
180005: 'Video processing time has exceeded the limit',
180006: 'Error in operation of WebSocket connection',
190003: 'The size of data sent to the server exceeds the allowed size',
1300001:
'Poor connection quality, the connection to the server does not meet the necessary requirements',
WebSocketTimeoutConnectionError: 'The connection to the server was closed due to inactivity',
},
},
},
};
Пример изменения английской локализации в TypeScript:
import tdvc, { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
// Копируем стандартные локали, чтобы при изменении определённых локалей остальные остались доступны в исходном виде
const locales = structuredClone(tdvc.DefaultLocales);
// Обновление нужных локалей
locales.en.PreparingEnvironment = 'The required resources are being loaded;
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
locales,
};
Пример добавления новой локализации в TypeScript:
Для добавления новой локализации подготовьте объект JavaScript, который будет содержать все те же поля, что и объект с английской локализацией, и определите текст на нужном языке для каждого идентификатора сообщения. Объект локализации, который можно использовать в качестве примера, находится в файле README.md в архиве поставки.
import tdvc, { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
// Копируем стандартные локали, чтобы при изменении определённых локалей остальные остались доступны в исходном виде
const locales = structuredClone(tdvc.DefaultLocales);
// Определение объекта с локалями для нужного языка, структура которого должна полностью соответствовать стандартным локалям.
const kkLocales = {
PreparingEnvironment: 'Ортаны дайындау',
MessageCode: 'Хабарлама коды: ',
SomeError: 'Қате орын алды, кейінірек қайта әрекет етіңіз',
// ...
};
// Добавляем новый объект в общий набор локалей, ключом которого является новый язык локализации.
locales['kk'] = kkLocales;
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
language: 'kk',
locales,
};
Взаимодействие веб-компоненты с внешней системой
Взаимодействие между веб-компонентой и внешними системами осуществляется с помощью функций обратного вызова (callbacks). Система определяет логику обработки событий на основе данных, предоставленных этими функциями, или на основе факта вызова callback. В конфигурации компонента определено несколько таких функций:
onMounted: (() => void)— функция, вызываемая, когда веб-компонента полностью инициализирована.onError: ((message: string, code: string) => void)— функция, вызываемая в случае возникновения ошибки при прохождении пользовательского пути.onMotion: ((type: 'left' | 'right' | 'up' | 'closer' | 'farther' | 'return', result: boolean | undefined) => void)— функция, вызываемая во время биометрической проверки "Motion Control". Если значение result равно undefined, проверка только началась; если true — успешно пройдена; если false — не пройдена.onGetReferenceImages: (referenceImage: string) => void; — функция, вызываемая после получения ключевого кадра. referenceImage — изображение в формате строки base64.onStartValidation: (() => void)— функция, вызываемая перед началом проверки результатов.onValidate: ((data: LiteValidationResult) => void)— функция, вызываемая после получения результата проверки данных от сервера.
Пример использования колбэков в TypeScript:
import { LiteComponentSettingsFromClient, LiteValidationResult } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
callbacks: {
onMounted: () => {
console.log('Component is successfully initilized');
},
onError: (message: string, code: string) => {
console.log('On error callback', message, code);
},
onMotion: (
type: 'left' | 'right' | 'up' | 'closer' | 'farther' | 'return',
currentAttemptNumber: number,
result?: boolean
) => {
console.log('On motion callback', type, currentAttemptNumber, result);
},
onGetReferenceImages: (referenceImage: string) => {
console.log('Reference image received');
console.log(referenceImage);
},
onStartValidation: () => {
console.log('On start validation callback');
},
onValidate: async (data: LiteValidationResult) => {
console.log('On validation callback', data);
await lib.destroy();
},
},
}
Стилизация интерфейса
Основной способ стилизации
Стилизация веб-компоненты осуществляется с помощью CSS. Элементы интерфейса содержат идентификаторы и CSS-классы, с помощью которых можно настроить их внешний вид. Идентификаторы и классы CSS, используемые для настройки, можно найти в файле @tdvc/face-onboarding/dist/css/style.css.
Стилизация через JavaScript/TypeScript
Для настройки сложных элементов пользовательского интерфейса, таких как маски лица на основе ключевых точек, подсказки действий Motion Control и границы лица, которые могут иметь различную форму, стили и логику отображения, одного CSS недостаточно. Поэтому для более гибкой стилизации предусмотрена возможность переопределения реализации этих элементов.
Все нижеперечисленные элементы используют базовый класс в качестве основы для дальнейшей реализации.
Базовый класс canvas
export type Options = Partial<{
strokeStyle: string;
fillStyle: string;
lineWidth: number;
}>;
export const DEFAULT_CANVAS_SETTINGS = {
strokeStyle: '#000000',
fillStyle: '#000000',
lineWidth: 1,
};
export default abstract class Canvas {
protected _root: HTMLCanvasElement;
protected _context: CanvasRenderingContext2D;
protected _options: Options;
protected _initialOptions: Options;
constructor(id: string, options?: Options) {
this._root = document.createElement('canvas');
this._root.classList.add('tdvc-canvas');
this._root.classList.add(id);
const context = this.root.getContext('2d');
if (!context) {
const elementClasses = this._root.classList
.keys()
.reduce((prev, cur) => (prev === '' ? prev + cur : prev + ' ' + cur), '');
throw new WebComponentError({ message: `2D context for ${elementClasses} is null` });
}
this._context = context;
this._initialOptions = options ?? DEFAULT_CANVAS_SETTINGS;
this.setContextOption({ ...this._initialOptions });
this.applyContextOptions();
}
get root() {
return this._root as Readonly<HTMLCanvasElement>;
}
get options() {
return this._options;
}
get initialOptions() {
return this._initialOptions;
}
setContextOption(options: Options) {
this._options = options;
}
applyContextOptions() {
if (this._options.strokeStyle) this._context.strokeStyle = this._options.strokeStyle;
if (this._options.lineWidth) this._context.lineWidth = this._options.lineWidth;
if (this._options.fillStyle) this._context.fillStyle = this._options.fillStyle;
}
setResolution(width: number, height: number) {
this._root.width = width;
this._root.height = height;
this.applyContextOptions();
}
clear() {
const { width, height } = this._context.canvas;
this._context.clearRect(0, 0, width, height);
}
removeFromDom() {
this._root.remove();
}
destroy() {
if (this._root && this._root.parentNode) this._root.remove();
this._context = null!;
this._root = null!;
}
}
В своих реализациях вы можете использовать как базовый класс, так и его производные.
Маска лица по ключевым точкам
Базовая реализация
export type FaceKeypointsMaskOptions = Options;
export const DEFAULT_FACE_KEYPOINTS_MASK_OPTIONS: FaceKeypointsMaskOptions = {
strokeStyle: '#32EEDB',
fillStyle: '#32EEDB',
lineWidth: 0.5,
};
export default class FaceKeypointsMask extends Canvas {
protected _isRendering = false;
constructor(options?: FaceKeypointsMaskOptions) {
super('tdvc-face-keypoints-mask', options ?? DEFAULT_FACE_KEYPOINTS_MASK_OPTIONS);
}
get isRendering() {
return this._isRendering;
}
draw(points: Point[]) {
if (this._isRendering || points.length !== 478) return;
this._isRendering = true;
this._context.beginPath();
for (let i = 0; i < TRIANGULATION.length; i += 3) {
const a = points[TRIANGULATION[i]];
const b = points[TRIANGULATION[i + 1]];
const c = points[TRIANGULATION[i + 2]];
this._context.moveTo(a.x, a.y);
this._context.lineTo(b.x, b.y);
this._context.lineTo(c.x, c.y);
}
this._context.stroke();
this._isRendering = false;
}
}
Пример пользовательской реализации
import tdvc, { LiteComponentSettingsFromClient, Point } from '@tdvc/face-onboarding';
// Скрытие маски, чтобы не тратить ресурсы на отображение
class NoMask extends tdvc.UiKit.FaceKeypointsMask {
draw(points: Point[]): void {}
}
// Отображение только точек вместо треугольников
class OnlyPointsFaceKeypointMask extends tdvc.UiKit.FaceKeypointsMask {
constructor() {
super({
...tdvc.UiKit.DEFAULT_FACE_KEYPOINTS_MASK_OPTIONS,
// Изменение цвета
fillStyle: 'red',
});
}
draw(points: Point[]): void {
if (this._isRendering || points.length !== 478) return;
this._isRendering = true;
for (const point of points) {
this._context.beginPath();
this._context.arc(point.x, point.y, 1, 0, 2 * Math.PI);
this._context.fill();
}
this._isRendering = false;
}
}
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
uiKit: {
FaceKeypointsMask: OnlyPointsFaceKeypointMask,
},
};
Граница лица
Базовые реализации
export type FaceBorderOptions = Options;
export const DEFAULT_FACE_BORDER_OPTIONS: FaceBorderOptions = {
strokeStyle: '#ffffff',
fillStyle: 'rgba(255, 255, 255, 0.5)',
lineWidth: 4,
};
export default abstract class FaceBorder extends Canvas {
constructor(options?: FaceBorderOptions) {
super('tdvc-face-position-circle', options ?? DEFAULT_FACE_BORDER_OPTIONS);
}
public draw(point: Point, resolution: Resolution) {
this._drawOverlay();
this._clearFaceArea(point, resolution);
this._drawBorder(point, resolution);
}
protected _drawOverlay() {
this._context.globalCompositeOperation = 'overlay';
this._context.fillRect(0, 0, this._context.canvas.width, this._context.canvas.height);
}
protected _clearFaceArea(point: Point, resolution: Resolution) {
this._context.globalCompositeOperation = 'destination-out';
this._context.fillStyle = 'rgba(0,0,0,1.0)';
this._baseFigure(point, resolution, (this._options?.lineWidth ?? 4) / 2);
this._context.fill();
}
protected _drawBorder(point: Point, resolution: Resolution) {
this._context.beginPath();
this._context.globalCompositeOperation = 'overlay';
this._baseFigure(point, resolution, 0);
this._context.stroke();
}
protected abstract _baseFigure(point: Point, resolution: Resolution, borderWidth: number): void;
}
export class EllipseFaceBorder extends FaceBorder {
constructor(options?: FaceBorderOptions) {
super(options ?? DEFAULT_FACE_BORDER_OPTIONS);
}
protected _baseFigure(point: Point, resolution: Resolution, borderWidth: number): void {
const { rx, ry } = this._calculateEllipseRadiuses(resolution);
this._context.ellipse(point.x, point.y, rx + borderWidth, ry + borderWidth, 0, 0, 2 * Math.PI);
}
protected _calculateEllipseRadiuses(resolution: Resolution) {
return {
rx: resolution.width / 2,
ry: resolution.height / 2,
};
}
}
Пример пользовательской реализации
import tdvc, {
LiteComponentSettingsFromClient,
Point,
Resolution,
} from '@tdvc/face-onboarding';
// Изменение стилей для эллиптической границы лица
class CustomEllipseFaceBorder extends tdvc.UiKit.EllipseFaceBorder {
constructor() {
super({
...tdvc.UiKit.DEFAULT_FACE_BORDER_OPTIONS,
fillStyle: 'rgba(0,0,0,1.0)',
lineWidth: 1,
strokeStyle: 'red',
});
}
}
// Реализация границы лица в виде прямоугольника со скругленными углами
class RoundedSquareFaceBorder extends tdvc.UiKit.FaceBorder {
constructor() {
super({
...tdvc.UiKit.DEFAULT_FACE_BORDER_OPTIONS,
fillStyle: 'rgba(0,0,0,1.0)',
});
}
protected _baseFigure(point: Point, resolution: Resolution, borderWidth = 0) {
const offset = Math.floor((resolution.width / 100) * 16);
const { topLeftCorner, bottomLeftCorner, bottomRightCorner, topRightCorner } =
this._calculateRectCornerCoordinates(point, resolution, borderWidth);
this._context.moveTo(topLeftCorner.x, topLeftCorner.y + offset);
this._context.quadraticCurveTo(topLeftCorner.x, topLeftCorner.y, topLeftCorner.x + offset, topLeftCorner.y);
this._context.lineTo(topRightCorner.x - offset, topRightCorner.y);
this._context.quadraticCurveTo(topRightCorner.x, topRightCorner.y, topRightCorner.x, topRightCorner.y + offset);
this._context.lineTo(bottomRightCorner.x, bottomRightCorner.y - offset);
this._context.quadraticCurveTo(
bottomRightCorner.x,
bottomRightCorner.y,
bottomRightCorner.x - offset,
bottomRightCorner.y
);
this._context.lineTo(bottomLeftCorner.x + offset, bottomRightCorner.y);
this._context.quadraticCurveTo(
bottomLeftCorner.x,
bottomLeftCorner.y,
bottomLeftCorner.x,
bottomLeftCorner.y - offset
);
this._context.closePath();
}
protected _calculateRectCornerCoordinates(point: Point, resolution: Resolution, borderWidth = 0) {
const topLeftCorner: Point = {
x: point.x - resolution.width / 2 - borderWidth,
y: point.y - resolution.height / 2 - borderWidth,
};
const topRightCorner: Point = {
x: point.x + resolution.width / 2 + borderWidth,
y: point.y - resolution.height / 2 - borderWidth,
};
const bottomRightCorner: Point = {
x: point.x + resolution.width / 2 + borderWidth,
y: point.y + resolution.height / 2 + borderWidth,
};
const bottomLeftCorner: Point = {
x: point.x - resolution.width / 2 - borderWidth,
y: point.y + resolution.height / 2 + borderWidth,
};
return {
topLeftCorner,
topRightCorner,
bottomRightCorner,
bottomLeftCorner,
};
}
}
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
uiKit: {
FaceBorder: RoundedSquareFaceBorder,
},
};
Подсказки направления Motion Control
Базовые реализации
export const DEFAULT_MOTION_CONTROL_DIRECTION_HINTS_OPTIONS = {
lineWidth: 2,
fillStyle: 'rgba(0, 0, 0, 0.5)',
strokeStyle: 'rgba(169, 169, 169, 1)',
};
export default abstract class MotionControlDirectionHints extends Canvas {
constructor(options?: Options) {
super('tdv-motion-control-direction-hints', options ?? DEFAULT_MOTION_CONTROL_DIRECTION_HINTS_OPTIONS);
}
abstract draw(bbox: TBoundingBox, command: MotionControlPattern | 'return', progress: number): void;
}
export class ArrowsMotionControlDirectionHints extends MotionControlDirectionHints {
protected _leftArrow: Path2D = new Path2D();
protected _rightArrow: Path2D = new Path2D();
protected _upArrow: Path2D = new Path2D();
protected _downArrow: Path2D = new Path2D();
protected _baseMargin = 4;
protected _gap = -4;
protected _arrowResolution: Resolution = {
width: 16,
height: 21,
};
protected _halfArrowResolution: Resolution = {
width: this._arrowResolution.width / 2,
height: this._arrowResolution.height / 2,
};
protected _successArrowFillColor = '#17ea4c';
protected _disabledArrowStrokeColor = 'rgba(255,255,255, 1)';
protected _disabledArrowFillColor = `rgba(255, 255, 255, 0.5)`;
constructor(options?: Options) {
super(options);
this._initLeftArrowPath();
this._initRightArrowPath();
this._initUpArrowPath();
this._initDownArrowPath();
}
draw(bbox: TBoundingBox, command: MotionControlPattern | 'return', progress = 0) {
switch (command) {
case 'left':
this._drawHintForLeftAction(bbox, progress);
break;
case 'right':
this._drawHintForRightAction(bbox, progress);
break;
case 'up':
this._drawHintForUpAction(bbox, progress);
break;
case 'closer':
this._drawHintForCloserAction(bbox, progress);
break;
case 'farther':
this._drawHintForFartherAction(bbox, progress);
break;
default:
break;
}
}
protected _drawHintForLeftAction(bbox: TBoundingBox, progress = 0) {
let basePoint;
for (let i = 0; i < 4; i++) {
basePoint = this._getPointForRightPosition(bbox, i);
this._renderArrow(this._rightArrow, basePoint, progress, i);
basePoint = this._getPointForLeftPosition(bbox, i);
this._renderArrow(this._leftArrow, basePoint, 0, i, true);
basePoint = this._getPointForUpPosition(bbox, i);
this._renderArrow(this._upArrow, basePoint, 0, i, true);
basePoint = this._getPointForDownPosition(bbox, i);
this._renderArrow(this._downArrow, basePoint, 0, i, true);
}
}
protected _drawHintForRightAction(bbox: TBoundingBox, progress = 0) {
let basePoint;
for (let i = 0; i < 4; i++) {
basePoint = this._getPointForRightPosition(bbox, i);
this._renderArrow(this._rightArrow, basePoint, 0, i, true);
basePoint = this._getPointForLeftPosition(bbox, i);
this._renderArrow(this._leftArrow, basePoint, progress, i);
basePoint = this._getPointForUpPosition(bbox, i);
this._renderArrow(this._upArrow, basePoint, 0, i, true);
basePoint = this._getPointForDownPosition(bbox, i);
this._renderArrow(this._downArrow, basePoint, 0, i, true);
}
}
protected _drawHintForUpAction(bbox: TBoundingBox, progress = 0) {
let basePoint;
for (let i = 0; i < 4; i++) {
basePoint = this._getPointForRightPosition(bbox, i);
this._renderArrow(this._rightArrow, basePoint, 0, i, true);
basePoint = this._getPointForLeftPosition(bbox, i);
this._renderArrow(this._leftArrow, basePoint, 0, i, true);
basePoint = this._getPointForUpPosition(bbox, i);
this._renderArrow(this._upArrow, basePoint, progress, i);
basePoint = this._getPointForDownPosition(bbox, i);
this._renderArrow(this._downArrow, basePoint, 0, i, true);
}
}
protected _drawHintForCloserAction(bbox: TBoundingBox, progress = 0) {
let basePoint;
for (let i = 0; i < 4; i++) {
basePoint = this._getPointForRightPosition(bbox, i);
this._renderArrow(this._leftArrow, basePoint, progress, i);
basePoint = this._getPointForLeftPosition(bbox, i);
this._renderArrow(this._rightArrow, basePoint, progress, i);
basePoint = this._getPointForUpPosition(bbox, i);
this._renderArrow(this._downArrow, basePoint, progress, i);
basePoint = this._getPointForDownPosition(bbox, i);
this._renderArrow(this._upArrow, basePoint, progress, i);
}
}
protected _drawHintForFartherAction(bbox: TBoundingBox, progress = 0) {
let basePoint;
for (let i = 0; i < 4; i++) {
basePoint = this._getPointForRightPosition(bbox, i);
this._renderArrow(this._rightArrow, basePoint, progress, i);
basePoint = this._getPointForLeftPosition(bbox, i);
this._renderArrow(this._leftArrow, basePoint, progress, i);
basePoint = this._getPointForUpPosition(bbox, i);
this._renderArrow(this._upArrow, basePoint, progress, i);
basePoint = this._getPointForDownPosition(bbox, i);
this._renderArrow(this._downArrow, basePoint, progress, i);
}
}
protected _getPointForRightPosition(bbox: TBoundingBox, index: number) {
const offset = this._baseMargin + index * (this._gap + this._arrowResolution.width);
return {
x: bbox.xMax + offset,
y: bbox.yMin + bbox.height / 2 - this._halfArrowResolution.height,
};
}
protected _getPointForLeftPosition(bbox: TBoundingBox, index: number) {
const offset = this._baseMargin + index * (this._gap + this._arrowResolution.width);
return {
x: bbox.xMin - offset - this._arrowResolution.width,
y: bbox.yMin + bbox.height / 2 - this._halfArrowResolution.height,
};
}
protected _getPointForUpPosition(bbox: TBoundingBox, index: number) {
const offset = this._baseMargin + index * (this._gap + this._arrowResolution.width);
return {
x: bbox.xMin + bbox.width / 2 - this._halfArrowResolution.height,
y: bbox.yMin - offset - this._arrowResolution.width,
};
}
protected _getPointForDownPosition(bbox: TBoundingBox, index: number) {
const offset = this._baseMargin + index * (this._gap + this._arrowResolution.width);
return {
x: bbox.xMin + bbox.width / 2 - this._halfArrowResolution.height,
y: bbox.yMax + offset,
};
}
protected _renderArrow(arrow: Path2D, basePoint: Point, progress: number, arrowIndex: number, isDisabled = false) {
this._context.save();
this._setFillColor(progress, arrowIndex, isDisabled);
this._context.translate(basePoint.x, basePoint.y);
this._context.fill(arrow);
this._context.stroke(arrow);
this._context.restore();
}
protected _initLeftArrowPath() {
this._leftArrow.moveTo(this._arrowResolution.width, 0);
this._leftArrow.lineTo(this._halfArrowResolution.width, 0);
this._leftArrow.lineTo(0, this._halfArrowResolution.height);
this._leftArrow.lineTo(this._halfArrowResolution.width, this._arrowResolution.height);
this._leftArrow.lineTo(this._arrowResolution.width, this._arrowResolution.height);
this._leftArrow.lineTo(this._halfArrowResolution.width, this._halfArrowResolution.height);
this._leftArrow.lineTo(this._arrowResolution.width, 0);
}
protected _initRightArrowPath() {
this._rightArrow.moveTo(0, 0);
this._rightArrow.lineTo(this._halfArrowResolution.width, 0);
this._rightArrow.lineTo(this._arrowResolution.width, this._halfArrowResolution.height);
this._rightArrow.lineTo(this._halfArrowResolution.width, this._arrowResolution.height);
this._rightArrow.lineTo(0, this._arrowResolution.height);
this._rightArrow.lineTo(this._halfArrowResolution.width, this._halfArrowResolution.height);
this._rightArrow.lineTo(0, 0);
}
protected _initUpArrowPath() {
this._upArrow.moveTo(0, this._arrowResolution.width);
this._upArrow.lineTo(0, this._halfArrowResolution.width);
this._upArrow.lineTo(this._halfArrowResolution.height, 0);
this._upArrow.lineTo(this._arrowResolution.height, this._halfArrowResolution.width);
this._upArrow.lineTo(this._arrowResolution.height, this._arrowResolution.width);
this._upArrow.lineTo(this._halfArrowResolution.height, this._halfArrowResolution.width);
this._upArrow.lineTo(0, this._arrowResolution.width);
}
protected _initDownArrowPath() {
this._downArrow.moveTo(0, 0);
this._downArrow.lineTo(0, this._halfArrowResolution.width);
this._downArrow.lineTo(this._halfArrowResolution.height, this._arrowResolution.width);
this._downArrow.lineTo(this._arrowResolution.height, this._halfArrowResolution.width);
this._downArrow.lineTo(this._arrowResolution.height, 0);
this._downArrow.lineTo(this._halfArrowResolution.height, this._halfArrowResolution.width);
this._downArrow.lineTo(0, 0);
}
protected _setFillColor(progress: number, currentIndex: number, isDisabled: boolean) {
const options = { ...this._initialOptions };
if (!isDisabled && Math.floor(progress / 25) >= currentIndex + 1) {
options.fillStyle = this._successArrowFillColor;
}
if (isDisabled) {
options.fillStyle = this._disabledArrowFillColor;
options.strokeStyle = this._disabledArrowStrokeColor;
}
this.setContextOption(options);
this.applyContextOptions();
}
destroy(): void {
this._leftArrow = undefined!;
this._rightArrow = undefined!;
this._upArrow = undefined!;
this._downArrow = undefined!;
super.destroy();
}
}
Пример пользовательской реализации
import tdvc, {BoundingBox, LiteComponentSettingsFromClient, MotionControlPattern } from '@tdvc/face-onboarding';
class MotionControlDirectionHintsViaFilledFrame extends tdvc.UiKit.MotionControlDirectionHints {
draw(bbox: BoundingBox, command: MotionControlPattern | 'return', progress = 0) {
this._context.save();
this._setStyleByProgress(progress);
this._draw(bbox);
this._context.restore();
}
private _draw(bbox: BoundingBox) {
const resolution = {
width: bbox.xMax - bbox.xMin + this._context.lineWidth / 2,
height: bbox.yMax - bbox.yMin + this._context.lineWidth / 2,
};
const offset = Math.floor((resolution.width / 100) * 16);
this._context.beginPath();
this._context.moveTo(bbox.xMin, bbox.yMin + offset);
this._context.quadraticCurveTo(bbox.xMin, bbox.yMin, bbox.xMin + offset, bbox.yMin);
this._context.lineTo(bbox.xMax - offset, bbox.yMin);
this._context.quadraticCurveTo(bbox.xMax, bbox.yMin, bbox.xMax, bbox.yMin + offset);
this._context.lineTo(bbox.xMax, bbox.yMax - offset);
this._context.quadraticCurveTo(bbox.xMax, bbox.yMax, bbox.xMax - offset, bbox.yMax);
this._context.lineTo(bbox.xMin + offset, bbox.yMax);
this._context.quadraticCurveTo(bbox.xMin, bbox.yMax, bbox.xMin, bbox.yMax - offset);
this._context.closePath();
this._context.closePath();
this._context.stroke();
}
private _setStyleByProgress(progress = 0) {
this._context.lineWidth = 4;
this._context.strokeStyle = this._getStrokeColor(progress);
}
private _getStrokeColor(progress: number) {
let hue, saturation, lightness;
hue = progress;
saturation = 83;
lightness = 50;
return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
}
destroy(): void {
super.destroy();
}
}
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
uiKit: {
MotionControlDirectionHints: MotionControlDirectionHintsViaFilledFrame,
},
};
Экран ошибки
Базовые реализации
export default class ErrorScreenLayout {
public readonly root: HTMLDivElement;
public readonly errorMessage: HTMLParagraphElement;
protected id = 'tdvc-error';
constructor() {
this.root = this._createRootElement();
this.errorMessage = this._createErrorMessage();
this.root.append(this.errorMessage);
}
protected _createRootElement() {
const element = document.createElement('div');
element.id = this.id;
element.classList.add(this.id);
return element;
}
protected _createErrorMessage() {
const element = document.createElement('p');
const id = `${this.id}__error-message`;
element.classList.add(id);
return element;
}
public setErrorMessage(text?: string) {
if (text === this.errorMessage.textContent) return;
this.errorMessage.textContent = text ?? '';
}
destroy() {
this.errorMessage.remove();
this.root.remove();
}
}
Пример пользовательской реализации
import tdvc, {BoundingBox, LiteComponentSettingsFromClient, MotionControlPattern } from '@tdvc/face-onboarding';
export class CustomErrorScreenLayout extends tdvc.UiKit.ErrorScreenLayout {
private _codeMessage: HTMLParagraphElement;
private _image: HTMLImageElement;
constructor() {
super();
this._createImage();
this._createCodeMessage();
}
private _createCodeMessage() {
this._codeMessage = document.createElement('p');
this._codeMessage.classList.add(`${this.id}__error-code`);
this.root.append(this._codeMessage);
}
private _createImage() {
this._image = document.createElement('img');
this._image.classList.add(`${this.id}__error-image`);
this._image.src = '/images/warning.png';
this.root.append(this._image);
}
setErrorMessage(text?: string): void {
if (!text) return;
const [message, code] = text?.split('. ');
this.errorMessage.textContent = message;
this._codeMessage.textContent = code;
}
}
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
uiKit: {
ErrorScreen: CustomErrorScreenLayout,
},
};
Логирование
Поле loggingSettings используется для определения настроек логирования. Содержит настройки enabled, level, output.
Поле
enabledиспользуется для включения или отключения логирования. По умолчанию true.Поле
levelиспользуется для определения минимального уровня логирования. Компонент будет логировать все сообщения установленного уровня и выше. Уровень определяется в следующем порядке: 'debug', 'warning', 'info', 'error', critical'. По умолчанию "debug".Поле
outputиспользуется для определения места вывода логов. Допустимые значения: "browser", 'server_via_websocket'. Можно указать несколько мест вывода. По умолчанию ['server_via_websocket'].Поле
correlationIdиспользуется для определения идентификатора, который можно использовать для явной идентификации запросов и ответов в рамках одного сеанса. По умолчанию undefined.Поле
fallbackIntervalиспользуется для установки периода отправки логов через HTTP/HTTPS, если отправка логов через веб-сокет включена, но по какой-то причине соединение недоступно в момент отправки логов. По умолчанию 3_000. Если значение установлено в 0, логи будут отправлены один раз в конце попытки или при возникновении ошибки.
Пример конфигурации с настройками логирования
import tdvc, { LiteComponentSettingsFromClient } from '@tdvc/face-onboarding';
const config: LiteComponentSettingsFromClient = {
mountElement: 'app',
baseUrl: '/',
authenticationToken:
'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJBdXRoZW50aWZpY2F0aW9uU2VydmljZSIsImV4cCI6MTc4NTczNjgwMywibmJmIjoxNzg1NzM2',
externalLink: '1234',
loggingSettings: {
enabled: true,
level: tdvc.LogLevel.DEBUG,
output: [tdvc.LoggingOutput.BROWSER],
correlationId: '133a96cc-5ed1-4c92-1111-832dff3806eb',
fallbackInterval: 3_000,
},
};
Рекомендации к устройству
Веб-компонента выполняет множество ресурсоемких операций, таких как обработка видеопотока с камеры, поиск лиц и анализ положения лица на кадре, визуализация маски и многое другое. Сочетание этих операций накладывает ограничения на технические характеристики устройства.
Для корректной работы устройство должно обладать следующими характеристиками:
- Наличие хотя бы одной рабочей и доступной веб-камеры с минимальным разрешением 1280x720 и минимальным FPS 25
- Уровень процессора MediaTek Dimensity 700 или выше
- Для смартфона требуется IOS 16/Android 10 и выше
Примеры устройств, которые мы используем для тестирования:
- POCO M4 5G
- Samsung Galaxy S9
- Samsung Galaxy A55
- Samsung Galaxy Tab S9
- iPhone 11 Pro
- Iphone 15 Plus
- Lenovo LOQ 15IRH8
- Macbook Air 13 (m3, 16гб)
- Macbook Pro 14" (m4, 16гб)
Поддержка браузеров
- Google Chrome
- Mozila Firefox
- Yandex Browser
- Safari
- Mi Browser
- Samsung Browser
Таблица совместимости версий
| Server BAF | @tdvc/face-onboarding |
| 1.18.* | 1.18.* |
| 1.15.*-1.18.* | 1.17.* |
| 1.15.*-1.16.* | 1.16.* |
| 1.15.* | 1.15.* |
| 1.14.* | 1.14.* |
| 1.13.* | 1.13.* |
| 1.12.* | 1.12.* |
| 1.10.* | 1.10.*-1.11.* |
| 1.9.* | 1.9.* |
| 1.8.* | 1.8.* |
| 1.7.0 | 1.7.0 |
| 1.5.0-1.7.0 | 1.6.0 |
| 1.5.0 | 1.5.0 |
| 1.3.0-1.4.0 | 1.4.0-1.4.1 |
| 1.3.0-1.3.1 | 1.3.1 |
| 1.3.0-1.3.1 | 1.3.1 |
| 1.2.0 | 1.2.0-1.3.0 |
| 1.1.0 | 1.0.0-1.1.2 |
| 1.0.0 | 1.0.0 |