import { n as WasmPipeline } from "./warmup-Dv2alr2-.js"; import { A as StateMachine, _ as MachineContext, c as AnyEventObject, p as EventObject, v as MetaObject, y as NonReducibleUnknown } from "./spawn-D9jgw9pW.js"; import "./StateMachine-EDpYWy0i.js"; import "./Actor-iTq7YY48.js"; import { t as CameraStream } from "./camera-9wWD-pwg.js"; import { t as DetectionOrientation } from "./IIdCaptureCapability-DHTT3FC2.js"; import { a as FacingMode, i as CameraCompositor, n as VideoSelfieDetectionStatus, o as VideoSelfieConfig, r as VideoSelfieValidationFailure, s as VideoSelfieStep, t as StepDetector } from "./videoSelfieStepDetector-D3oo2ofo.js"; //#region src/internal/recordings/multipartRecordingService.d.ts type MultipartRecordingResult = { /** * The completed upload's id, or `null` if recording produced no parts, a * chunk could not be delivered even after the retry rounds, or * finalization failed. */ recordingId: string | null; }; /** * Records the camera on-device and streams it to the backend as it is * captured, using the video-selfie-service multipart upload protocol * (`/v1/video-upload/*`). * * This is the Video Selfie module's client-side recorder and is deliberately * independent of the face-capture recording services (`LocalRecordingService` * / `OpenViduRecordingService`) — it is the replacement for server-side * (OpenVidu) recording, not a sibling of it. * * Every ~1 s recorder blob uploads as its own chunk, concurrently with * recording, through {@link VideoSelfieChunkUploader} (keep-until-ack + * retry with backoff — see its doc for the full policy). The service stages * sub-5 MiB chunks and combines them server-side, so `stop()` only drains * the stragglers and finalizes; client memory holds un-acked chunks only. * No client-side encryption: video is encrypted at rest server-side * (S3 SSE-AES-256). */ declare class MultipartRecordingService { private recorder; private timer; private session; private uploader; private chunksEmitted; get isRecording(): boolean; start(stream: MediaStream): Promise; stop(): Promise; cleanup(): void; /** * `complete` is idempotent server-side ("safe to repeat if the response * was lost"), so transient failures — network errors, 5xx, 429 — retry a * couple of times before the recording is declared failed. A 4xx (e.g. * `400` naming a missing part) is permanent: after a clean drain every * chunk was acked, so a reported hole cannot be filled from here. */ private completeWithRetry; /** * Fire-and-forget abort: the upload can no longer complete, so tell the * backend to fail it immediately rather than at its expiry. Best-effort — * an abort that doesn't land (including a 409 from a newer epoch having * taken over) just means the server falls back to expiry or salvage. */ private abandonUpload; } //#endregion //#region src/modules/video-selfie/videoSelfieRecordingMachine.d.ts type VideoSelfieRecordingDependencies = { createRecordingService?: () => MultipartRecordingService; createCompositor?: () => CameraCompositor; acquireCamera?: (facingMode: FacingMode, withAudio: boolean) => Promise; /** Runs WASM detection + backend validation per step; resolves to advance. */ detect?: StepDetector; /** Minimum time to hold the switching-camera screen before resuming capture. */ switchingCameraMinDwellMs?: number; }; /** * Why the module errored: `connection` means a transport-level failure the * user can fix by getting back online (the UI shows the connection-error * copy); `technical` is everything else (raw detail stays in `error` for * diagnostics/hosts, the UI shows its generic fallback). */ type VideoSelfieErrorKind = 'connection' | 'technical'; //#endregion //#region src/modules/video-selfie/videoSelfieRecordingActor.d.ts type CreateVideoSelfieRecordingActorOptions = { /** Module config; its flags determine the active capture steps + validations. */ config?: VideoSelfieConfig; dependencies?: VideoSelfieRecordingDependencies; }; //#endregion //#region src/modules/video-selfie/videoSelfieRecordingManager.d.ts type VideoSelfieRecordingStatus = 'idle' | 'starting' | 'recording' | 'validationFeedback' | 'flippingId' | 'switchingCamera' | 'finalizing' | 'success' | 'finished' | 'error' | 'aborted'; type VideoSelfieRecordingState = { /** Current lifecycle status. */ status: VideoSelfieRecordingStatus; /** The active capture step (e.g. `selfie`, `frontId`). */ step: VideoSelfieStep | undefined; /** Zero-based index of the active step. */ stepIndex: number; /** Whether the active step is the last one (advancing it finalizes). */ isLastStep: boolean; /** The active source camera (raw, per-step facing). */ stream: MediaStream | undefined; /** * The composited recording output — a bounded canvas-backed stream that * follows camera switches while the preview renders the raw source stream. */ composite: MediaStream | undefined; /** Live per-step detection feedback (e.g. `tooFar`, `blur`, `detecting`). */ detectionStatus: VideoSelfieDetectionStatus | undefined; /** * Live document orientation from the ID detector, when the pipeline * reports one — the mask follows a rotated ID. `undefined` keeps the * default fixed frame. */ orientation: DetectionOrientation | undefined; /** Validation failure shown during the current retry/exhaustion dwell. */ validationFailure: VideoSelfieValidationFailure | undefined; /** Remaining validation attempts for the active capture step; `-1` means unlimited. */ attemptsRemaining: number; /** The completed upload id, available during `success` and `finished`. */ recordingId: string | null; /** Failure detail, set when `status === 'error'`. */ error: string | undefined; /** * Why the module errored: `connection` (transport failure — the UI shows * the connection-error copy; raw detail stays in `error` for diagnostics) * or `technical` (everything else). Set when `status === 'error'`. */ errorKind: VideoSelfieErrorKind | undefined; }; /** * Creates a manager for a multi-step, camera-switching Video Selfie recording. * * The whole session records as one continuous video that follows the camera * across steps (front for selfie, rear for ID). Exposes `getState()` / * `subscribe()` (status, step, preview `stream`, `recordingId`) plus `start()`, * `nextStep()`, and `abort()`. */ declare function createVideoSelfieRecordingManager(options?: CreateVideoSelfieRecordingActorOptions): { stop(): void; getState(): VideoSelfieRecordingState; subscribe(listener: (state: VideoSelfieRecordingState) => void): () => void; /** Acquire the first camera, open the upload, and begin recording. */ start(): void; retry(): void; /** * Advance to the next step. Switches the camera when the next step's * facing mode differs; finalizes the upload on the last step. */ nextStep(): void; /** Abandon the session without finalizing the upload. */ abort(): void; }; type VideoSelfieRecordingManager = ReturnType; //#endregion //#region src/modules/video-selfie/videoSelfieSteps.d.ts /** * The camera facing mode a given step should use. ID and proof-of-address steps * use the rear camera; selfie / questions / speech use the front camera. */ declare function facingModeForStep(step: VideoSelfieStep): 'user' | 'environment'; /** * Resolves the ordered list of active capture steps from the module config. * The order mirrors V1 `getVideoSelfieModules`: the rear-camera document steps * (`frontId` → `backId` → `poa`) run first, then the front-camera steps * (`selfie` → `questions` → `speech`). This keeps the user from flipping the * device between front and rear cameras mid-session. `selfie` is always present; * the document and voice-consent steps are gated by their config flags. * * Both ID sides are captured whenever `checkIdScan` is on (a normal two-sided ID * scan) — mirroring V1, which gated `back` on `checkIdScan`, not on the compare * flags. `compareBackIdEnabled`/`compareBackOcrEnabled` only decide whether the * captured back is *validated* against the backend (see `validateIdFrame` in * `videoSelfieStepDetector`); with both off the back is captured passively on * the first well-framed frame. */ declare function resolveVideoSelfieSteps(config: VideoSelfieConfig): VideoSelfieStep[]; /** * The WASM pipelines a Video Selfie session loads. The selfie step always runs * face detection (`videoSelfie`); the ID steps run the simplified ID-capture * pipeline (`videoSelfieId`), gated by `checkIdScan`. Used both for the * flow-level eager warmup ({@link getRequiredWasmPipelines}) and the * tutorial-time lazy warmup (`warmupVideoSelfieWasm`). */ declare function videoSelfieWasmPipelines(config: VideoSelfieConfig): WasmPipeline[]; //#endregion //#region src/modules/video-selfie/videoSelfieWasm.d.ts /** * Warms the WASM pipelines the Video Selfie flow needs (face detection, plus the * ID-capture pipeline when `checkIdScan` is on), reusing the WASM config stored * by `setup({ wasm })`. * * Idempotent and safe to call eagerly — the UI invokes it when the tutorial * mounts so the models finish loading while the user reads the instructions, and * detection is ready the instant recording starts (mirrors how the selfie and ID * modules warm up during their tutorials). No-op when WASM was not configured. */ declare function warmupVideoSelfieWasm(config: VideoSelfieConfig): Promise; //#endregion //#region src/modules/video-selfie/videoSelfieCameraWarmer.d.ts /** * Warms the camera for a Video Selfie session ahead of time, so tapping "Start" * on the tutorial begins recording without waiting on `getUserMedia` (mirrors how * the selfie tutorial pre-acquires the camera "when possible"). * * The acquire is gated on permission already being granted — exactly like the * selfie tutorial — so we never trigger the OS camera/mic prompt while the user * is still reading the instructions. */ type VideoSelfieCameraWarmer = { /** * Pre-acquire the first step's camera (video + audio) in the background, but * only when camera permission is already granted. Idempotent — safe to call * repeatedly (e.g. on every tutorial render). */ warm(): void; /** * The `acquireCamera` dependency to hand to the recording manager. It returns * the warmed stream for the machine's first acquire (matching facing mode + * audio) and falls back to a fresh `getUserMedia` for every other acquire * (e.g. the rear→front camera switch) and when nothing was warmed. */ acquireCamera: NonNullable; /** * Stop a warmed-but-unused stream. Call on unmount when capture never started * so the camera light doesn't stay on. No-op once the stream has been consumed * by the recording machine. */ dispose(): void; }; /** * Creates a {@link VideoSelfieCameraWarmer} for the given config. The first * camera (and whether it needs audio) is derived from the resolved step order — * the same first acquire the recording machine performs on `START`. */ declare function createVideoSelfieCameraWarmer(config: VideoSelfieConfig): VideoSelfieCameraWarmer; //#endregion //#region src/modules/video-selfie/videoSelfieSpeechService.d.ts /** A single random question (and its expected answer) for the challenge step. */ type VideoSelfieQuestion = { id: string; question: string; answer: string; }; /** * Fetches `count` random challenge questions the user answers out loud. The * spoken answers are captured in the main video recording (no separate upload) * and verified server-side. */ declare function getVideoSelfieQuestions(count: number): Promise; /** * Fetches the voice-consent phrase the user must read aloud. The phrase is the * `answer` of the consent question returned when `returnVoiceConsentQuestion` * is requested with no challenge questions. */ declare function getVoiceConsentPhrase(): Promise; //#endregion //#region src/modules/video-selfie/videoSelfieConsentRecorder.d.ts /** * Drives the voice-consent audio capture for the Video Selfie speech step: * records the spoken consent phrase as a standalone MP3 (separate from the main * video) and uploads it for speech-to-text validation. The UI owns the start / * submit timing (button taps); this keeps the L0 recorder + upload wiring out * of the L2 component. */ type ConsentRecorder = { /** Start capturing audio from the given stream (uses its audio tracks). */ start(stream: MediaStream): void; /** Stop, encode to MP3 base64, and upload. Resolves the backend verdict. */ submit(): Promise<{ success: boolean; }>; /** Stop and discard without uploading (consent check disabled, or abort). */ cancel(): void; }; declare function createConsentRecorder(): ConsentRecorder; //#endregion //#region src/modules/video-selfie/videoSelfieFlowModuleMachine.d.ts /** * Parked flow-module machine for the `VIDEO_ONBOARDING` step. * * The video-selfie UI component owns the entire capture / streaming / upload * lifecycle (it creates its own {@link createVideoSelfieRecordingManager}) and * signals completion to the flow via `flowManager.completeModule()` * (`MODULE_COMPLETE`). This machine therefore only needs to hold the step open: * it starts in a non-final `running` state and never transitions, so the * orchestrated flow stays in `runningModule` until the UI advances it. * * **Completion contract:** the L2 `incode-video-selfie` web component calls * `flowManager.completeModule()` once the recording manager reaches `finished`. * Recoverable errors stay inside the module until the user retries. * * **Abort / unmount:** if the user closes the module or the web component * unmounts before completion, the orchestrated flow manager's existing close / * abort path (`MODULE_CLOSE` / session teardown) is responsible for exiting the * step. This parked machine does not model those paths itself. * * Contrast {@link noOpFlowModuleMachine}, whose initial state is `final` — that * is used for headless steps (e.g. `IP_ADDRESS`) that must complete instantly * with no UI. Using a no-op here would skip the video-selfie UI entirely. */ declare const videoSelfieFlowModuleMachine: StateMachine; //#endregion export { type ConsentRecorder, type CreateVideoSelfieRecordingActorOptions, type VideoSelfieCameraWarmer, type VideoSelfieConfig, type VideoSelfieQuestion, type VideoSelfieRecordingManager, type VideoSelfieRecordingState, type VideoSelfieRecordingStatus, type VideoSelfieStep, createConsentRecorder, createVideoSelfieCameraWarmer, createVideoSelfieRecordingManager, facingModeForStep, getVideoSelfieQuestions, getVoiceConsentPhrase, resolveVideoSelfieSteps, videoSelfieFlowModuleMachine, videoSelfieWasmPipelines, warmupVideoSelfieWasm };