Built the Sentinel Tab

This commit is contained in:
Sagnik
2026-04-12 02:02:58 +05:30
parent fb656d1443
commit 075ab280ad
526 changed files with 17646 additions and 70931 deletions

View File

@@ -0,0 +1,107 @@
/**
* landmarkPacketEncoder — Converts a MediaPipe FaceLandmarkerResult into
* the compact BiometricPacket format sent over the WebSocket to FastAPI.
*
* Only the 52 blend shapes relevant to micro-expression analysis are forwarded.
* Raw landmark coordinates are excluded to minimise payload size.
*/
import type { BiometricPacket } from '@/types';
// The MediaPipe canonical blend shape keys we care about for QD scoring.
// These cover eye blinks, smiles, brow raises, and jaw movements.
export const QD_BLEND_SHAPES: readonly string[] = [
'eyeBlinkLeft',
'eyeBlinkRight',
'eyeWideLeft',
'eyeWideRight',
'eyeLookUpLeft',
'eyeLookUpRight',
'eyeLookDownLeft',
'eyeLookDownRight',
'eyeLookInLeft',
'eyeLookInRight',
'eyeLookOutLeft',
'eyeLookOutRight',
'eyeSquintLeft',
'eyeSquintRight',
'browDownLeft',
'browDownRight',
'browInnerUp',
'browOuterUpLeft',
'browOuterUpRight',
'cheekPuff',
'cheekSquintLeft',
'cheekSquintRight',
'noseSneerLeft',
'noseSneerRight',
'mouthSmileLeft',
'mouthSmileRight',
'mouthFrownLeft',
'mouthFrownRight',
'mouthDimpleLeft',
'mouthDimpleRight',
'mouthStretchLeft',
'mouthStretchRight',
'mouthRollLower',
'mouthRollUpper',
'mouthShrugLower',
'mouthShrugUpper',
'mouthPressLeft',
'mouthPressRight',
'mouthLowerDownLeft',
'mouthLowerDownRight',
'mouthUpperUpLeft',
'mouthUpperUpRight',
'jawOpen',
'jawForward',
'jawLeft',
'jawRight',
'mouthClose',
'mouthFunnel',
'mouthPucker',
'mouthLeft',
'mouthRight',
'tongueOut',
];
/**
* Encodes a FaceLandmarkerResult blend shapes array into a compact packet.
*
* @param rawBlendShapes The `faceBlendshapes[0].categories` array from MediaPipe
* @param videoTsMs Current marketing video playback position in milliseconds
* @param leadId The active lead being tracked
* @param sessionId UUID identifying this perception session
*/
export function encodeLandmarkPacket(
rawBlendShapes: Array<{ categoryName: string; score: number }>,
videoTsMs: number,
leadId: string,
sessionId: string,
): BiometricPacket {
const blend_shapes: Record<string, number> = {};
for (const shape of rawBlendShapes) {
if (QD_BLEND_SHAPES.includes(shape.categoryName)) {
// Round to 4dp — sufficient precision, reduces JSON size ~30%
blend_shapes[shape.categoryName] = Math.round(shape.score * 10_000) / 10_000;
}
}
return {
lead_id: leadId,
session_id: sessionId,
video_ts_ms: videoTsMs,
blend_shapes,
};
}
/**
* Returns true if there is meaningful facial expression activity in the packet
* (i.e., at least one key blend shape exceeds the noise threshold).
* Used to skip sending "blank face" packets.
*/
export function hasSignificantActivity(packet: BiometricPacket): boolean {
const KEY_SHAPES = ['mouthSmileLeft', 'mouthSmileRight', 'browInnerUp', 'eyeWideLeft', 'eyeWideRight', 'jawOpen'];
return KEY_SHAPES.some((key) => (packet.blend_shapes[key] ?? 0) > 0.12);
}