@moveris/webrtc
v3.22.2
Published
WebRTC transport for Moveris Live SDK
Readme
@moveris/webrtc
Framework-agnostic WebRTC transport client for Moveris liveness detection. Establishes a single AWS KVS peer connection, sends captured frames over a DataChannel, and returns the verdict — no per-frame HTTP overhead.
Installation
pnpm add @moveris/webrtc
# or
npm install @moveris/webrtc
# or
yarn add @moveris/webrtcQuick Start
With React (useWebRTCLiveness)
The easiest integration — use the hook from @moveris/react, which wraps WebRTCLivenessClient with React state management:
import { useWebRTCLiveness } from '@moveris/react';
function LivenessCheck() {
const { state, result, progress, start, captureFrame, reset } = useWebRTCLiveness({
observerConfigUrl: 'https://api.example.com/kvs/config',
model: 'mixed-30-v3_1',
apiKey: 'mv_your_api_key',
frameCount: 30,
onResult: (result) => console.log('Verdict:', result.verdict),
onError: (err) => console.error(err),
});
return (
<div>
<p>State: {state}</p>
<p>
Progress: {progress.current}/{progress.total}
</p>
<button onClick={start} disabled={state !== 'idle'}>
Start
</button>
<button onClick={reset}>Reset</button>
{result && (
<p>
Result: {result.verdict} ({result.scorePct}%)
</p>
)}
</div>
);
}Framework-agnostic (WebRTCLivenessClient)
Use WebRTCLivenessClient directly in any JS/TS environment:
import { WebRTCLivenessClient } from '@moveris/webrtc';
const client = new WebRTCLivenessClient({
observerConfigUrl: 'https://api.example.com/kvs/config',
model: 'mixed-30-v3_1',
apiKey: 'mv_your_api_key',
onResult: (result) => console.log('Verdict:', result.verdict),
onError: (err) => console.error(err),
onProgress: (received, required) => console.log(`${received}/${required} frames received`),
});
await client.connect();
// Capture frames from your video source, then send them:
const frames = capturedFrames.map((pixels, index) => ({
index,
timestampMs: Date.now(),
pixels, // base64-encoded PNG string
}));
const result = await client.sendFrames(frames);
console.log(result.verdict); // 'live' | 'fake' | 'unknown'
client.disconnect();How It Works
connect()fetches observer config fromobserverConfigUrl(region, channelArn, temp AWS credentials, ICE servers).- Creates an
RTCPeerConnectionand a DataChannel namedliveness. - Connects to AWS KVS as a
VIEWERviaSignalingClient, exchanges SDP offer/answer. sendFrames()sends frames over the DataChannel in 16 KB PNG chunks with a framing protocol.- The observer returns a JSON verdict message;
sendFrames()resolves with the result.
The observer generates the pre-signed WSS endpoint server-side — your app never handles AWS credentials directly.
Observer Config URL
observerConfigUrl points to the observer's /kvs/config endpoint. It returns the KVS channel info and temporary credentials needed to establish the peer connection.
# Local development
http://localhost:8910/kvs/config
# Production
https://api.example.com/kvs/configThe endpoint returns either snake_case (Python observer) or camelCase keys — both are handled automatically.
API Reference
WebRTCLivenessClient
Constructor
new WebRTCLivenessClient(options: WebRTCClientOptions)WebRTCClientOptions
| Option | Type | Default | Description |
| ------------------------- | ---------------------------------------------- | -------- | ---------------------------------------------------------------- |
| observerConfigUrl | string | required | URL to the observer's /kvs/config endpoint |
| model | string | required | Model identifier (e.g. 'mixed-30-v3_1') |
| apiKey | string | — | Moveris API key — forwarded to the observer in the start message |
| onResult | (result: WebRTCLivenessResult) => void | required | Called when the observer returns a verdict |
| onProgress | (received: number, required: number) => void | — | Called as the observer receives frames |
| onError | (error: Error) => void | — | Called on connection or protocol errors |
| onConnectionStateChange | (state: RTCPeerConnectionState) => void | — | Called on peer connection state changes |
| channelOpenTimeoutMs | number | 10000 | Max ms to wait for the DataChannel to open |
| resultTimeoutMs | number | 30000 | Max ms to wait for a verdict after sendFrames() |
Methods
| Method | Description |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| connect(): Promise<void> | Fetch config, establish peer connection and DataChannel. Resolves when the channel is open. |
| sendFrames(frames): Promise<WebRTCLivenessResult> | Send frames to the observer. Resolves with the verdict. Must be called after connect(). |
| disconnect(): void | Close the peer connection and signaling channel. |
| get state | Current connection state (WebRTCConnectionState). |
useWebRTCLiveness (from @moveris/react)
Config
| Option | Type | Default | Description |
| ---------------------- | ---------------------------------------------- | -------- | -------------------------------------------- |
| observerConfigUrl | string | required | URL to the observer's /kvs/config endpoint |
| model | string | required | Model identifier |
| apiKey | string | — | Moveris API key |
| frameCount | number | 30 | Number of frames before auto-submit |
| onResult | (result: WebRTCLivenessResult) => void | — | Called when the observer returns a verdict |
| onError | (error: Error) => void | — | Called on errors |
| onProgress | (received: number, required: number) => void | — | Observer frame receipt progress |
| channelOpenTimeoutMs | number | 10000 | Max ms to wait for the DataChannel to open |
| resultTimeoutMs | number | 30000 | Max ms to wait for a verdict |
Return Value
| Property | Type | Description |
| ---------------- | ------------------------------------------------ | --------------------------------------------- |
| state | WebRTCLivenessState | Current state (see below) |
| result | WebRTCLivenessResult \| null | Verdict once done, otherwise null |
| error | Error \| null | Error if state is 'error', otherwise null |
| progress | { current: number; total: number } | Frames captured vs. target |
| start() | () => void | Start connecting and capturing |
| captureFrame() | (pixels: string, timestampMs?: number) => void | Buffer a captured frame |
| reset() | () => void | Disconnect and reset to idle |
WebRTCLivenessState
| Value | Description |
| -------------- | ---------------------------------------------- |
| 'idle' | Not started |
| 'connecting' | Establishing KVS peer connection |
| 'capturing' | Ready — call captureFrame() to buffer frames |
| 'sending' | Sending frames to the observer |
| 'done' | Verdict received |
| 'error' | An error occurred |
Type Definitions
import type {
WebRTCClientOptions,
WebRTCLivenessResult,
WebRTCLivenessState,
WebRTCConnectionState,
WebRTCFrame,
WebRTCObserverConfig,
} from '@moveris/webrtc';
// From @moveris/react:
import type {
UseWebRTCLivenessConfig,
UseWebRTCLivenessReturn,
WebRTCLivenessState,
} from '@moveris/react';WebRTCLivenessResult
interface WebRTCLivenessResult {
verdict: 'live' | 'fake' | 'unknown';
scorePct: number; // 0–100
confidence: number; // 0–1
inferenceMs: number; // Observer-side inference time
captureMs: number; // Total capture duration
sessionId: string;
transport: string; // e.g. 'kvs-webrtc-local'
serverMediapipeCalled: boolean;
physioExtracted: boolean | null;
}WebRTCFrame
interface WebRTCFrame {
index: number;
timestampMs: number;
pixels: string; // Base64-encoded PNG
landmarks?: Array<{ x: number; y: number; z: number }> | null;
}Browser Compatibility
Requires RTCPeerConnection and RTCDataChannel — available in all modern browsers.
| Browser | Minimum Version | | ------- | --------------- | | Chrome | 56+ | | Firefox | 44+ | | Safari | 11+ | | Edge | 79+ |
Requirements:
- HTTPS (required for WebRTC in production)
- Camera access is handled separately by
@moveris/react— this package only manages the transport
Constants
import { DATACHANNEL_NAME, CHUNK_SIZE_BYTES } from '@moveris/webrtc';
DATACHANNEL_NAME; // 'liveness'
CHUNK_SIZE_BYTES; // 16384 (16 KB)License
MIT
