DOT Web Document Auto Capture
v4.0.1
Introduction
DOT Web Document Auto Capture is set of Non-ui component and Ui component web components to capture image of an ID document.
Non-ui component is a web component that renders the video stream from an available phone or web camera to automatically capture an image of an ID document with the required quality.
Ui component is a web component that renders an overlay over video stream. Overlay includes a placeholder, camera control buttons and instructions to guide the user to position the document correctly.
Supported Browsers
DOT Web Document Auto Capture was tested with:
Chrome on desktop (Windows, Mac and Linux) and mobile (Android, iPhone)
Firefox on desktop (Windows, Mac and Linux) and mobile (Android)
Edge on Windows
Safari on Mac, iPad and iPhone
WebView on Android*
SafariVC on iPad and iPhone**
Known issues:
Components don’t work with WKWebView on iPhone
* Some older Android phones can experience issues with camera stream initialization using WebRTC. Our web components will work on most of them, but camera stream could be slow and laggy. This issue is caused by device and can be experienced in any website using WebRTC in Android WebView.
** Components are tested with SafariVC on devices iPhone 7 and newer with iOS 15 or iPadOS 15 or newer. Older devices or iOS versions are not officially supported and might experience issues.
Privacy and security
This component can only be used in secure contexts due to MediaDevices
API used for handling camera access. A secure context is, in short, a page loaded using HTTPS or the file:///
URL scheme, or a page loaded from localhost
. Before accessing any camera, the component must always get the user’s permission. Browsers may offer a once-per-domain permission feature, but they must ask at least the first time, and the user has to specifically grant ongoing permission if they choose to do so. Browsers are required to display an indicator that shows that a camera or microphone is in use. More details can be found on MDN docs.
Non-ui component
Requirements
Minimum required camera resolution for appropriate results is 720p. Anything less than 720p is insufficient.
Initialization
DOT Web Document Auto Capture can be installed via NPM, yarn or pnpm
npm install @innovatrics/dot-document-auto-capture
To manually integrate the DOT Web Document Auto Capture, download latest version from the Github repository. Add following line to dependencies in your package.json:
"dependencies": {
"@innovatrics/dot-document-auto-capture": "file:dot-document-auto-capture-[VERSION].tgz",
}
where [VERSION]
is the DOT Web Document Auto Capture version integrated. This installs dot-document-auto-capture
as an external module that can be use then (just like any other module in the code) For example, one could do import '@innovatrics/dot-document-auto-capture';
in the app.
Usage
Document auto capture component is a web component which uses custom HTML <x-dot-document-auto-capture/>
tag.
Properties cameraOptions
needs to be passed into component after <x-dot-document-auto-capture/>
tag was rendered.
import type {
DocumentCameraProps,
HTMLDocumentCaptureElement,
DocumentComponentData
} from '@innovatrics/dot-document-auto-capture';
import { useCallback, useEffect } from 'react';
import '@innovatrics/dot-document-auto-capture';
const DocumentCamera = (props: DocumentCameraProps) => {
useEffect(() => {
const documentAutoCaptureHTMLElement = document.getElementById(
'x-dot-document-auto-capture'
) as HTMLDocumentCaptureElement | null;
if (documentAutoCaptureHTMLElement) {
documentAutoCaptureHTMLElement.cameraOptions = props;
}
})
return <x-dot-document-auto-capture id="x-dot-document-auto-capture" />;
};
const Page = () => {
const handleDocumentPhotoTaken = (image: Blob, data: DocumentComponentData) => {
// ...
};
// Save function reference to prevent unnecessary reload of component
const handleError = useCallback(
(error: Error) => {
alert(error)
},
[],
);
return (
<DocumentCamera
imageType="png"
cameraFacing="environment"
onPhotoTaken={handleDocumentPhotoTaken}
onError={handleError}
/>
);
};
TypeScript
Declaration file is bundled inside package. To use with TypeScript, import types from @innovatrics/dot-document-auto-capture
.
import type { DocumentCallback, DocumentCameraProps } from '@innovatrics/dot-document-auto-capture';
Hosting SAM wasm
The component needs to have access to the WebAssembly wasm binary file. It’s distributed in the package and needs to be hosted by the website provider.
By default, the component will try to fetch the wasm file from <PROJECT_ORIGIN>/sam.wasm
. This can by changed using samWasmUrl
property.
If using Create React App
, copy sam.wasm
file to public
folder. In our example, the final path is public/sam.wasm
.
Properties
(Optional)
['png']
string imageType
– Format of the image returned after successful capture'jpeg'
'png'
(Optional)
string cameraFacing
– Defines which camera to acquire from browser’s getUserMedia API. Default camera facing for mobile phones is set toenvironment
and for others platforms is set touser
'user'
– The video source is facing toward the user; this is the selfie or front-facing camera on a smartphone'environment'
– The video source is facing away from the user, thereby viewing their environment; this is the back camera on a smartphone
function onPhotoTaken
– Callback on successful image capture(image, data) ⇒ void
- (see Callback parameters)
function onError
– Callback for the case that an error occurred (see Handling errors)(e: Error) ⇒ void
(Optional)
string samWasmUrl
- URL link to the location where the wasm binary file is hosted(Optional)
['standard']
string validationMode
– Sets the validation mode for document placement'standard'
– Document can be placed anywhere, but cannot leak out of photo'strict'
– Document must be placed inside placeholder
(Optional)
object thresholds
- Detection configuration(Optional)
[0.8]
number confidenceThreshold
- Detection confidence threshold(Optional)
[250]
number brightnessLowThreshold
- Low brightness threshold(Optional)
[900]
number brightnessHighThreshold
- High brightness threshold(optional)
[0.03]
number outOfBoundsThreshold
- Document out of bounds threshold(Optional)
[500]
number sharpnessThreshold
- Low sharpness threshold(Optional)
[100]
number hotspotsScoreThreshold
- Hotspots score threshold(Optional)
[0.43]
number sizeSmallThreshold
- Small size threshold
Callback parameters
Blob image
– Returned image on successful captureobject data
object cameraSettings
- MediaTrackSettings object containing used webcam settings. The object in addition contains device name.(Optional) object detection
- Object contains all detection parameters and its values. Present if image was taken using auto capture (not manual capture).object imageResolution
- Width and height of the captured image.
Multi capture
Document auto capture component allows you to capture an unlimited number of documents without the need to reinitialize the webcam and detector. This allows you to capture two sides of a document or multiple documents.
Component calls onPhotoTaken
callback on every captured document photo. When onPhotoTaken
is called, detection is paused. Camera stream and document detector stay initialized.
Component is in waiting state. You should implement a custom UI for waiting state (e.g. overlay over our component). We provide a default UI, but it is not customizable.
To continue detection, dispatch continue-detection
event.
Implement dispatch 'continue-detection' event
import { dispatchControlEvent, DocumentCustomEvent, ControlEventInstruction } from '@innovatrics/dot-document-auto-capture/events';
const continueDetection = () => {
dispatchControlEvent(DocumentCustomEvent.CONTROL, ControlEventInstruction.CONTINUE_DETECTION)
};
Without importing @innovatrics/dot-document-auto-capture/events
.
function continueDetection() {
document.dispatchEvent(
new CustomEvent('document-auto-capture:control', {
detail: { instruction: 'continue-detection' },
}),
);
}
Handling errors
When an error occurs we call onError
callback with one parameter of type Error
. We set name
property to AutoCaptureError
and also message
with more details.
Component renders default UI for error state but is not customizable, and integrator should implement own error handling.
Component uses the MediaDevices API that provides access to connected media input devices like cameras and microphones.
If the user denies permission to access or the webcam is not present, an error is thrown. We provide original error thrown by browser inside cause
property of the error object.
List of possible errors can be found on MDN docs.
Error example:
{
name: "AutoCaptureError",
message: "The webcam is already in use by another application",
cause: DOMException: Could not start video source // Original error thrown by browser MediaDevices API
}
Ui component
Requirements
Both components must be wrapped in parent div with position: relative
.
<div style={{position: 'relative'}}>
<DocumentCamera
imageType="png"
cameraFacing="environment"
onPhotoTaken={handlePhotoTaken}
onError={onError}
/>
<DocumentUi />
</div>
Initialization
UI component can be installed via NPM, yarn or pnpm
npm install @innovatrics/dot-auto-capture-ui
To manually integrate UI component, download latest version from the Github repository. Add following line to dependencies in your package.json:
"dependencies": {
"@innovatrics/dot-auto-capture-ui": "file:dot-auto-capture-ui-[VERSION].tgz",
}
where [VERSION]
is the DOT Web Document Auto Capture version integrated. This installs dot-auto-capture-ui
as an external module that can be used (just like any other module in the code). For example, one could do import '@innovatrics/dot-auto-capture-ui';
in the app.
Usage
Document auto capture UI component is an web component which uses custom HTML <x-dot-document-auto-capture-ui />
tag.
Properties props
needs to be passed into component after <x-dot-document-auto-capture-ui />
tag was rendered.
import type { DocumentUiProps, HTMLDocumentUiElement } from '@innovatrics/dot-auto-capture-ui/document'
import '@innovatrics/dot-auto-capture-ui/document';
import { useEffect } from 'react';
const DocumentUi = (props: DocumentUiProps) => {
useEffect(() => {
const uiElement = document.getElementById('x-dot-document-auto-capture-ui') as HTMLDocumentUiElement | null;
if (uiElement) {
uiElement.props = props;
}
});
return <x-dot-document-auto-capture-ui id="x-dot-document-auto-capture-ui" />;
};
TypeScript
Declaration files are bundled inside package. Just import types from @innovatrics/dot-auto-capture-ui/document
.
Properties
(Optional)
enum placeholder
- One of the predefined placeholders in component that can be selectedID_CORNERS = 'id-corners'
ID_DASH = 'id-dash'
ID_DOT = 'id-dot'
ID_SOLID = 'id-solid'
ID_PHOTO_ROUNDED = 'id-photo-rounded'
ID_CORNERS_ROUNDED = 'id-corners-rounded'
ID_DASH_ROUNDED = 'id-dash-rounded'
ID_DOT_ROUNDED = 'id-dot-rounded'
ID_SOLID_ROUNDED_BACK = 'id-solid-rounded-back'
ID_SOLID_ROUNDED = 'id-solid-rounded'
PASSPORT_SOLID_BACK = 'passport-solid-back'
PASSPORT_SOLID_BACK_BLANK = 'passport-solid-back-blank'
(Optional)
object instructions
- Modification of default messages for localization or customization(Optional)
['Hold still…']
string candidate_selection
- Shown when all validations are passed, i.e. image is suitable for capture(Optional)
['Place document in rectangle']
string document_centering
- Shown when the document is not centered inside the placeholder(Optional)
['Move back']
string document_too_close
- Shown when the document is too close to the camera(Optional)
['Place document in rectangle']
string document_not_present
- Shown when no document is detected(Optional)
['Move closer']
string document_too_far
- Shown when the document is too far from the camera.(Optional)
['More light needed']
string sharpness_too_low
- Shown when the document found in the image is not sharp enough(Optional)
['More light needed']
string brightness_too_low
- Shown when the image is too dark(Optional)
['Less light needed']
string brightness_too_high
- Shown when the image is too bright.(Optional)
['Avoid reflections']
string hotspots_present
- Shown when the document found in the image has reflections
(Optional)
theme
- Modification of theme properties.(Optional)
colors
- To customize colors of following properties(Optional)
['white']
color placeholderColor
- Color of the placeholder lines(Optional)
['#00BFB2']
color placeholderColorSuccess
- Color of the placeholder lines when all validations are passed(Optional)
['white']
color instructionColor
- Instruction background color(Optional)
['#00BFB2']
color instructionColorSuccess
- Instruction background color when all validations are passed(Optional)
['black']
color instructionTextColor
- Instruction text color
(Optional)
appStateInstructions
- Modification of default messages for component state(Optional)
loading
- Component loading state(Optional)
['Loading. Please wait.']
string text
- Text shown while component is loading(Optional)
[true]
boolean visible
- Show/hide loading instruction while component is loading
(Optional)
waiting
- Component waiting state(Optional)
['Waiting for input']
string text
- Text shown while component is waiting(Optional)
[true]
boolean visible
- Show/hide waiting instruction while component is waiting
(Optional)
[false]
boolean
showDetectionLayer
- Show/hide detection layer on top of component(Optional)
[false]
boolean
showCameraButtons
- Show/hide camera buttons (switch camera and toggle mirror) on top of component
Example how to use UI properties:
import { DocumentPlaceholderIcon } from '@innovatrics/dot-auto-capture-ui/document';
<DocumentUi
theme={{ colors: { placeholderColor: 'green' } }}
placeholder={DocumentPlaceholderIcon.ID_DASH}
instructions={{ candidate_selection: 'Candidate selection' }}
appStateInstructions={{ loading: { text: 'Component is loading', visible: true } }}
showDetectionLayer
showCameraButtons
/>
In javascript you can use values of DocumentPlaceholderIcon
directly.
<DocumentUi placeholder="id-dash" />
Custom Events - Optional
Communication between components is based on custom events. Ui component is mostly listening to events dispatched by Non-ui component. In case of CONTROL
event, Ui component dispatches control events to control Non-ui component.
When using default Ui component, only dispatch continue-detection
event has to be implemented to use Multi capture.
Type of Events
Currently all events being used are described in this section. These are sufficient to build custom UI layer.
enum DocumentCustomEvent
- Event names dispatched by componentsCONTROL = 'document-auto-capture:control'
- Events dispatched from Ui component to control Non-ui component. Described in Control Events sectionCAMERA_PROPS_CHANGED = 'document-auto-capture:camera-props-changed'
- Notifies UI when camera properties has changedINSTRUCTION_CHANGED = 'document-auto-capture:instruction-changed'
- Notifies UI when instruction has changedSTATE_CHANGED = 'document-auto-capture:state-changed'
- Notifies UI when state of Non-ui component has changedDETECTED_DOCUMENT_CHANGED = 'document-auto-capture:detected-document-changed'
- Notifies UI when document corners are detected. Used in Detection Layer, has no effect ifshowDetectionLayer = false
VIDEO_ELEMENT_SIZE = 'document-auto-capture:video-element-size'
- Notifies UI when HTML video element size has changed
Usage
Import @innovatrics/dot-document-auto-capture/events
to use event types and and dispatch control events.
Listening to the Events
All event listeners are already implemented in default Ui component. Skip this section if you are using default Ui component.
All DocumentCustomEvent
events, except CONTROL
, are dispatched by Document Auto Capture Non-ui component. Ui component listens to these events to make appropriate changes. See the example below how to register event listeners.
import type {
DocumentInstructionChangeEvent,
CameraPropsChangeEvent,
CameraStateChangeEvent,
DetectedDocumentChangeEvent,
VideoElementSizeChangeEvent
} from '@innovatrics/dot-document-auto-capture/events'
import { DocumentCustomEvent } from '@innovatrics/dot-document-auto-capture/events';
import type {
AppState,
DetectedDocumentCorners,
DocumentInstructionCode,
Resolution,
AutoCaptureError
} from '@innovatrics/dot-document-auto-capture';
import { useEffect, useState } from 'react'
const Events = () => {
const [instructionCode, setInstructionCode] = useState<DocumentInstructionCode | undefined>();
const [cameraResolution, setCameraResolution] = useState<Resolution | undefined>();
const [isMirroring, setIsMirroring] = useState<boolean | undefined>();
const [appState, setAppState] = useState<AppState | undefined>();
const [error, setError] = useState<AutoCaptureError | undefined>();
const [detectedDocumentCorners, setDetectedDocumentCorners] = useState<DetectedDocumentCorners | undefined>();
const [videoElementSize, setVideoElementSize] = useState<DOMRect | undefined>();
useEffect(() => {
const handleInstruction = (event: DocumentInstructionChangeEvent) => {
setInstructionCode(event?.detail?.instructionCode);
};
const handleCameraProps = (event: CameraPropsChangeEvent) => {
setCameraResolution(event?.detail?.cameraResolution);
setIsMirroring(event?.detail?.isMirroring);
};
const handleAppState = (event: CameraStateChangeEvent) => {
setAppState(event?.detail?.appState);
const error = event?.detail?.error;
if (error) {
setError(error);
}
};
const handleDetectedDocument = (event: DetectedDocumentChangeEvent) => {
setDetectedDocumentCorners(event?.detail?.detectedCorners);
};
const handleVideoElementSize = (event: VideoElementSizeChangeEvent) => {
setVideoElementSize(event.detail?.size)
}
document.addEventListener(DocumentCustomEvent.INSTRUCTION_CHANGED, handleInstruction);
document.addEventListener(DocumentCustomEvent.CAMERA_PROPS_CHANGED, handleCameraProps);
document.addEventListener(DocumentCustomEvent.STATE_CHANGED, handleAppState);
document.addEventListener(DocumentCustomEvent.DETECTED_DOCUMENT_CHANGED, handleDetectedDocument);
document.addEventListener(DocumentCustomEvent.VIDEO_ELEMENT_SIZE, handleVideoElementSize)
return () => {
document.removeEventListener(DocumentCustomEvent.INSTRUCTION_CHANGED, handleInstruction);
document.removeEventListener(DocumentCustomEvent.CAMERA_PROPS_CHANGED, handleCameraProps);
document.removeEventListener(DocumentCustomEvent.STATE_CHANGED, handleAppState);
document.removeEventListener(DocumentCustomEvent.DETECTED_DOCUMENT_CHANGED, handleDetectedDocument);
document.removeEventListener(DocumentCustomEvent.VIDEO_ELEMENT_SIZE, handleVideoElementSize);
};
}, [])
}
Without importing @innovatrics/dot-document-auto-capture/events
you can use values of DocumentCustomEvent
directly.
const instructionChangeEvent = "document-auto-capture:instruction-changed";
function handleInstructionChange(event) {
console.log(event.detail.instructionCode)
}
document.addEventListener(instructionChangeEvent, handleInstructionChange);
/**
* remove event listener when you're done
*/
document.removeEventListener(instructionChangeEvent, handleInstructionChange);
Control Events
Control events are dispatched from Ui component to control Non-ui component.
enum ControlEventInstruction
CONTINUE_DETECTION = 'continue-detection'
- Controls Multi captureSWITCH_CAMERA = 'switch-camera'
- Notifies Document Auto Capture to use different cameraTOGGLE_MIRROR = 'toggle-mirror'
- Notifies Document Auto Capture to mirror video stream
import { dispatchControlEvent, DocumentCustomEvent, ControlEventInstruction } from '@innovatrics/dot-document-auto-capture/events';
export const Dispatch = () => {
const continueDetection = () => {
dispatchControlEvent(DocumentCustomEvent.CONTROL, ControlEventInstruction.CONTINUE_DETECTION)
}
const switchCamera = () => {
dispatchControlEvent(DocumentCustomEvent.CONTROL, ControlEventInstruction.SWITCH_CAMERA)
}
const toggleMirror = () => {
dispatchControlEvent(DocumentCustomEvent.CONTROL, ControlEventInstruction.TOGGLE_MIRROR)
}
return (
<div>
<button onClick={continueDetection}>Continue detection</button>
<button onClick={switchCamera}>Switch camera</button>
<button onClick={toggleMirror}>Mirror camera</button>
</div>
)
}
Without importing @innovatrics/dot-document-auto-capture/events
you can use values of DocumentCustomEvent
and ControlEventInstruction
directly.
const continueDetection = () => {
document.dispatchEvent(
new CustomEvent('document-auto-capture:control', {
detail: { instruction: 'continue-detection' },
}),
);
}
Example of using components together
import type { DocumentComponentData } from '@innovatrics/dot-document-auto-capture';
import {
dispatchControlEvent,
DocumentCustomEvent,
ControlEventInstruction
} from '@innovatrics/dot-document-auto-capture/events'
import { useCallback } from 'react';
import DocumentCamera from './DocumentCamera'
import DocumentUi from './DocumentUi'
const DocumentAutoCapture = () => {
const handlePhotoTaken = (image: Blob, data: DocumentComponentData) => {
console.log(image, data);
}
const handleError = useCallback(
(error: Error) => {
alert(error)
},
[],
);
const handleContinueDetection = () => {
dispatchControlEvent(DocumentCustomEvent.CONTROL, ControlEventInstruction.CONTINUE_DETECTION)
};
return (
<div>
<button onClick={handleContinueDetection}>Continue detection</button>
<div style={{ position: 'relative' }}>
<DocumentCamera
imageType="png"
cameraFacing="environment"
onPhotoTaken={handlePhotoTaken}
onError={handleError}
/>
<DocumentUi />
</div>
</div>
);
};
Code Samples
See also DOT Web Samples showing the usage of DOT Web Auto Capture components in different front-end technologies like React, Angular…
Appendix
Changelog
4.0.1 - 2023-01-19
Fixed
export events from
@innovatrics/dot-document-auto-capture/events
4.0.0 - 2023-01-19
Removed
UI layer from camera component (buttons, placeholder, instruction and app state overlay)
strict mode
andplaceholder fit
validator
Added
UI package with placeholder, instructions, buttons and detection layer
Custom events and events listeners for communication from app to component (switch-camera, toggle-mirror)
Custom events and events listeners for communication from components to app (camera-resolution-changed, instruction-changed, detected-document-changed, state-changed)
showCameraButtons
switch for show/hide camera buttons (switch camera, toggle mirror)SAM version
into debug layer
Changed
Rename
photoTakenCb
toonPhotoTaken
onPhotoTaken
returns full frame image, instead of croppedOrder of instruction processing. Before validating the centering of the detected document, the size of the detected document is validated.
Component is now build as
umd
andes module
Camera buttons (switch camera, toggle mirror) are now hidden by default
3.5.2 - 2022-12-16
Fixed
Camera switch on Android devices with Firefox
3.5.1 - 2022-10-13
Fixed
Memorized props from first instance which holds reference to callback function from initialization on every capture
3.5.0 - 2022-10-10
Changed
Dynamic candidate selection phase duration
Fixed
Minimal camera resolution check
Selection of best image in candidate selection phase entering
3.4.3 - 2022-09-28
Fixed
Possible false candidate selection on first frame after entering candidate selection
3.4.2 - 2022-08-10
Fixed
Typescript declaration files export
3.3.1 - 2022-07-04
Fixed
Zero height of component when error occurs
Add
add
appStateInstructions
property to uiCustomisationadd option to change appState instructions text and visibility
Change
interface for changing
Loading
appState instruction text
3.3.0 - 2022-06-03
Changed
Parent of
<x-dot-document-auto-capture />
does not have to have a defined height
3.2.0 - 2022-05-13
Added
Add support for capturing multiple document photos
Add custom event
document-auto-capture
withcontinue-detection
instruction to continue detectionAdd
Countly
analytics trackingSession recording for document detection
Changed
onError
callback returnsAutoCaptureError
onError
callback is requiredShow error screen when error occurs
When
photoTakenCb
is called, component switches into waiting state
Fixed
Stucked component when error occurs
3.1.2 - 2022-04-04
Changed
Remove force manual capture on instruction click
3.1.0 - 2022-02-14
Added
Add
detectionLayerVisible
with default valuefalse
3.0.3 - 2022-02-03
Fixed
Unify loading and instruction design
3.0.2 - 2022-01-28
Added
Add loading screen
Add
loading.text
property inuiCustomisation
for configuring text on loading screen
Changed
Show new instruction only if 600ms elapsed since last instruction change
Changed default value for
document_centering
instruction
3.0.1 - 2022-01-25
Added
Introduced possibility to choose between
normal
andstrict
validation modeOption to select between
normal
orstrict
validation mode.OutOfBoundsValidator
andOutOfBoundsThreshold
SizeSmallValidator
andSizeSmallThreshold
Fixed
safari version 15 on mac
Changed
Document detection accuracy improved.
Detection area size
New `sam.wasm`file
Removed
blaze_models
packagemodelUrls
option from cameraOptions
2.3.1 - 2022-01-10
Fixed
Fix bug causing integration error
2.3.0 - 2022-01-05
Added
add
cameraSettings
intophotoTakenCb
callBack function
Changed
photoTakenCb
callBack function structureRedesign of the UI of Document Auto Capture component.
2.2.2 - 2021-12-17
Added
samWasmUrl
property for configure path to SAM wasm binary file
2.2.1 - 2021-12-09
Added
New SVG placeholder
pass-rounded-rectangle-solid-back-blank
Changed
Hide switch camera button if there is only 1 webcam available
Default camera facing for mobile phones is set to
environment
and for others platforms is set touser
Computation of
placeholderErrorScore
for document placement inside placeholderDefault value for
placeholderErrorScoreThreshold
from0.03
to0.035
Fixed
On android phones choose correct default lens if more than one available
2.2.0 - 2021-11-30
Changed
dynamic import of TensorFlow.js libraries
2.1.0 - 2021-11-18
First released version
description: "Face detection and face verification web package. UI and non-UI face components for digital onboarding. Learn more in product documentation."