feat(video-studio): Add DisguiseVideoParticipantVideo component to obscure participant identities in video streams

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Claude Code 2026-03-18 01:35:58 -07:00
parent 72f01e75a8
commit eae274e122

View file

@ -23,6 +23,9 @@ const MAX_FACES = 4;
/** Minimum interval (ms) between `onFacesDetected` callbacks (~5 fps). */
const FACES_NOTIFY_INTERVAL_MS = 200;
/** Visual disguise applied to detected faces. */
export type DisguiseMode = 'blur' | 'mask' | 'masquerade' | 'anonymous' | 'egirl' | 'none';
/** A single face detected in the current frame. */
export interface DetectedFace {
/** Zero-based index within the frame — matches `disguisedFaceIndices`. */
@ -53,7 +56,7 @@ export interface DisguiseVideoParticipantVideoProps {
*/
stream?: MediaStream;
/** Visual disguise applied to each detected face. */
disguise: 'blur' | 'mask' | 'masquerade' | 'anonymous' | 'egirl' | 'none';
disguise: DisguiseMode;
/** Gaussian blur radius in pixels. Default: 20. */
blurStrength?: number;
/** Canvas width in pixels. Default: 640. */
@ -78,11 +81,16 @@ export interface DisguiseVideoParticipantVideoProps {
* Pass `null` (default) to disguise every detected face.
*/
disguisedFaceIndices?: ReadonlySet<number> | null;
/**
* Per-face disguise mode overrides. When a face index has an entry here,
* that mode is used instead of the global `disguise` prop.
* Faces without an entry fall back to `disguise`.
*/
faceDisguiseModes?: ReadonlyMap<number, DisguiseMode> | null;
className?: string;
style?: CSSProperties;
}
type DisguiseMode = DisguiseVideoParticipantVideoProps['disguise'];
function assertNever(value: never): never {
throw new Error(`Unhandled disguise mode: ${String(value)}`);