---
title: "Video Selfie Module"
url: "https://developer.incode.com/sdk-reference/web-sdk-2-module-video-selfie/"
section: "sdk-reference"
group: "Incode Web SDK 2 Reference / Web SDK 2 Individual Modules"
version: "v1.1"
status: "live"
---
# Video Selfie Module

:::note
  This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation [here](/sdk-reference/web-sdk-reference/).  Contact your Incode Representative for upgrade information and check if you are a candidate for this upgrade. <br /><br />Full rollout to all clients still TBD.
:::

The Video Selfie module runs selfie, ID, and optional voice-consent capture as one continuous camera session, recorded on-device and uploaded alongside the captures. The camera switches between front and rear while a single composited recording follows it, so the user sees one uninterrupted experience instead of a sequence of separate capture screens.

This module combines [camera-capture](/sdk-reference/web-sdk-2-module-patterns/#2-camera-capture-modules) and [composite / orchestrator](/sdk-reference/web-sdk-2-module-patterns/#5-composite--orchestrator-modules) traits: it owns several capture steps and drives its own step progression.

## Tag

`<incode-video-selfie>` is a standard Web Component. Importing the UI subpath registers the custom element; importing the CSS applies the module's styles.

```ts
import '@incodetech/web/video-selfie';
import '@incodetech/web/video-selfie/styles.css';
```

## Properties

| Property   | Type                                   | Required | Description                       |
| ---------- | -------------------------------------- | -------- | --------------------------------- |
| `config`   | `VideoSelfieConfig`                    | ❌        | Configuration options             |
| `onFinish` | `() => void`                           | ❌        | Called when the session completes |
| `onError`  | `(error: string \| undefined) => void` | ❌        | Called when an error occurs       |

## Configuration

`VideoSelfieConfig` mirrors the backend `VIDEO_ONBOARDING` workflow module, so inside `<incode-flow>` or `<incode-workflow>` the orchestrator supplies it from Dashboard. Standalone integrators set it on `config` directly.

`config.steps` can explicitly select and order the capture steps. When absent or empty, the SDK derives the order from options such as `checkIdScan` and `checkVoiceConsent`.

| Option                      | Type      | Description                                                                                      |
| --------------------------- | --------- | ------------------------------------------------------------------------------------------------ |
| `steps` | `VideoSelfieStep[]` | Optional ordered capture steps. An absent or empty list uses the derived order. |
| `maxWaitingVideoSelfieFile` | `number` | Maximum recording duration in seconds, supplied by Dashboard. It is not an upload timeout. |
| `useAsSelfie`               | `boolean` | Treat the captured selfie as the session's selfie, so a separate Selfie step is unnecessary.     |
| `showTutorials`             | `boolean` | Show the tutorial screen before capture. When `false`, the module starts at the permission step. |
| `companyName`               | `string`  | Company name shown in the consent copy.                                                          |
| `checkLiveness`             | `boolean` | Run liveness checks on the selfie step.                                                          |
| `checkIdScan`               | `boolean` | Add the front and back ID capture steps.                                                         |
| `checkDocumentScan`         | `boolean` | Add the proof-of-address document step.                                                          |
| `compareIdEnabled`          | `boolean` | Compare the captured face against the ID portrait.                                               |
| `compareOcrEnabled`         | `boolean` | Compare OCR data from the front of the ID.                                                       |
| `compareBackIdEnabled`      | `boolean` | Compare against the back of the ID.                                                              |
| `compareBackOcrEnabled`     | `boolean` | Compare OCR data from the back of the ID.                                                        |
| `checkVoiceConsent`         | `boolean` | Add the spoken-consent step.                                                                     |
| `voiceConsentQuestions`     | `number`  | How many consent questions to ask.                                                               |
| `numberOfTries`             | `number`  | Validation attempts per capture and voice step. Default `3`; `-1` means unlimited.               |
| `speechToTextCheck`         | `boolean` | Validate the consent audio server-side. Default `true`.                                          |
| `selfieQualityAffectsScore` | `boolean` | Let selfie quality contribute to the session score.                                              |
| `validateClosedEyes`        | `boolean` | Reject frames where the eyes are closed.                                                         |
| `validateFaceMask`          | `boolean` | Reject frames where a face mask is present.                                                      |
| `validateHeadCover`         | `boolean` | Reject frames where a head covering obscures the face.                                           |
| `validateLenses`            | `boolean` | Reject frames where glasses or lenses interfere.                                                 |

Pass Dashboard-provided quality-check settings through unmodified. The recording duration limit applies to the active recording, including capture steps.

## Steps

`VideoSelfieStep` is the set of capture steps a session can run, in flow order:

| Step        | Camera | Description                                    |
| ----------- | ------ | ---------------------------------------------- |
| `selfie`    | Front  | Face capture with liveness and quality checks. |
| `frontId`   | Rear   | Front of the ID document.                      |
| `backId`    | Rear   | Back of the ID document.                       |
| `poa`       | Rear   | Proof-of-address document.                     |
| `questions` | Front  | On-screen consent questions.                   |
| `speech`    | Front  | Spoken consent, recorded for verification.     |

For example, `steps: ['selfie', 'frontId', 'backId']` keeps that order. A nonempty top-level `steps` option on `createVideoSelfieRecordingManager` takes precedence over `config.steps`. If both are absent or empty, the derived order is ID sides, optional proof of address, Selfie, then configured questions and speech.

## State machine

`VideoSelfieRecordingState` carries a `status` plus live step and detection detail:

| Status               | Description                                                                      |
| -------------------- | -------------------------------------------------------------------------------- |
| `idle`               | Initial state, waiting for `start()`.                                            |
| `starting`           | Acquiring the first camera and opening the upload.                               |
| `recording`          | Capturing the active step.                                                       |
| `validationFeedback` | A validation check failed; the module dwells to show the reason before retrying. |
| `flippingId`         | Prompting the user to turn the ID over between the front and back steps.         |
| `switchingCamera`    | Moving between front and rear cameras for the next step.                         |
| `finalizing`         | Finishing the upload after the last step.                                        |
| `success`            | Upload accepted. Carries `recordingId`.                                          |
| `finished`           | Terminal.                                                                        |
| `error`              | Failed. Carries `error` and `errorKind`.                                         |
| `aborted`            | The session was abandoned without finalizing.                                    |

State properties:

| Property            | Type                          | Description                                                                                                                         |
| ------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `step`              | `VideoSelfieStep?`            | The active capture step.                                                                                                            |
| `stepIndex`         | `number`                      | Zero-based index of the active step.                                                                                                |
| `isLastStep`        | `boolean`                     | Whether advancing finalizes the session.                                                                                            |
| `stream`            | `MediaStream?`                | The raw camera for the active step. Render this as the preview.                                                                     |
| `composite`         | `MediaStream?`                | The composited recording output that follows camera switches. Not for preview.                                                      |
| `detectionStatus`   | `string?`                     | Live capture feedback for the active step — show it as guidance.                                                                    |
| `orientation`       | `DetectionOrientation?`       | Document orientation when the detector reports one, so an ID mask can follow a rotated document. `undefined` keeps the fixed frame. |
| `validationFailure` | `object?`                     | Why the current attempt failed, during a `validationFeedback` dwell.                                                                |
| `attemptsRemaining` | `number`                      | Attempts left on the active step. `-1` means unlimited.                                                                             |
| `recordingId`       | `string \| null`              | The completed upload id, available during `success` and `finished`.                                                                 |
| `error`             | `string?`                     | Failure detail when `status === 'error'`.                                                                                           |
| `errorKind`         | `'connection' \| 'technical' \| 'maxVideoLengthReached' \| 'validationAttemptsExhausted'` | Failure category; the duration-limit and exhausted-validation kinds cannot retry.                                         |

## API methods

| Method       | Purpose                                                                         | Callable when                 |
| ------------ | ------------------------------------------------------------------------------- | ----------------------------- |
| `start()`    | Acquire the camera, open the upload, and begin recording.                       | `idle`                        |
| `nextStep()` | Advance to the next step, switching cameras when needed. Finalizes on the last. | `recording`                   |
| `retry()`    | Retry the active step after a validation failure or error.                      | `validationFeedback`; `error` only for recoverable `connection` or `technical` failures |
| `abort()`    | Abandon the session without finalizing the upload.                              | Any active status             |

Plus the universal lifecycle: `subscribe`, `getState`, `stop`.

### Terminal errors

`maxVideoLengthReached` means the configured recording duration has elapsed. Do not offer retry. The SDK completes the recorded upload, briefly displays the limit message, then reaches `finished` so Flow can advance.

`validationAttemptsExhausted` means the allowed validation attempts have ended. Do not retry or restart that attempt in place. A standalone component reports it through `onError` with `moduleErrorCode: 'VIDEO_SELFIE_VALIDATION_ATTEMPTS_EXHAUSTED'`. Flow handles that terminal module outcome by advancing the configured journey; it is not a successful verification result.

Headless hosts should branch on `errorKind`, preserve session-result handling, and stop the manager when leaving the surface.

## Headless usage

```typescript
import { setup } from '@incodetech/core';
import { createVideoSelfieRecordingManager } from '@incodetech/core/video-selfie';

await setup({ apiURL, token });

const manager = createVideoSelfieRecordingManager({ config });

manager.subscribe((state) => {
  if (state.status === 'recording') {
    renderPreview(state.stream, {
      step: state.step,
      guidance: state.detectionStatus,
      attemptsLeft: state.attemptsRemaining,
    });
  }
  if (state.status === 'finished') {
    onDone(state.recordingId);
  }
});

manager.start();
```

Render `state.stream` as the preview, not `state.composite` — the composite exists to keep one continuous recording across camera switches.

Creating the manager starts its required WASM warmup. `manager.start()` waits for that warmup before it acquires the camera, and reports a retryable technical error if warmup fails.

`@incodetech/core/video-selfie` also exports helpers for building your own capture screen: `resolveVideoSelfieSteps` (which steps a config runs), `facingModeForStep`, `createVideoSelfieCameraWarmer` (warm the camera before the user reaches the step), `getVideoSelfieQuestions` and `getVoiceConsentPhrase` (consent copy), and `createConsentRecorder`.

## App background recovery

When the browser moves to the background, the module pauses recording and capture validation. The open upload and completed video chunks remain unchanged.

When the browser returns, the module waits for a new camera frame before it resumes recording. The module acquires the video camera again if necessary.

If the audio track or recorder cannot recover, the module reports a technical error. The user can retry with a new recording.

The module does not complete a recording with a frozen background interval.

## WASM requirement

The resolved steps determine pipelines: `selfie` needs `videoSelfie`; `frontId` or `backId` needs `videoSelfieId`. This also applies to explicit step lists. The Core recording manager automatically loads exactly what its config needs. You can still call `warmupVideoSelfieWasm(config, steps)` earlier for explicit preloading, or derive the list with `videoSelfieWasmPipelines(config, steps)` and pass it to `setup({ wasm: { pipelines } })`.

## See also

- [Module Patterns → camera-capture](/sdk-reference/web-sdk-2-module-patterns/#2-camera-capture-modules)
- [WASM Configuration](/sdk-reference/web-sdk-2-wasm/)
- [Module: Selfie](/sdk-reference/web-sdk-2-module-selfie-1/): the single-step selfie capture module
- [Individual Modules](/sdk-reference/web-sdk-2-individual-modules/)