@viji-dev/core 0.4.6 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/artist-dts-p5.js +1 -1
- package/dist/artist-dts.js +1 -1
- package/dist/artist-global-p5.d.ts +114 -48
- package/dist/artist-global.d.ts +114 -48
- package/dist/artist-jsdoc.d.ts +2 -6
- package/dist/assets/{viji.worker-BbzNOVhB.js → viji.worker-DwYMDyfQ.js} +539 -170
- package/dist/assets/viji.worker-DwYMDyfQ.js.map +1 -0
- package/dist/docs-api.js +548 -458
- package/dist/{essentia-wasm.web-qCUJ8zjr.js → essentia-wasm.web-x6zu4Vib.js} +2 -2
- package/dist/{essentia-wasm.web-qCUJ8zjr.js.map → essentia-wasm.web-x6zu4Vib.js.map} +1 -1
- package/dist/{index-Oj_9v8r4.js → index-Cqh1k_49.js} +999 -19
- package/dist/index-Cqh1k_49.js.map +1 -0
- package/dist/index.d.ts +571 -48
- package/dist/index.js +1 -1
- package/dist/shader-uniforms.js +10 -0
- package/package.json +1 -1
- package/dist/assets/viji.worker-BbzNOVhB.js.map +0 -1
- package/dist/index-Oj_9v8r4.js.map +0 -1
|
@@ -1104,7 +1104,7 @@ class InteractionSystem {
|
|
|
1104
1104
|
this.previousPointerDown = false;
|
|
1105
1105
|
}
|
|
1106
1106
|
}
|
|
1107
|
-
var cvWorkerCode = "/**\r\n * MediaPipe Tasks Vision Classic Worker\r\n * \r\n * Classic worker for MediaPipe Tasks Vision processing.\r\n * Asset URLs (vision bundle, WASM) are received from CVSystem via the 'init'\r\n * message — no hardcoded paths.\r\n */\r\n\r\n// Debug logging — controlled by CVSystem via 'debug' message\r\nlet DEBUG = false;\r\nfunction log(...args) {\r\n if (DEBUG) {\r\n console.log('🔧 [CV Tasks Worker]', ...args);\r\n }\r\n}\r\n\r\n// Asset config received from CVSystem via init message\r\nlet assetConfig = { wasmUrls: null };\r\n\r\n// Define CommonJS environment for MediaPipe bundle\r\nself.exports = {};\r\nself.module = { exports: {} };\r\n\r\n// MediaPipe model instances\r\nlet faceDetector = null;\r\nlet faceLandmarker = null;\r\nlet gestureRecognizer = null;\r\nlet poseLandmarker = null;\r\nlet imageSegmenter = null;\r\n\r\n// Vision runtime\r\nlet vision = null;\r\nlet isInitialized = false;\r\n\r\n// Active features tracking\r\nconst activeFeatures = new Set();\r\n\r\n// Configuration queue to prevent race conditions\r\nconst configQueue = [];\r\nlet processingConfig = false;\r\n\r\n// Worker health tracking\r\nlet workerHealthy = true;\r\nlet memoryPressureDetected = false;\r\n\r\n// Safe zero-defaults for face data when features are inactive\r\nconst EMPTY_EXPRESSIONS = Object.freeze({\r\n neutral: 0, happy: 0, sad: 0, angry: 0, surprised: 0, disgusted: 0, fearful: 0\r\n});\r\n\r\nconst EMPTY_HEAD_POSE = Object.freeze({ pitch: 0, yaw: 0, roll: 0 });\r\n\r\nconst EMPTY_BLENDSHAPES = Object.freeze({\r\n browDownLeft: 0, browDownRight: 0, browInnerUp: 0, browOuterUpLeft: 0, browOuterUpRight: 0,\r\n cheekPuff: 0, cheekSquintLeft: 0, cheekSquintRight: 0,\r\n eyeBlinkLeft: 0, eyeBlinkRight: 0,\r\n eyeLookDownLeft: 0, eyeLookDownRight: 0, eyeLookInLeft: 0, eyeLookInRight: 0,\r\n eyeLookOutLeft: 0, eyeLookOutRight: 0, eyeLookUpLeft: 0, eyeLookUpRight: 0,\r\n eyeSquintLeft: 0, eyeSquintRight: 0, eyeWideLeft: 0, eyeWideRight: 0,\r\n jawForward: 0, jawLeft: 0, jawOpen: 0, jawRight: 0,\r\n mouthClose: 0, mouthDimpleLeft: 0, mouthDimpleRight: 0,\r\n mouthFrownLeft: 0, mouthFrownRight: 0, mouthFunnel: 0, mouthLeft: 0,\r\n mouthLowerDownLeft: 0, mouthLowerDownRight: 0, mouthPressLeft: 0, mouthPressRight: 0,\r\n mouthPucker: 0, mouthRight: 0, mouthRollLower: 0, mouthRollUpper: 0,\r\n mouthShrugLower: 0, mouthShrugUpper: 0, mouthSmileLeft: 0, mouthSmileRight: 0,\r\n mouthStretchLeft: 0, mouthStretchRight: 0, mouthUpperUpLeft: 0, mouthUpperUpRight: 0,\r\n noseSneerLeft: 0, noseSneerRight: 0, tongueOut: 0\r\n});\r\n\r\n/**\r\n * Convert MediaPipe faceBlendshapes categories array to a flat record\r\n */\r\nfunction buildBlendshapesRecord(categories) {\r\n const record = {};\r\n for (const cat of categories) {\r\n record[cat.categoryName] = cat.score;\r\n }\r\n return record;\r\n}\r\n\r\n/**\r\n * EMFACS-based emotion prototype vectors (Ekman FACS → ARKit blendshapes).\r\n * Weights reflect each blendshape's reliability in MediaPipe's 2D web model.\r\n * Known near-zero blendshapes (cheekSquint*, noseSneer*, eyeWide*) are\r\n * down-weighted and supplemented by correlated signals that do activate.\r\n *\r\n * Reference: Aldenhoven et al. (2026) \"Real-Time Emotion Recognition\r\n * Performance of Mobile Devices\" — EMFACS cosine similarity approach,\r\n * 68.3% accuracy on 7 emotions, exceeding human raters (58.9%).\r\n */\r\nconst EMOTION_PROTOTYPES = {\r\n // mouthSmile is unique to happiness — no other emotion uses it.\r\n // eyeSquint is a secondary \"Duchenne smile\" indicator.\r\n happy: {\r\n mouthSmileLeft: 1.0, mouthSmileRight: 1.0,\r\n eyeSquintLeft: 0.3, eyeSquintRight: 0.3\r\n },\r\n // Pouty/trembling lip: mouthShrugLower (chin raiser) is the primary signal,\r\n // mouthPucker (compressed lips) secondary. Compact prototype so it wins\r\n // over angry when the differentiating upper-face signals are absent.\r\n sad: {\r\n mouthShrugLower: 1.0,\r\n mouthPucker: 0.8\r\n },\r\n // Shares sad's mouth signals at lower weight, differentiated by upper-face\r\n // tension: eyeSquint + browDown. These extra dimensions shift the cosine\r\n // direction away from sad only when genuinely activated.\r\n angry: {\r\n mouthShrugLower: 0.6, mouthPucker: 0.5,\r\n eyeSquintLeft: 1.0, eyeSquintRight: 1.0,\r\n browDownLeft: 1.0, browDownRight: 1.0\r\n },\r\n // Brow raise only — the simplest, most distinctive prototype.\r\n // jawOpen removed to avoid overlap with fearful.\r\n surprised: {\r\n browInnerUp: 1.0,\r\n browOuterUpLeft: 1.0, browOuterUpRight: 1.0\r\n },\r\n // mouthUpperUp (upper lip raise) is the unique primary signal.\r\n // mouthFrown supports, browDown at low weight for wrinkled-brow disgust.\r\n disgusted: {\r\n mouthUpperUpLeft: 1.0, mouthUpperUpRight: 1.0,\r\n mouthFrownLeft: 0.8, mouthFrownRight: 0.8,\r\n browDownLeft: 0.3, browDownRight: 0.3\r\n },\r\n // Shares surprised's brow raise, differentiated by jawOpen (rare in other\r\n // emotions at even 10-20%). jawOpen is the primary differentiator.\r\n fearful: {\r\n browInnerUp: 0.8, browOuterUpLeft: 0.8, browOuterUpRight: 0.8,\r\n jawOpen: 1.0\r\n }\r\n};\r\n\r\nconst PROTOTYPE_KEYS = Object.keys(EMPTY_BLENDSHAPES);\r\n\r\n// Pre-compute prototype magnitudes for cosine similarity\r\nconst PROTOTYPE_MAGNITUDES = {};\r\nfor (const [emotion, proto] of Object.entries(EMOTION_PROTOTYPES)) {\r\n let sumSq = 0;\r\n for (const key of PROTOTYPE_KEYS) {\r\n const v = proto[key] || 0;\r\n sumSq += v * v;\r\n }\r\n PROTOTYPE_MAGNITUDES[emotion] = Math.sqrt(sumSq);\r\n}\r\n\r\n// Noise floor: blendshape values below this are treated as zero to\r\n// prevent resting-state activations from matching emotion prototypes\r\nconst BLENDSHAPE_NOISE_FLOOR = 0.10;\r\n\r\n/**\r\n * Cosine similarity between observed blendshape vector and a prototype.\r\n * cos(v, p) = (v · p) / (|v| * |p|)\r\n * Applies a noise floor to observed values to suppress resting-state noise.\r\n */\r\nfunction emotionCosineSimilarity(observed, prototype, protoMag) {\r\n let dot = 0;\r\n let magO = 0;\r\n for (const key of PROTOTYPE_KEYS) {\r\n const raw = observed[key] || 0;\r\n const o = raw > BLENDSHAPE_NOISE_FLOOR ? raw : 0;\r\n const p = prototype[key] || 0;\r\n dot += o * p;\r\n magO += o * o;\r\n }\r\n magO = Math.sqrt(magO);\r\n if (magO < 1e-8 || protoMag < 1e-8) return 0;\r\n return dot / (magO * protoMag);\r\n}\r\n\r\n// Cross-suppression: when one emotion is confident, competing emotions are\r\n// reduced. Uses raw (pre-suppression) scores so order doesn't matter.\r\n// [suppressor] → { [target]: strength 0-1 }\r\nconst EMOTION_INHIBITIONS = {\r\n happy: { angry: 0.7, sad: 0.5, disgusted: 0.4, fearful: 0.3 },\r\n sad: { happy: 0.3, angry: 0.2 },\r\n angry: { happy: 0.3, sad: 0.2 },\r\n surprised: { angry: 0.3, sad: 0.3 },\r\n disgusted: { happy: 0.4, surprised: 0.2 },\r\n fearful: { happy: 0.3, angry: 0.2 }\r\n};\r\n\r\n/**\r\n * Classify observed blendshapes into emotions using a 3-stage pipeline:\r\n * 1. Cosine similarity against EMFACS prototypes (base scores)\r\n * 2. Key-signal boosters for defining blendshapes (mouthPress → angry)\r\n * 3. Cross-emotion inhibition matrix (happy suppresses angry, etc.)\r\n *\r\n * Returns { neutral, happy, sad, angry, surprised, disgusted, fearful }\r\n */\r\nfunction mapBlendshapesToEmotions(bs) {\r\n const NF = BLENDSHAPE_NOISE_FLOOR;\r\n\r\n // --- Stage 1: Cosine similarity base scores ---\r\n const scores = {};\r\n for (const [emotion, proto] of Object.entries(EMOTION_PROTOTYPES)) {\r\n scores[emotion] = Math.max(0, emotionCosineSimilarity(bs, proto, PROTOTYPE_MAGNITUDES[emotion]));\r\n }\r\n\r\n // --- Stage 2: Key-signal boosters ---\r\n // mouthPress is a defining angry signal not in the prototype (to avoid\r\n // resting-state contamination) but boosts angry when clearly present\r\n const mouthPress = Math.max(0,\r\n ((bs.mouthPressLeft || 0) + (bs.mouthPressRight || 0)) / 2 - NF);\r\n if (mouthPress > 0) {\r\n scores.angry = Math.min(1, scores.angry + mouthPress * 0.3);\r\n }\r\n\r\n // --- Stage 3: Cross-emotion inhibition ---\r\n // Snapshot raw scores so suppression is non-circular\r\n const raw = {};\r\n for (const key in scores) raw[key] = scores[key];\r\n\r\n for (const [suppressor, targets] of Object.entries(EMOTION_INHIBITIONS)) {\r\n const suppressorScore = raw[suppressor] || 0;\r\n if (suppressorScore > 0.1) {\r\n for (const [target, strength] of Object.entries(targets)) {\r\n scores[target] *= (1 - suppressorScore * strength);\r\n }\r\n }\r\n }\r\n\r\n // --- Neutral: dominant when no emotion is confident ---\r\n let maxScore = 0;\r\n for (const emotion of Object.keys(EMOTION_PROTOTYPES)) {\r\n if (scores[emotion] > maxScore) maxScore = scores[emotion];\r\n }\r\n const neutralThreshold = 0.35;\r\n scores.neutral = maxScore < neutralThreshold ? 1.0 : Math.max(0, 1.0 - maxScore * 1.5);\r\n\r\n return {\r\n neutral: scores.neutral,\r\n happy: scores.happy || 0,\r\n sad: scores.sad || 0,\r\n angry: scores.angry || 0,\r\n surprised: scores.surprised || 0,\r\n disgusted: scores.disgusted || 0,\r\n fearful: scores.fearful || 0\r\n };\r\n}\r\n\r\n/**\r\n * Compute head pose (pitch, yaw, roll in degrees) from 468 face landmarks.\r\n * Uses nose tip, chin, eye corners, and forehead to derive 3D orientation.\r\n */\r\nfunction computeHeadPoseFromLandmarks(landmarks) {\r\n // Key landmark indices (MediaPipe FaceMesh)\r\n const noseTip = landmarks[1];\r\n const chin = landmarks[152];\r\n const leftEye = landmarks[33];\r\n const rightEye = landmarks[263];\r\n const forehead = landmarks[10];\r\n\r\n if (!noseTip || !chin || !leftEye || !rightEye || !forehead) {\r\n return { pitch: 0, yaw: 0, roll: 0 };\r\n }\r\n\r\n // Yaw: horizontal angle from eye midpoint to nose tip\r\n const eyeMidX = (leftEye.x + rightEye.x) / 2;\r\n const eyeMidY = (leftEye.y + rightEye.y) / 2;\r\n const yaw = Math.atan2(noseTip.x - eyeMidX, Math.abs(noseTip.z - ((leftEye.z + rightEye.z) / 2 || 0)) + 0.001) * (180 / Math.PI);\r\n\r\n // Pitch: vertical angle from forehead to chin through nose\r\n const faceVerticalLen = Math.sqrt((chin.x - forehead.x) ** 2 + (chin.y - forehead.y) ** 2) || 0.001;\r\n const noseRelY = (noseTip.y - forehead.y) / faceVerticalLen;\r\n const pitch = (noseRelY - 0.5) * 180;\r\n\r\n // Roll: tilt from horizontal eye line\r\n const roll = Math.atan2(rightEye.y - leftEye.y, rightEye.x - leftEye.x) * (180 / Math.PI);\r\n\r\n return {\r\n pitch: isNaN(pitch) ? 0 : Math.max(-90, Math.min(90, pitch)),\r\n yaw: isNaN(yaw) ? 0 : Math.max(-90, Math.min(90, yaw)),\r\n roll: isNaN(roll) ? 0 : Math.max(-180, Math.min(180, roll))\r\n };\r\n}\r\n\r\n/**\r\n * Detect WASM SIMD support at runtime.\r\n * Uses the standard test: validate a minimal SIMD module.\r\n */\r\nfunction detectSIMDSupport() {\r\n try {\r\n return WebAssembly.validate(new Uint8Array([\r\n 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123,\r\n 3, 2, 1, 0, 10, 10, 1, 8, 0, 65, 0, 253, 15, 253, 98, 11\r\n ]));\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Initialize MediaPipe Tasks Vision runtime.\r\n *\r\n * Constructs a WasmFileset manually from individual URLs (bypassing\r\n * FilesetResolver) so that the consumer's bundler-resolved URLs are\r\n * used directly. Picks the SIMD or non-SIMD variant at runtime.\r\n */\r\nasync function initializeVision() {\r\n if (isInitialized) {\r\n log('Vision already initialized, skipping');\r\n return;\r\n }\r\n \r\n if (!assetConfig.wasmUrls) {\r\n throw new Error('WASM URLs not set — init message must be received before initializeVision()');\r\n }\r\n \r\n try {\r\n log('Starting MediaPipe Tasks Vision initialization...');\r\n \r\n const simd = detectSIMDSupport();\r\n log('WASM SIMD support:', simd);\r\n\r\n const wasmFileset = simd\r\n ? { wasmLoaderPath: assetConfig.wasmUrls.simdLoaderJs, wasmBinaryPath: assetConfig.wasmUrls.simdBinary }\r\n : { wasmLoaderPath: assetConfig.wasmUrls.nosimdLoaderJs, wasmBinaryPath: assetConfig.wasmUrls.nosimdBinary };\r\n\r\n log('Using WASM fileset:', wasmFileset);\r\n\r\n vision = wasmFileset;\r\n \r\n isInitialized = true;\r\n log('✅ MediaPipe Tasks Vision initialized successfully');\r\n } catch (error) {\r\n log('❌ Failed to initialize MediaPipe Tasks Vision:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load and initialize Face Detection\r\n */\r\nasync function initializeFaceDetection() {\r\n if (faceDetector) return;\r\n \r\n // Ensure vision runtime is initialized first\r\n await initializeVision();\r\n \r\n try {\r\n log('Loading Face Detector...');\r\n \r\n const options = {\r\n baseOptions: {\r\n modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/face_detector/blaze_face_short_range/float16/1/blaze_face_short_range.tflite',\r\n delegate: 'GPU'\r\n },\r\n runningMode: 'VIDEO',\r\n minDetectionConfidence: 0.5,\r\n minSuppressionThreshold: 0.3\r\n };\r\n \r\n const FaceDetector = self.FaceDetector || self.module.exports.FaceDetector || self.exports.FaceDetector;\r\n faceDetector = await FaceDetector.createFromOptions(vision, options);\r\n log('✅ Face Detector loaded');\r\n } catch (error) {\r\n log('❌ Failed to load Face Detector:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load and initialize Face Landmarks\r\n */\r\nasync function initializeFaceLandmarks() {\r\n if (faceLandmarker) return;\r\n \r\n // Ensure vision runtime is initialized first\r\n await initializeVision();\r\n \r\n try {\r\n log('Loading Face Landmarker...');\r\n \r\n const options = {\r\n baseOptions: {\r\n modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task',\r\n delegate: 'GPU'\r\n },\r\n runningMode: 'VIDEO',\r\n numFaces: 1,\r\n outputFaceBlendshapes: true\r\n };\r\n \r\n const FaceLandmarker = self.FaceLandmarker || self.module.exports.FaceLandmarker || self.exports.FaceLandmarker;\r\n faceLandmarker = await FaceLandmarker.createFromOptions(vision, options);\r\n log('✅ Face Landmarker loaded (blendshapes enabled)');\r\n } catch (error) {\r\n log('❌ Failed to load Face Landmarker:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load and initialize Hand Tracking via GestureRecognizer\r\n * (provides landmarks + handedness + ML-based gesture classification in one call)\r\n */\r\nasync function initializeHandTracking() {\r\n if (gestureRecognizer) return;\r\n \r\n await initializeVision();\r\n \r\n try {\r\n log('Loading Gesture Recognizer...');\r\n \r\n const options = {\r\n baseOptions: {\r\n modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/gesture_recognizer/gesture_recognizer/float16/1/gesture_recognizer.task',\r\n delegate: 'GPU'\r\n },\r\n runningMode: 'VIDEO',\r\n numHands: 2\r\n };\r\n \r\n const GestureRecognizer = self.GestureRecognizer || self.module.exports.GestureRecognizer || self.exports.GestureRecognizer;\r\n gestureRecognizer = await GestureRecognizer.createFromOptions(vision, options);\r\n log('✅ Gesture Recognizer loaded');\r\n } catch (error) {\r\n log('❌ Failed to load Gesture Recognizer:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load and initialize Pose Detection\r\n */\r\nasync function initializePoseDetection() {\r\n if (poseLandmarker) return;\r\n \r\n // Ensure vision runtime is initialized first\r\n await initializeVision();\r\n \r\n try {\r\n log('Loading Pose Landmarker...');\r\n \r\n const options = {\r\n baseOptions: {\r\n modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task',\r\n delegate: 'GPU'\r\n },\r\n runningMode: 'VIDEO',\r\n numPoses: 1\r\n };\r\n \r\n const PoseLandmarker = self.PoseLandmarker || self.module.exports.PoseLandmarker || self.exports.PoseLandmarker;\r\n poseLandmarker = await PoseLandmarker.createFromOptions(vision, options);\r\n log('✅ Pose Landmarker loaded');\r\n } catch (error) {\r\n log('❌ Failed to load Pose Landmarker:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load and initialize Body Segmentation\r\n */\r\nasync function initializeBodySegmentation() {\r\n if (imageSegmenter) return;\r\n \r\n // Ensure vision runtime is initialized first\r\n await initializeVision();\r\n \r\n try {\r\n log('Loading Image Segmenter...');\r\n \r\n const options = {\r\n baseOptions: {\r\n modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/image_segmenter/selfie_segmenter/float16/1/selfie_segmenter.tflite',\r\n delegate: 'GPU'\r\n },\r\n runningMode: 'IMAGE',\r\n outputCategoryMask: true,\r\n outputConfidenceMasks: false\r\n };\r\n \r\n const ImageSegmenter = self.ImageSegmenter || self.module.exports.ImageSegmenter || self.exports.ImageSegmenter;\r\n imageSegmenter = await ImageSegmenter.createFromOptions(vision, options);\r\n log('✅ Image Segmenter loaded');\r\n } catch (error) {\r\n log('❌ Failed to load Image Segmenter:', error);\r\n throw error;\r\n }\r\n}\r\n\r\nfunction computeHandBounds(landmarks) {\r\n let minX = 1, minY = 1, maxX = 0, maxY = 0;\r\n for (const p of landmarks) {\r\n if (p.x < minX) minX = p.x;\r\n if (p.y < minY) minY = p.y;\r\n if (p.x > maxX) maxX = p.x;\r\n if (p.y > maxY) maxY = p.y;\r\n }\r\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\r\n}\r\n\r\n// Map MediaPipe GestureRecognizer category names to our API field names\r\nconst GESTURE_NAME_MAP = {\r\n 'Closed_Fist': 'fist',\r\n 'Open_Palm': 'openPalm',\r\n 'Victory': 'peace',\r\n 'Thumb_Up': 'thumbsUp',\r\n 'Pointing_Up': 'pointing',\r\n 'Thumb_Down': 'thumbsDown',\r\n 'ILoveYou': 'iLoveYou'\r\n};\r\n\r\nfunction mapGestures(gestureCategories) {\r\n const result = { fist: 0, openPalm: 0, peace: 0, thumbsUp: 0, pointing: 0, thumbsDown: 0, iLoveYou: 0 };\r\n if (!gestureCategories) return result;\r\n for (const cat of gestureCategories) {\r\n const key = GESTURE_NAME_MAP[cat.categoryName];\r\n if (key) result[key] = cat.score;\r\n }\r\n return result;\r\n}\r\n\r\n// BlazePose landmark index groups for named body parts\r\nconst POSE_FACE_INDICES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\r\nconst POSE_TORSO_INDICES = [11, 12, 23, 24];\r\nconst POSE_LEFT_ARM_INDICES = [11, 13, 15];\r\nconst POSE_RIGHT_ARM_INDICES = [12, 14, 16];\r\nconst POSE_LEFT_LEG_INDICES = [23, 25, 27, 29, 31];\r\nconst POSE_RIGHT_LEG_INDICES = [24, 26, 28, 30, 32];\r\n\r\nfunction extractPoseGroup(landmarks, indices) {\r\n return indices.map(i => {\r\n const lm = landmarks[i];\r\n return lm ? { x: lm.x, y: lm.y } : { x: 0, y: 0 };\r\n });\r\n}\r\n\r\nfunction computePoseConfidence(landmarks) {\r\n let sum = 0;\r\n for (const lm of landmarks) sum += (lm.visibility || 0);\r\n return landmarks.length > 0 ? sum / landmarks.length : 0;\r\n}\r\n\r\n/**\r\n * Process video frame with active CV features\r\n * @param {ImageData|ImageBitmap} imageInput - Image input (ImageData or ImageBitmap)\r\n * @param {number} timestamp - Frame timestamp \r\n * @param {string[]} features - Active CV features\r\n */\r\nasync function processFrame(imageInput, timestamp, features) {\r\n const results = {};\r\n \r\n try {\r\n // Process face detection\r\n if (features.includes('faceDetection') && faceDetector) {\r\n const detectionResult = faceDetector.detectForVideo(imageInput, timestamp);\r\n results.faces = detectionResult.detections.map((detection, index) => ({\r\n id: index,\r\n bounds: {\r\n x: detection.boundingBox.originX / imageInput.width,\r\n y: detection.boundingBox.originY / imageInput.height,\r\n width: detection.boundingBox.width / imageInput.width,\r\n height: detection.boundingBox.height / imageInput.height\r\n },\r\n center: {\r\n x: (detection.boundingBox.originX + detection.boundingBox.width / 2) / imageInput.width,\r\n y: (detection.boundingBox.originY + detection.boundingBox.height / 2) / imageInput.height\r\n },\r\n landmarks: [],\r\n expressions: EMPTY_EXPRESSIONS,\r\n headPose: EMPTY_HEAD_POSE,\r\n blendshapes: EMPTY_BLENDSHAPES,\r\n confidence: detection.categories[0]?.score || 0\r\n }));\r\n }\r\n \r\n // Process face landmarks (used by faceMesh and emotionDetection)\r\n if ((features.includes('faceMesh') || features.includes('emotionDetection')) && faceLandmarker) {\r\n const landmarkResult = faceLandmarker.detectForVideo(imageInput, timestamp);\r\n if (landmarkResult.faceLandmarks.length > 0) {\r\n const landmarks = landmarkResult.faceLandmarks[0];\r\n \r\n if (!results.faces) {\r\n results.faces = [{\r\n id: 0,\r\n bounds: null,\r\n center: null,\r\n landmarks: [],\r\n expressions: EMPTY_EXPRESSIONS,\r\n headPose: EMPTY_HEAD_POSE,\r\n blendshapes: EMPTY_BLENDSHAPES,\r\n confidence: 0.8\r\n }];\r\n }\r\n \r\n const mappedLandmarks = landmarks.map((landmark) => ({\r\n x: landmark.x,\r\n y: landmark.y,\r\n z: landmark.z || 0\r\n }));\r\n\r\n if (results.faces[0]) {\r\n results.faces[0].landmarks = mappedLandmarks;\r\n results.faces[0].headPose = computeHeadPoseFromLandmarks(landmarks);\r\n\r\n if (features.includes('emotionDetection') &&\r\n landmarkResult.faceBlendshapes &&\r\n landmarkResult.faceBlendshapes.length > 0) {\r\n const bs = buildBlendshapesRecord(landmarkResult.faceBlendshapes[0].categories);\r\n results.faces[0].blendshapes = bs;\r\n results.faces[0].expressions = mapBlendshapesToEmotions(bs);\r\n }\r\n }\r\n } else if (!results.faces) {\r\n results.faces = [];\r\n }\r\n }\r\n \r\n // Process hand tracking (GestureRecognizer provides landmarks + gestures in one call)\r\n if (features.includes('handTracking') && gestureRecognizer) {\r\n const handResult = gestureRecognizer.recognizeForVideo(imageInput, timestamp);\r\n results.hands = handResult.landmarks.map((landmarks, index) => {\r\n const mapped = landmarks.map((landmark) => ({\r\n x: landmark.x,\r\n y: landmark.y,\r\n z: landmark.z || 0\r\n }));\r\n\r\n const rawHandedness = handResult.handednesses[index]?.[0]?.categoryName || 'unknown';\r\n\r\n return {\r\n id: index,\r\n handedness: rawHandedness.toLowerCase(),\r\n confidence: handResult.handednesses[index]?.[0]?.score || 0,\r\n bounds: computeHandBounds(mapped),\r\n landmarks: mapped,\r\n palm: mapped[9],\r\n gestures: mapGestures(handResult.gestures[index])\r\n };\r\n });\r\n }\r\n \r\n // Process pose detection\r\n if (features.includes('poseDetection') && poseLandmarker) {\r\n const poseResult = poseLandmarker.detectForVideo(imageInput, timestamp);\r\n if (poseResult.landmarks.length > 0) {\r\n const poseLandmarks = poseResult.landmarks[0].map((landmark) => ({\r\n x: landmark.x,\r\n y: landmark.y,\r\n z: landmark.z || 0,\r\n visibility: landmark.visibility || 1\r\n }));\r\n\r\n results.pose = {\r\n confidence: computePoseConfidence(poseLandmarks),\r\n landmarks: poseLandmarks,\r\n face: extractPoseGroup(poseLandmarks, POSE_FACE_INDICES),\r\n torso: extractPoseGroup(poseLandmarks, POSE_TORSO_INDICES),\r\n leftArm: extractPoseGroup(poseLandmarks, POSE_LEFT_ARM_INDICES),\r\n rightArm: extractPoseGroup(poseLandmarks, POSE_RIGHT_ARM_INDICES),\r\n leftLeg: extractPoseGroup(poseLandmarks, POSE_LEFT_LEG_INDICES),\r\n rightLeg: extractPoseGroup(poseLandmarks, POSE_RIGHT_LEG_INDICES),\r\n worldLandmarks: poseResult.worldLandmarks?.[0]?.map((landmark) => ({\r\n x: landmark.x,\r\n y: landmark.y,\r\n z: landmark.z || 0,\r\n visibility: landmark.visibility || 1\r\n })) || []\r\n };\r\n } else {\r\n results.pose = null;\r\n }\r\n }\r\n \r\n // Process body segmentation\r\n if (features.includes('bodySegmentation') && imageSegmenter) {\r\n const segmentResult = imageSegmenter.segment(imageInput);\r\n if (segmentResult.categoryMask) {\r\n try {\r\n results.segmentation = {\r\n mask: segmentResult.categoryMask.getAsUint8Array(),\r\n width: segmentResult.categoryMask.width,\r\n height: segmentResult.categoryMask.height\r\n };\r\n log('Segmentation mask:', results.segmentation.width, 'x', results.segmentation.height);\r\n } finally {\r\n segmentResult.categoryMask.close();\r\n }\r\n } else {\r\n results.segmentation = null;\r\n }\r\n }\r\n \r\n return results;\r\n } catch (error) {\r\n log('❌ Error processing frame:', error);\r\n return {};\r\n }\r\n}\r\n\r\n// Note: Removed reusable canvas functions - no longer needed with direct ImageBitmap processing!\r\n\r\n/**\r\n * Clean up WASM instance with proper memory management\r\n */\r\nfunction cleanupWasmInstance(instance, featureName) {\r\n if (instance) {\r\n try {\r\n log(`🧹 Cleaning up ${featureName} WASM instance...`);\r\n instance.close();\r\n \r\n // Force garbage collection if available (Chrome DevTools)\r\n if (typeof gc === 'function') {\r\n gc();\r\n }\r\n \r\n // Give time for WASM cleanup\r\n return new Promise(resolve => {\r\n setTimeout(resolve, 100);\r\n });\r\n } catch (error) {\r\n log(`⚠️ Error cleaning up ${featureName}:`, error);\r\n }\r\n }\r\n return Promise.resolve();\r\n}\r\n\r\n/**\r\n * Process configuration queue sequentially\r\n */\r\nasync function processConfigQueue() {\r\n if (processingConfig || configQueue.length === 0) return;\r\n \r\n processingConfig = true;\r\n \r\n try {\r\n while (configQueue.length > 0) {\r\n const { features, resolve, reject } = configQueue.shift();\r\n \r\n try {\r\n await handleConfigUpdateInternal(features);\r\n resolve({ configured: true, activeFeatures: Array.from(activeFeatures) });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n }\r\n } finally {\r\n processingConfig = false;\r\n }\r\n}\r\n\r\n/**\r\n * Queue configuration update to prevent race conditions\r\n */\r\nfunction queueConfigUpdate(features) {\r\n return new Promise((resolve, reject) => {\r\n configQueue.push({ features, resolve, reject });\r\n processConfigQueue();\r\n });\r\n}\r\n\r\n/**\r\n * Handle feature configuration updates (internal)\r\n */\r\nasync function handleConfigUpdateInternal(features) {\r\n if (!workerHealthy) {\r\n throw new Error('Worker is in unhealthy state, restart required');\r\n }\r\n \r\n const newFeatures = new Set(features);\r\n const toEnable = features.filter(f => !activeFeatures.has(f));\r\n const toDisable = Array.from(activeFeatures).filter(f => !newFeatures.has(f));\r\n \r\n log(`🔄 Config update: enable [${toEnable.join(', ')}], disable [${toDisable.join(', ')}]`);\r\n \r\n // Disable unused features first (cleanup instances)\r\n const cleanupPromises = [];\r\n for (const feature of toDisable) {\r\n switch (feature) {\r\n case 'faceDetection':\r\n cleanupPromises.push(cleanupWasmInstance(faceDetector, 'FaceDetector'));\r\n faceDetector = null;\r\n break;\r\n case 'faceMesh':\r\n // Only teardown FaceLandmarker if emotionDetection also not active\r\n if (!newFeatures.has('emotionDetection')) {\r\n cleanupPromises.push(cleanupWasmInstance(faceLandmarker, 'FaceLandmarker'));\r\n faceLandmarker = null;\r\n }\r\n break;\r\n case 'emotionDetection':\r\n // Only teardown FaceLandmarker if faceMesh also not active\r\n if (!newFeatures.has('faceMesh')) {\r\n cleanupPromises.push(cleanupWasmInstance(faceLandmarker, 'FaceLandmarker'));\r\n faceLandmarker = null;\r\n }\r\n break;\r\n case 'handTracking':\r\n cleanupPromises.push(cleanupWasmInstance(gestureRecognizer, 'GestureRecognizer'));\r\n gestureRecognizer = null;\r\n break;\r\n case 'poseDetection':\r\n cleanupPromises.push(cleanupWasmInstance(poseLandmarker, 'PoseLandmarker'));\r\n poseLandmarker = null;\r\n break;\r\n case 'bodySegmentation':\r\n cleanupPromises.push(cleanupWasmInstance(imageSegmenter, 'ImageSegmenter'));\r\n imageSegmenter = null;\r\n break;\r\n }\r\n activeFeatures.delete(feature);\r\n log(`🗑️ Disabled feature: ${feature}`);\r\n }\r\n \r\n // Wait for all cleanup to complete\r\n if (cleanupPromises.length > 0) {\r\n await Promise.all(cleanupPromises);\r\n log('✅ All cleanup completed');\r\n }\r\n \r\n // Note: No canvas cleanup needed - using direct ImageBitmap processing!\r\n \r\n // Enable new features\r\n for (const feature of toEnable) {\r\n try {\r\n switch (feature) {\r\n case 'faceDetection':\r\n await initializeFaceDetection();\r\n break;\r\n case 'faceMesh':\r\n case 'emotionDetection':\r\n // Both share the FaceLandmarker (with blendshapes enabled)\r\n await initializeFaceLandmarks();\r\n break;\r\n case 'handTracking':\r\n await initializeHandTracking();\r\n break;\r\n case 'poseDetection':\r\n await initializePoseDetection();\r\n break;\r\n case 'bodySegmentation':\r\n await initializeBodySegmentation();\r\n break;\r\n }\r\n activeFeatures.add(feature);\r\n log(`✅ Enabled feature: ${feature}`);\r\n } catch (error) {\r\n log(`❌ Failed to enable feature ${feature}:`, error);\r\n \r\n // Check if this is a memory error\r\n if (error.message && error.message.includes('Out of memory')) {\r\n memoryPressureDetected = true;\r\n workerHealthy = false;\r\n throw new Error(`Memory exhausted while enabling ${feature}. Worker restart required.`);\r\n }\r\n \r\n throw error;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Legacy function for backward compatibility\r\n */\r\nasync function handleConfigUpdate(features) {\r\n return await queueConfigUpdate(features);\r\n}\r\n\r\n// Message handler. Every request carries a monotonic `requestId`; we echo it\r\n// back on every `result` post so the host can correlate responses to requests.\r\nself.onmessage = async (event) => {\r\n const message = event.data;\r\n const requestId = message.requestId;\r\n\r\n // Only log non-process messages to avoid per-frame spam\r\n if (message.type !== 'process') {\r\n log('Received message:', message.type, 'requestId:', requestId);\r\n }\r\n\r\n try {\r\n switch (message.type) {\r\n case 'debug': {\r\n DEBUG = !!message.enabled;\r\n log('Debug mode', DEBUG ? 'enabled' : 'disabled');\r\n break;\r\n }\r\n\r\n case 'init': {\r\n log('Received init message');\r\n\r\n const visionCode = message.visionBundleCode;\r\n assetConfig.wasmUrls = message.wasmUrls || null;\r\n\r\n if (!visionCode || !assetConfig.wasmUrls) {\r\n throw new Error('init message must include visionBundleCode and wasmUrls');\r\n }\r\n\r\n log('WASM URLs received:', Object.keys(assetConfig.wasmUrls));\r\n\r\n try {\r\n (0, eval)(visionCode);\r\n log('vision_bundle executed successfully (inlined code)');\r\n } catch (error) {\r\n log('❌ Failed to execute vision_bundle:', error);\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: false,\r\n error: 'Failed to execute vision bundle: ' + error.message,\r\n restartRequired: true\r\n });\r\n break;\r\n }\r\n\r\n try {\r\n await initializeVision();\r\n log('Vision runtime ready for feature loading');\r\n } catch (error) {\r\n log('❌ Vision runtime initialization failed:', error);\r\n throw error;\r\n }\r\n\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: true,\r\n data: { initialized: true }\r\n });\r\n break;\r\n }\r\n\r\n case 'config': {\r\n log('Received config message:', message.features);\r\n\r\n try {\r\n const result = await handleConfigUpdate(message.features);\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: true,\r\n data: result\r\n });\r\n } catch (error) {\r\n log('❌ Config update failed:', error);\r\n\r\n // Check if worker needs restart\r\n if (!workerHealthy || memoryPressureDetected) {\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: false,\r\n error: error.message,\r\n restartRequired: true\r\n });\r\n } else {\r\n throw error; // Re-throw for normal error handling\r\n }\r\n }\r\n break;\r\n }\r\n\r\n case 'process': {\r\n try {\r\n // 🚀 OPTIMIZED: Pass ImageBitmap directly to MediaPipe (no conversion!)\r\n const results = await processFrame(message.bitmap, message.timestamp, message.features);\r\n\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: true,\r\n data: results\r\n });\r\n } finally {\r\n // Clean up ImageBitmap after processing\r\n if (message.bitmap && typeof message.bitmap.close === 'function') {\r\n message.bitmap.close();\r\n }\r\n }\r\n break;\r\n }\r\n\r\n default:\r\n log('❌ Unknown message type:', message.type);\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: false,\r\n error: `Unknown message type: ${message.type}`\r\n });\r\n }\r\n } catch (error) {\r\n log('❌ Error handling message:', error);\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: false,\r\n error: error instanceof Error ? error.message : String(error)\r\n });\r\n }\r\n};\r\n\r\nlog('CV Tasks Worker loaded — waiting for init message with inlined code and WASM URLs');\r\n";
|
|
1107
|
+
var cvWorkerCode = "/**\r\n * MediaPipe Tasks Vision Classic Worker\r\n * \r\n * Classic worker for MediaPipe Tasks Vision processing.\r\n * Asset URLs (vision bundle, WASM) are received from CVSystem via the 'init'\r\n * message — no hardcoded paths.\r\n */\r\n\r\n// Debug logging — controlled by CVSystem via 'debug' message\r\nlet DEBUG = false;\r\nfunction log(...args) {\r\n if (DEBUG) {\r\n console.log('🔧 [CV Tasks Worker]', ...args);\r\n }\r\n}\r\n\r\n// Asset config received from CVSystem via init message\r\nlet assetConfig = { wasmUrls: null };\r\n\r\n// Define CommonJS environment for MediaPipe bundle\r\nself.exports = {};\r\nself.module = { exports: {} };\r\n\r\n// MediaPipe model instances\r\nlet faceDetector = null;\r\nlet faceLandmarker = null;\r\nlet gestureRecognizer = null;\r\nlet poseLandmarker = null;\r\nlet imageSegmenter = null;\r\n\r\n// Vision runtime\r\nlet vision = null;\r\nlet isInitialized = false;\r\n\r\n// Active features tracking\r\nconst activeFeatures = new Set();\r\n\r\n// Configuration queue to prevent race conditions\r\nconst configQueue = [];\r\nlet processingConfig = false;\r\n\r\n// Worker health tracking\r\nlet workerHealthy = true;\r\nlet memoryPressureDetected = false;\r\n\r\n// Safe zero-defaults for face data when features are inactive\r\nconst EMPTY_EXPRESSIONS = Object.freeze({\r\n neutral: 0, happy: 0, sad: 0, angry: 0, surprised: 0, disgusted: 0, fearful: 0\r\n});\r\n\r\nconst EMPTY_HEAD_POSE = Object.freeze({ pitch: 0, yaw: 0, roll: 0 });\r\n\r\nconst EMPTY_BLENDSHAPES = Object.freeze({\r\n browDownLeft: 0, browDownRight: 0, browInnerUp: 0, browOuterUpLeft: 0, browOuterUpRight: 0,\r\n cheekPuff: 0, cheekSquintLeft: 0, cheekSquintRight: 0,\r\n eyeBlinkLeft: 0, eyeBlinkRight: 0,\r\n eyeLookDownLeft: 0, eyeLookDownRight: 0, eyeLookInLeft: 0, eyeLookInRight: 0,\r\n eyeLookOutLeft: 0, eyeLookOutRight: 0, eyeLookUpLeft: 0, eyeLookUpRight: 0,\r\n eyeSquintLeft: 0, eyeSquintRight: 0, eyeWideLeft: 0, eyeWideRight: 0,\r\n jawForward: 0, jawLeft: 0, jawOpen: 0, jawRight: 0,\r\n mouthClose: 0, mouthDimpleLeft: 0, mouthDimpleRight: 0,\r\n mouthFrownLeft: 0, mouthFrownRight: 0, mouthFunnel: 0, mouthLeft: 0,\r\n mouthLowerDownLeft: 0, mouthLowerDownRight: 0, mouthPressLeft: 0, mouthPressRight: 0,\r\n mouthPucker: 0, mouthRight: 0, mouthRollLower: 0, mouthRollUpper: 0,\r\n mouthShrugLower: 0, mouthShrugUpper: 0, mouthSmileLeft: 0, mouthSmileRight: 0,\r\n mouthStretchLeft: 0, mouthStretchRight: 0, mouthUpperUpLeft: 0, mouthUpperUpRight: 0,\r\n noseSneerLeft: 0, noseSneerRight: 0, tongueOut: 0\r\n});\r\n\r\n/**\r\n * Convert MediaPipe faceBlendshapes categories array to a flat record\r\n */\r\nfunction buildBlendshapesRecord(categories) {\r\n const record = {};\r\n for (const cat of categories) {\r\n record[cat.categoryName] = cat.score;\r\n }\r\n return record;\r\n}\r\n\r\n/**\r\n * EMFACS-based emotion prototype vectors (Ekman FACS → ARKit blendshapes).\r\n * Weights reflect each blendshape's reliability in MediaPipe's 2D web model.\r\n * Known near-zero blendshapes (cheekSquint*, noseSneer*, eyeWide*) are\r\n * down-weighted and supplemented by correlated signals that do activate.\r\n *\r\n * Reference: Aldenhoven et al. (2026) \"Real-Time Emotion Recognition\r\n * Performance of Mobile Devices\" — EMFACS cosine similarity approach,\r\n * 68.3% accuracy on 7 emotions, exceeding human raters (58.9%).\r\n */\r\nconst EMOTION_PROTOTYPES = {\r\n // mouthSmile is unique to happiness — no other emotion uses it.\r\n // eyeSquint is a secondary \"Duchenne smile\" indicator.\r\n happy: {\r\n mouthSmileLeft: 1.0, mouthSmileRight: 1.0,\r\n eyeSquintLeft: 0.3, eyeSquintRight: 0.3\r\n },\r\n // Pouty/trembling lip: mouthShrugLower (chin raiser) is the primary signal,\r\n // mouthPucker (compressed lips) secondary. Compact prototype so it wins\r\n // over angry when the differentiating upper-face signals are absent.\r\n sad: {\r\n mouthShrugLower: 1.0,\r\n mouthPucker: 0.8\r\n },\r\n // Shares sad's mouth signals at lower weight, differentiated by upper-face\r\n // tension: eyeSquint + browDown. These extra dimensions shift the cosine\r\n // direction away from sad only when genuinely activated.\r\n angry: {\r\n mouthShrugLower: 0.6, mouthPucker: 0.5,\r\n eyeSquintLeft: 1.0, eyeSquintRight: 1.0,\r\n browDownLeft: 1.0, browDownRight: 1.0\r\n },\r\n // Brow raise only — the simplest, most distinctive prototype.\r\n // jawOpen removed to avoid overlap with fearful.\r\n surprised: {\r\n browInnerUp: 1.0,\r\n browOuterUpLeft: 1.0, browOuterUpRight: 1.0\r\n },\r\n // mouthUpperUp (upper lip raise) is the unique primary signal.\r\n // mouthFrown supports, browDown at low weight for wrinkled-brow disgust.\r\n disgusted: {\r\n mouthUpperUpLeft: 1.0, mouthUpperUpRight: 1.0,\r\n mouthFrownLeft: 0.8, mouthFrownRight: 0.8,\r\n browDownLeft: 0.3, browDownRight: 0.3\r\n },\r\n // Shares surprised's brow raise, differentiated by jawOpen (rare in other\r\n // emotions at even 10-20%). jawOpen is the primary differentiator.\r\n fearful: {\r\n browInnerUp: 0.8, browOuterUpLeft: 0.8, browOuterUpRight: 0.8,\r\n jawOpen: 1.0\r\n }\r\n};\r\n\r\nconst PROTOTYPE_KEYS = Object.keys(EMPTY_BLENDSHAPES);\r\n\r\n// Pre-compute prototype magnitudes for cosine similarity\r\nconst PROTOTYPE_MAGNITUDES = {};\r\nfor (const [emotion, proto] of Object.entries(EMOTION_PROTOTYPES)) {\r\n let sumSq = 0;\r\n for (const key of PROTOTYPE_KEYS) {\r\n const v = proto[key] || 0;\r\n sumSq += v * v;\r\n }\r\n PROTOTYPE_MAGNITUDES[emotion] = Math.sqrt(sumSq);\r\n}\r\n\r\n// Noise floor: blendshape values below this are treated as zero to\r\n// prevent resting-state activations from matching emotion prototypes\r\nconst BLENDSHAPE_NOISE_FLOOR = 0.10;\r\n\r\n/**\r\n * Cosine similarity between observed blendshape vector and a prototype.\r\n * cos(v, p) = (v · p) / (|v| * |p|)\r\n * Applies a noise floor to observed values to suppress resting-state noise.\r\n */\r\nfunction emotionCosineSimilarity(observed, prototype, protoMag) {\r\n let dot = 0;\r\n let magO = 0;\r\n for (const key of PROTOTYPE_KEYS) {\r\n const raw = observed[key] || 0;\r\n const o = raw > BLENDSHAPE_NOISE_FLOOR ? raw : 0;\r\n const p = prototype[key] || 0;\r\n dot += o * p;\r\n magO += o * o;\r\n }\r\n magO = Math.sqrt(magO);\r\n if (magO < 1e-8 || protoMag < 1e-8) return 0;\r\n return dot / (magO * protoMag);\r\n}\r\n\r\n// Cross-suppression: when one emotion is confident, competing emotions are\r\n// reduced. Uses raw (pre-suppression) scores so order doesn't matter.\r\n// [suppressor] → { [target]: strength 0-1 }\r\nconst EMOTION_INHIBITIONS = {\r\n happy: { angry: 0.7, sad: 0.5, disgusted: 0.4, fearful: 0.3 },\r\n sad: { happy: 0.3, angry: 0.2 },\r\n angry: { happy: 0.3, sad: 0.2 },\r\n surprised: { angry: 0.3, sad: 0.3 },\r\n disgusted: { happy: 0.4, surprised: 0.2 },\r\n fearful: { happy: 0.3, angry: 0.2 }\r\n};\r\n\r\n/**\r\n * Classify observed blendshapes into emotions using a 3-stage pipeline:\r\n * 1. Cosine similarity against EMFACS prototypes (base scores)\r\n * 2. Key-signal boosters for defining blendshapes (mouthPress → angry)\r\n * 3. Cross-emotion inhibition matrix (happy suppresses angry, etc.)\r\n *\r\n * Returns { neutral, happy, sad, angry, surprised, disgusted, fearful }\r\n */\r\nfunction mapBlendshapesToEmotions(bs) {\r\n const NF = BLENDSHAPE_NOISE_FLOOR;\r\n\r\n // --- Stage 1: Cosine similarity base scores ---\r\n const scores = {};\r\n for (const [emotion, proto] of Object.entries(EMOTION_PROTOTYPES)) {\r\n scores[emotion] = Math.max(0, emotionCosineSimilarity(bs, proto, PROTOTYPE_MAGNITUDES[emotion]));\r\n }\r\n\r\n // --- Stage 2: Key-signal boosters ---\r\n // mouthPress is a defining angry signal not in the prototype (to avoid\r\n // resting-state contamination) but boosts angry when clearly present\r\n const mouthPress = Math.max(0,\r\n ((bs.mouthPressLeft || 0) + (bs.mouthPressRight || 0)) / 2 - NF);\r\n if (mouthPress > 0) {\r\n scores.angry = Math.min(1, scores.angry + mouthPress * 0.3);\r\n }\r\n\r\n // --- Stage 3: Cross-emotion inhibition ---\r\n // Snapshot raw scores so suppression is non-circular\r\n const raw = {};\r\n for (const key in scores) raw[key] = scores[key];\r\n\r\n for (const [suppressor, targets] of Object.entries(EMOTION_INHIBITIONS)) {\r\n const suppressorScore = raw[suppressor] || 0;\r\n if (suppressorScore > 0.1) {\r\n for (const [target, strength] of Object.entries(targets)) {\r\n scores[target] *= (1 - suppressorScore * strength);\r\n }\r\n }\r\n }\r\n\r\n // --- Neutral: dominant when no emotion is confident ---\r\n let maxScore = 0;\r\n for (const emotion of Object.keys(EMOTION_PROTOTYPES)) {\r\n if (scores[emotion] > maxScore) maxScore = scores[emotion];\r\n }\r\n const neutralThreshold = 0.35;\r\n scores.neutral = maxScore < neutralThreshold ? 1.0 : Math.max(0, 1.0 - maxScore * 1.5);\r\n\r\n return {\r\n neutral: scores.neutral,\r\n happy: scores.happy || 0,\r\n sad: scores.sad || 0,\r\n angry: scores.angry || 0,\r\n surprised: scores.surprised || 0,\r\n disgusted: scores.disgusted || 0,\r\n fearful: scores.fearful || 0\r\n };\r\n}\r\n\r\n/**\r\n * Compute head pose (pitch, yaw, roll in degrees) from 468 face landmarks.\r\n * Uses nose tip, chin, eye corners, and forehead to derive 3D orientation.\r\n */\r\nfunction computeHeadPoseFromLandmarks(landmarks) {\r\n // Key landmark indices (MediaPipe FaceMesh)\r\n const noseTip = landmarks[1];\r\n const chin = landmarks[152];\r\n const leftEye = landmarks[33];\r\n const rightEye = landmarks[263];\r\n const forehead = landmarks[10];\r\n\r\n if (!noseTip || !chin || !leftEye || !rightEye || !forehead) {\r\n return { pitch: 0, yaw: 0, roll: 0 };\r\n }\r\n\r\n // Yaw: horizontal angle from eye midpoint to nose tip\r\n const eyeMidX = (leftEye.x + rightEye.x) / 2;\r\n const eyeMidY = (leftEye.y + rightEye.y) / 2;\r\n const yaw = Math.atan2(noseTip.x - eyeMidX, Math.abs(noseTip.z - ((leftEye.z + rightEye.z) / 2 || 0)) + 0.001) * (180 / Math.PI);\r\n\r\n // Pitch: vertical angle from forehead to chin through nose\r\n const faceVerticalLen = Math.sqrt((chin.x - forehead.x) ** 2 + (chin.y - forehead.y) ** 2) || 0.001;\r\n const noseRelY = (noseTip.y - forehead.y) / faceVerticalLen;\r\n const pitch = (noseRelY - 0.5) * 180;\r\n\r\n // Roll: tilt from horizontal eye line\r\n const roll = Math.atan2(rightEye.y - leftEye.y, rightEye.x - leftEye.x) * (180 / Math.PI);\r\n\r\n return {\r\n pitch: isNaN(pitch) ? 0 : Math.max(-90, Math.min(90, pitch)),\r\n yaw: isNaN(yaw) ? 0 : Math.max(-90, Math.min(90, yaw)),\r\n roll: isNaN(roll) ? 0 : Math.max(-180, Math.min(180, roll))\r\n };\r\n}\r\n\r\n/**\r\n * Detect WASM SIMD support at runtime.\r\n * Uses the standard test: validate a minimal SIMD module.\r\n */\r\nfunction detectSIMDSupport() {\r\n try {\r\n return WebAssembly.validate(new Uint8Array([\r\n 0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 123,\r\n 3, 2, 1, 0, 10, 10, 1, 8, 0, 65, 0, 253, 15, 253, 98, 11\r\n ]));\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Initialize MediaPipe Tasks Vision runtime.\r\n *\r\n * Constructs a WasmFileset manually from individual URLs (bypassing\r\n * FilesetResolver) so that the consumer's bundler-resolved URLs are\r\n * used directly. Picks the SIMD or non-SIMD variant at runtime.\r\n */\r\nasync function initializeVision() {\r\n if (isInitialized) {\r\n log('Vision already initialized, skipping');\r\n return;\r\n }\r\n \r\n if (!assetConfig.wasmUrls) {\r\n throw new Error('WASM URLs not set — init message must be received before initializeVision()');\r\n }\r\n \r\n try {\r\n log('Starting MediaPipe Tasks Vision initialization...');\r\n \r\n const simd = detectSIMDSupport();\r\n log('WASM SIMD support:', simd);\r\n\r\n const wasmFileset = simd\r\n ? { wasmLoaderPath: assetConfig.wasmUrls.simdLoaderJs, wasmBinaryPath: assetConfig.wasmUrls.simdBinary }\r\n : { wasmLoaderPath: assetConfig.wasmUrls.nosimdLoaderJs, wasmBinaryPath: assetConfig.wasmUrls.nosimdBinary };\r\n\r\n log('Using WASM fileset:', wasmFileset);\r\n\r\n vision = wasmFileset;\r\n \r\n isInitialized = true;\r\n log('✅ MediaPipe Tasks Vision initialized successfully');\r\n } catch (error) {\r\n log('❌ Failed to initialize MediaPipe Tasks Vision:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load and initialize Face Detection\r\n */\r\nasync function initializeFaceDetection() {\r\n if (faceDetector) return;\r\n \r\n // Ensure vision runtime is initialized first\r\n await initializeVision();\r\n \r\n try {\r\n log('Loading Face Detector...');\r\n \r\n const options = {\r\n baseOptions: {\r\n modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/face_detector/blaze_face_short_range/float16/1/blaze_face_short_range.tflite',\r\n delegate: 'GPU'\r\n },\r\n runningMode: 'VIDEO',\r\n minDetectionConfidence: 0.5,\r\n minSuppressionThreshold: 0.3\r\n };\r\n \r\n const FaceDetector = self.FaceDetector || self.module.exports.FaceDetector || self.exports.FaceDetector;\r\n faceDetector = await FaceDetector.createFromOptions(vision, options);\r\n log('✅ Face Detector loaded');\r\n } catch (error) {\r\n log('❌ Failed to load Face Detector:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load and initialize Face Landmarks\r\n */\r\nasync function initializeFaceLandmarks() {\r\n if (faceLandmarker) return;\r\n \r\n // Ensure vision runtime is initialized first\r\n await initializeVision();\r\n \r\n try {\r\n log('Loading Face Landmarker...');\r\n \r\n const options = {\r\n baseOptions: {\r\n modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task',\r\n delegate: 'GPU'\r\n },\r\n runningMode: 'VIDEO',\r\n numFaces: 1,\r\n outputFaceBlendshapes: true\r\n };\r\n \r\n const FaceLandmarker = self.FaceLandmarker || self.module.exports.FaceLandmarker || self.exports.FaceLandmarker;\r\n faceLandmarker = await FaceLandmarker.createFromOptions(vision, options);\r\n log('✅ Face Landmarker loaded (blendshapes enabled)');\r\n } catch (error) {\r\n log('❌ Failed to load Face Landmarker:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load and initialize Hand Tracking via GestureRecognizer\r\n * (provides landmarks + handedness + ML-based gesture classification in one call)\r\n */\r\nasync function initializeHandTracking() {\r\n if (gestureRecognizer) return;\r\n \r\n await initializeVision();\r\n \r\n try {\r\n log('Loading Gesture Recognizer...');\r\n \r\n const options = {\r\n baseOptions: {\r\n modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/gesture_recognizer/gesture_recognizer/float16/1/gesture_recognizer.task',\r\n delegate: 'GPU'\r\n },\r\n runningMode: 'VIDEO',\r\n numHands: 2\r\n };\r\n \r\n const GestureRecognizer = self.GestureRecognizer || self.module.exports.GestureRecognizer || self.exports.GestureRecognizer;\r\n gestureRecognizer = await GestureRecognizer.createFromOptions(vision, options);\r\n log('✅ Gesture Recognizer loaded');\r\n } catch (error) {\r\n log('❌ Failed to load Gesture Recognizer:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load and initialize Pose Detection\r\n */\r\nasync function initializePoseDetection() {\r\n if (poseLandmarker) return;\r\n \r\n // Ensure vision runtime is initialized first\r\n await initializeVision();\r\n \r\n try {\r\n log('Loading Pose Landmarker...');\r\n \r\n const options = {\r\n baseOptions: {\r\n modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task',\r\n delegate: 'GPU'\r\n },\r\n runningMode: 'VIDEO',\r\n numPoses: 1\r\n };\r\n \r\n const PoseLandmarker = self.PoseLandmarker || self.module.exports.PoseLandmarker || self.exports.PoseLandmarker;\r\n poseLandmarker = await PoseLandmarker.createFromOptions(vision, options);\r\n log('✅ Pose Landmarker loaded');\r\n } catch (error) {\r\n log('❌ Failed to load Pose Landmarker:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Load and initialize Body Segmentation\r\n */\r\nasync function initializeBodySegmentation() {\r\n if (imageSegmenter) return;\r\n \r\n // Ensure vision runtime is initialized first\r\n await initializeVision();\r\n \r\n try {\r\n log('Loading Image Segmenter...');\r\n \r\n const options = {\r\n baseOptions: {\r\n modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/image_segmenter/selfie_segmenter/float16/1/selfie_segmenter.tflite',\r\n delegate: 'GPU'\r\n },\r\n runningMode: 'IMAGE',\r\n outputCategoryMask: true,\r\n outputConfidenceMasks: false\r\n };\r\n \r\n const ImageSegmenter = self.ImageSegmenter || self.module.exports.ImageSegmenter || self.exports.ImageSegmenter;\r\n imageSegmenter = await ImageSegmenter.createFromOptions(vision, options);\r\n log('✅ Image Segmenter loaded');\r\n } catch (error) {\r\n log('❌ Failed to load Image Segmenter:', error);\r\n throw error;\r\n }\r\n}\r\n\r\nfunction computeHandBounds(landmarks) {\r\n let minX = 1, minY = 1, maxX = 0, maxY = 0;\r\n for (const p of landmarks) {\r\n if (p.x < minX) minX = p.x;\r\n if (p.y < minY) minY = p.y;\r\n if (p.x > maxX) maxX = p.x;\r\n if (p.y > maxY) maxY = p.y;\r\n }\r\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\r\n}\r\n\r\n// Map MediaPipe GestureRecognizer category names to our API field names\r\nconst GESTURE_NAME_MAP = {\r\n 'Closed_Fist': 'fist',\r\n 'Open_Palm': 'openPalm',\r\n 'Victory': 'peace',\r\n 'Thumb_Up': 'thumbsUp',\r\n 'Pointing_Up': 'pointing',\r\n 'Thumb_Down': 'thumbsDown',\r\n 'ILoveYou': 'iLoveYou'\r\n};\r\n\r\nfunction mapGestures(gestureCategories) {\r\n const result = { fist: 0, openPalm: 0, peace: 0, thumbsUp: 0, pointing: 0, thumbsDown: 0, iLoveYou: 0 };\r\n if (!gestureCategories) return result;\r\n for (const cat of gestureCategories) {\r\n const key = GESTURE_NAME_MAP[cat.categoryName];\r\n if (key) result[key] = cat.score;\r\n }\r\n return result;\r\n}\r\n\r\n// BlazePose landmark index groups for named body parts\r\nconst POSE_FACE_INDICES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\r\nconst POSE_TORSO_INDICES = [11, 12, 23, 24];\r\nconst POSE_LEFT_ARM_INDICES = [11, 13, 15];\r\nconst POSE_RIGHT_ARM_INDICES = [12, 14, 16];\r\nconst POSE_LEFT_LEG_INDICES = [23, 25, 27, 29, 31];\r\nconst POSE_RIGHT_LEG_INDICES = [24, 26, 28, 30, 32];\r\n\r\nfunction extractPoseGroup(landmarks, indices) {\r\n return indices.map(i => {\r\n const lm = landmarks[i];\r\n return lm ? { x: lm.x, y: lm.y } : { x: 0, y: 0 };\r\n });\r\n}\r\n\r\nfunction computePoseConfidence(landmarks) {\r\n let sum = 0;\r\n for (const lm of landmarks) sum += (lm.visibility || 0);\r\n return landmarks.length > 0 ? sum / landmarks.length : 0;\r\n}\r\n\r\n/**\r\n * Process video frame with active CV features\r\n * @param {ImageData|ImageBitmap} imageInput - Image input (ImageData or ImageBitmap)\r\n * @param {number} timestamp - Frame timestamp \r\n * @param {string[]} features - Active CV features\r\n */\r\nasync function processFrame(imageInput, timestamp, features) {\r\n const results = {};\r\n \r\n try {\r\n // Process face detection\r\n if (features.includes('faceDetection') && faceDetector) {\r\n const detectionResult = faceDetector.detectForVideo(imageInput, timestamp);\r\n results.faces = detectionResult.detections.map((detection, index) => ({\r\n id: index,\r\n bounds: {\r\n x: detection.boundingBox.originX / imageInput.width,\r\n y: detection.boundingBox.originY / imageInput.height,\r\n width: detection.boundingBox.width / imageInput.width,\r\n height: detection.boundingBox.height / imageInput.height\r\n },\r\n center: {\r\n x: (detection.boundingBox.originX + detection.boundingBox.width / 2) / imageInput.width,\r\n y: (detection.boundingBox.originY + detection.boundingBox.height / 2) / imageInput.height\r\n },\r\n landmarks: [],\r\n expressions: EMPTY_EXPRESSIONS,\r\n headPose: EMPTY_HEAD_POSE,\r\n blendshapes: EMPTY_BLENDSHAPES,\r\n confidence: detection.categories[0]?.score || 0\r\n }));\r\n }\r\n \r\n // Process face landmarks (used by faceMesh and emotionDetection)\r\n if ((features.includes('faceMesh') || features.includes('emotionDetection')) && faceLandmarker) {\r\n const landmarkResult = faceLandmarker.detectForVideo(imageInput, timestamp);\r\n if (landmarkResult.faceLandmarks.length > 0) {\r\n const landmarks = landmarkResult.faceLandmarks[0];\r\n \r\n if (!results.faces) {\r\n results.faces = [{\r\n id: 0,\r\n bounds: null,\r\n center: null,\r\n landmarks: [],\r\n expressions: EMPTY_EXPRESSIONS,\r\n headPose: EMPTY_HEAD_POSE,\r\n blendshapes: EMPTY_BLENDSHAPES,\r\n confidence: 0.8\r\n }];\r\n }\r\n \r\n const mappedLandmarks = landmarks.map((landmark) => ({\r\n x: landmark.x,\r\n y: landmark.y,\r\n z: landmark.z || 0\r\n }));\r\n\r\n if (results.faces[0]) {\r\n results.faces[0].landmarks = mappedLandmarks;\r\n results.faces[0].headPose = computeHeadPoseFromLandmarks(landmarks);\r\n\r\n if (features.includes('emotionDetection') &&\r\n landmarkResult.faceBlendshapes &&\r\n landmarkResult.faceBlendshapes.length > 0) {\r\n const bs = buildBlendshapesRecord(landmarkResult.faceBlendshapes[0].categories);\r\n results.faces[0].blendshapes = bs;\r\n results.faces[0].expressions = mapBlendshapesToEmotions(bs);\r\n }\r\n }\r\n } else if (!results.faces) {\r\n results.faces = [];\r\n }\r\n }\r\n \r\n // Process hand tracking (GestureRecognizer provides landmarks + gestures in one call)\r\n if (features.includes('handTracking') && gestureRecognizer) {\r\n const handResult = gestureRecognizer.recognizeForVideo(imageInput, timestamp);\r\n results.hands = handResult.landmarks.map((landmarks, index) => {\r\n const mapped = landmarks.map((landmark) => ({\r\n x: landmark.x,\r\n y: landmark.y,\r\n z: landmark.z || 0\r\n }));\r\n\r\n const rawHandedness = handResult.handednesses[index]?.[0]?.categoryName || 'unknown';\r\n\r\n return {\r\n id: index,\r\n handedness: rawHandedness.toLowerCase(),\r\n confidence: handResult.handednesses[index]?.[0]?.score || 0,\r\n bounds: computeHandBounds(mapped),\r\n landmarks: mapped,\r\n palm: mapped[9],\r\n gestures: mapGestures(handResult.gestures[index])\r\n };\r\n });\r\n }\r\n \r\n // Process pose detection\r\n if (features.includes('poseDetection') && poseLandmarker) {\r\n const poseResult = poseLandmarker.detectForVideo(imageInput, timestamp);\r\n if (poseResult.landmarks.length > 0) {\r\n const poseLandmarks = poseResult.landmarks[0].map((landmark) => ({\r\n x: landmark.x,\r\n y: landmark.y,\r\n z: landmark.z || 0,\r\n visibility: landmark.visibility || 1\r\n }));\r\n\r\n results.pose = {\r\n confidence: computePoseConfidence(poseLandmarks),\r\n landmarks: poseLandmarks,\r\n face: extractPoseGroup(poseLandmarks, POSE_FACE_INDICES),\r\n torso: extractPoseGroup(poseLandmarks, POSE_TORSO_INDICES),\r\n leftArm: extractPoseGroup(poseLandmarks, POSE_LEFT_ARM_INDICES),\r\n rightArm: extractPoseGroup(poseLandmarks, POSE_RIGHT_ARM_INDICES),\r\n leftLeg: extractPoseGroup(poseLandmarks, POSE_LEFT_LEG_INDICES),\r\n rightLeg: extractPoseGroup(poseLandmarks, POSE_RIGHT_LEG_INDICES),\r\n worldLandmarks: poseResult.worldLandmarks?.[0]?.map((landmark) => ({\r\n x: landmark.x,\r\n y: landmark.y,\r\n z: landmark.z || 0,\r\n visibility: landmark.visibility || 1\r\n })) || []\r\n };\r\n } else {\r\n results.pose = null;\r\n }\r\n }\r\n \r\n // Process body segmentation\r\n if (features.includes('bodySegmentation') && imageSegmenter) {\r\n const segmentResult = imageSegmenter.segment(imageInput);\r\n if (segmentResult.categoryMask) {\r\n try {\r\n results.segmentation = {\r\n mask: segmentResult.categoryMask.getAsUint8Array(),\r\n width: segmentResult.categoryMask.width,\r\n height: segmentResult.categoryMask.height\r\n };\r\n log('Segmentation mask:', results.segmentation.width, 'x', results.segmentation.height);\r\n } finally {\r\n segmentResult.categoryMask.close();\r\n }\r\n } else {\r\n results.segmentation = null;\r\n }\r\n }\r\n \r\n return results;\r\n } catch (error) {\r\n log('❌ Error processing frame:', error);\r\n return {};\r\n }\r\n}\r\n\r\n// Note: Removed reusable canvas functions - no longer needed with direct ImageBitmap processing!\r\n\r\n/**\r\n * Clean up WASM instance with proper memory management\r\n */\r\nfunction cleanupWasmInstance(instance, featureName) {\r\n if (instance) {\r\n try {\r\n log(`🧹 Cleaning up ${featureName} WASM instance...`);\r\n instance.close();\r\n \r\n // Force garbage collection if available (Chrome DevTools)\r\n if (typeof gc === 'function') {\r\n gc();\r\n }\r\n \r\n // Give time for WASM cleanup\r\n return new Promise(resolve => {\r\n setTimeout(resolve, 100);\r\n });\r\n } catch (error) {\r\n log(`⚠️ Error cleaning up ${featureName}:`, error);\r\n }\r\n }\r\n return Promise.resolve();\r\n}\r\n\r\n/**\r\n * Process configuration queue sequentially\r\n */\r\nasync function processConfigQueue() {\r\n if (processingConfig || configQueue.length === 0) return;\r\n \r\n processingConfig = true;\r\n \r\n try {\r\n while (configQueue.length > 0) {\r\n const { features, resolve, reject } = configQueue.shift();\r\n \r\n try {\r\n await handleConfigUpdateInternal(features);\r\n resolve({ configured: true, activeFeatures: Array.from(activeFeatures) });\r\n } catch (error) {\r\n reject(error);\r\n }\r\n }\r\n } finally {\r\n processingConfig = false;\r\n }\r\n}\r\n\r\n/**\r\n * Queue configuration update to prevent race conditions\r\n */\r\nfunction queueConfigUpdate(features) {\r\n return new Promise((resolve, reject) => {\r\n configQueue.push({ features, resolve, reject });\r\n processConfigQueue();\r\n });\r\n}\r\n\r\n/**\r\n * Handle feature configuration updates (internal)\r\n */\r\nasync function handleConfigUpdateInternal(features) {\r\n if (!workerHealthy) {\r\n throw new Error('Worker is in unhealthy state, restart required');\r\n }\r\n \r\n const newFeatures = new Set(features);\r\n const toEnable = features.filter(f => !activeFeatures.has(f));\r\n const toDisable = Array.from(activeFeatures).filter(f => !newFeatures.has(f));\r\n \r\n log(`🔄 Config update: enable [${toEnable.join(', ')}], disable [${toDisable.join(', ')}]`);\r\n \r\n // Disable unused features first (cleanup instances)\r\n const cleanupPromises = [];\r\n for (const feature of toDisable) {\r\n switch (feature) {\r\n case 'faceDetection':\r\n cleanupPromises.push(cleanupWasmInstance(faceDetector, 'FaceDetector'));\r\n faceDetector = null;\r\n break;\r\n case 'faceMesh':\r\n // Only teardown FaceLandmarker if emotionDetection also not active\r\n if (!newFeatures.has('emotionDetection')) {\r\n cleanupPromises.push(cleanupWasmInstance(faceLandmarker, 'FaceLandmarker'));\r\n faceLandmarker = null;\r\n }\r\n break;\r\n case 'emotionDetection':\r\n // Only teardown FaceLandmarker if faceMesh also not active\r\n if (!newFeatures.has('faceMesh')) {\r\n cleanupPromises.push(cleanupWasmInstance(faceLandmarker, 'FaceLandmarker'));\r\n faceLandmarker = null;\r\n }\r\n break;\r\n case 'handTracking':\r\n cleanupPromises.push(cleanupWasmInstance(gestureRecognizer, 'GestureRecognizer'));\r\n gestureRecognizer = null;\r\n break;\r\n case 'poseDetection':\r\n cleanupPromises.push(cleanupWasmInstance(poseLandmarker, 'PoseLandmarker'));\r\n poseLandmarker = null;\r\n break;\r\n case 'bodySegmentation':\r\n cleanupPromises.push(cleanupWasmInstance(imageSegmenter, 'ImageSegmenter'));\r\n imageSegmenter = null;\r\n break;\r\n }\r\n activeFeatures.delete(feature);\r\n log(`🗑️ Disabled feature: ${feature}`);\r\n }\r\n \r\n // Wait for all cleanup to complete\r\n if (cleanupPromises.length > 0) {\r\n await Promise.all(cleanupPromises);\r\n log('✅ All cleanup completed');\r\n }\r\n \r\n // Note: No canvas cleanup needed - using direct ImageBitmap processing!\r\n \r\n // Enable new features\r\n for (const feature of toEnable) {\r\n try {\r\n switch (feature) {\r\n case 'faceDetection':\r\n await initializeFaceDetection();\r\n break;\r\n case 'faceMesh':\r\n case 'emotionDetection':\r\n // Both share the FaceLandmarker (with blendshapes enabled)\r\n await initializeFaceLandmarks();\r\n break;\r\n case 'handTracking':\r\n await initializeHandTracking();\r\n break;\r\n case 'poseDetection':\r\n await initializePoseDetection();\r\n break;\r\n case 'bodySegmentation':\r\n await initializeBodySegmentation();\r\n break;\r\n }\r\n activeFeatures.add(feature);\r\n log(`✅ Enabled feature: ${feature}`);\r\n } catch (error) {\r\n log(`❌ Failed to enable feature ${feature}:`, error);\r\n \r\n // Check if this is a memory error\r\n if (error.message && error.message.includes('Out of memory')) {\r\n memoryPressureDetected = true;\r\n workerHealthy = false;\r\n throw new Error(`Memory exhausted while enabling ${feature}. Worker restart required.`);\r\n }\r\n \r\n throw error;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Legacy function for backward compatibility\r\n */\r\nasync function handleConfigUpdate(features) {\r\n return await queueConfigUpdate(features);\r\n}\r\n\r\n// Message handler. Every request carries a monotonic `requestId`; we echo it\r\n// back on every `result` post so the host can correlate responses to requests.\r\nself.onmessage = async (event) => {\r\n const message = event.data;\r\n const requestId = message.requestId;\r\n\r\n // Only log non-process messages to avoid per-frame spam\r\n if (message.type !== 'process') {\r\n log('Received message:', message.type, 'requestId:', requestId);\r\n }\r\n\r\n try {\r\n switch (message.type) {\r\n case 'debug': {\r\n DEBUG = !!message.enabled;\r\n log('Debug mode', DEBUG ? 'enabled' : 'disabled');\r\n break;\r\n }\r\n\r\n case 'init': {\r\n log('Received init message');\r\n\r\n const visionCode = message.visionBundleCode;\r\n assetConfig.wasmUrls = message.wasmUrls || null;\r\n\r\n if (!visionCode || !assetConfig.wasmUrls) {\r\n throw new Error('init message must include visionBundleCode and wasmUrls');\r\n }\r\n\r\n log('WASM URLs received:', Object.keys(assetConfig.wasmUrls));\r\n\r\n try {\r\n (0, eval)(visionCode);\r\n log('vision_bundle executed successfully (inlined code)');\r\n } catch (error) {\r\n log('❌ Failed to execute vision_bundle:', error);\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: false,\r\n error: 'Failed to execute vision bundle: ' + error.message,\r\n restartRequired: true\r\n });\r\n break;\r\n }\r\n\r\n try {\r\n await initializeVision();\r\n log('Vision runtime ready for feature loading');\r\n } catch (error) {\r\n log('❌ Vision runtime initialization failed:', error);\r\n throw error;\r\n }\r\n\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: true,\r\n data: { initialized: true }\r\n });\r\n break;\r\n }\r\n\r\n case 'config': {\r\n log('Received config message:', message.features);\r\n\r\n try {\r\n const result = await handleConfigUpdate(message.features);\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: true,\r\n data: result\r\n });\r\n } catch (error) {\r\n log('❌ Config update failed:', error);\r\n\r\n // Check if worker needs restart\r\n if (!workerHealthy || memoryPressureDetected) {\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: false,\r\n error: error.message,\r\n restartRequired: true\r\n });\r\n } else {\r\n throw error; // Re-throw for normal error handling\r\n }\r\n }\r\n break;\r\n }\r\n\r\n case 'process': {\r\n // The bitmap is transferred BACK to CVSystem on the success path so the\r\n // host can pair MediaPipe's results with the exact pixels that produced\r\n // them (viji.video.cv.analysedFrame). MediaPipe's tasks-vision API treats\r\n // the input as a borrowed TexImageSource and does not retain it\r\n // (vision.d.ts:1772-1773 + ImageSource = TexImageSource at :1935), so\r\n // the bitmap is still valid after detectForVideo / segment / etc.\r\n //\r\n // Resource discipline (docs/14 rule 1): every code path either\r\n // transfers the bitmap or closes it.\r\n // - Inner try resolves → success post transfers, flag set\r\n // - Inner try throws → finally closes (flag still false)\r\n // - Outer catch error post → no data.frame; finally already closed\r\n //\r\n // Note: this transfer is intra-worker (scene worker ↔ cv-tasks\r\n // sub-worker, both inside the iframe). It does NOT cross the\r\n // host↔iframe boundary, so collectTransferables in\r\n // src/iframe/protocol.ts does not apply here.\r\n let bitmapTransferred = false;\r\n try {\r\n // 🚀 OPTIMIZED: Pass ImageBitmap directly to MediaPipe (no conversion!)\r\n const results = await processFrame(message.bitmap, message.timestamp, message.features);\r\n\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: true,\r\n data: { ...results, frame: message.bitmap }\r\n }, [message.bitmap]);\r\n bitmapTransferred = true;\r\n } finally {\r\n if (!bitmapTransferred && message.bitmap && typeof message.bitmap.close === 'function') {\r\n try { message.bitmap.close(); } catch { /* already detached */ }\r\n }\r\n }\r\n break;\r\n }\r\n\r\n default:\r\n log('❌ Unknown message type:', message.type);\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: false,\r\n error: `Unknown message type: ${message.type}`\r\n });\r\n }\r\n } catch (error) {\r\n log('❌ Error handling message:', error);\r\n self.postMessage({\r\n type: 'result',\r\n requestId,\r\n success: false,\r\n error: error instanceof Error ? error.message : String(error)\r\n });\r\n }\r\n};\r\n\r\nlog('CV Tasks Worker loaded — waiting for init message with inlined code and WASM URLs');\r\n";
|
|
1108
1108
|
var visionBundleCode = '"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t="undefined"!=typeof self?self:{};function e(e,n){e=e.split(".");var r,i=t;e[0]in i||void 0===i.execScript||i.execScript("var "+e[0]);for(;e.length&&(r=e.shift());)e.length||void 0===n?i=i[r]&&i[r]!==Object.prototype[r]?i[r]:i[r]={}:i[r]=n}function n(){throw Error("Invalid UTF8")}function r(t,e){return e=String.fromCharCode.apply(null,e),null==t?e:t+e}let i,s;const o="undefined"!=typeof TextDecoder;let a;const c="undefined"!=typeof TextEncoder;function h(t){if(c)t=(a||=new TextEncoder).encode(t);else{let n=0;const r=new Uint8Array(3*t.length);for(let i=0;i<t.length;i++){var e=t.charCodeAt(i);if(e<128)r[n++]=e;else{if(e<2048)r[n++]=e>>6|192;else{if(e>=55296&&e<=57343){if(e<=56319&&i<t.length){const s=t.charCodeAt(++i);if(s>=56320&&s<=57343){e=1024*(e-55296)+s-56320+65536,r[n++]=e>>18|240,r[n++]=e>>12&63|128,r[n++]=e>>6&63|128,r[n++]=63&e|128;continue}i--}e=65533}r[n++]=e>>12|224,r[n++]=e>>6&63|128}r[n++]=63&e|128}}t=n===r.length?r:r.subarray(0,n)}return t}var u,l;t:{for(var f=["CLOSURE_FLAGS"],d=t,p=0;p<f.length;p++)if(null==(d=d[f[p]])){l=null;break t}l=d}var g,m=l&&l[610401301];u=null!=m&&m;const y=t.navigator;function _(t){return!!u&&(!!g&&g.brands.some((({brand:e})=>e&&-1!=e.indexOf(t))))}function v(e){var n;return(n=t.navigator)&&(n=n.userAgent)||(n=""),-1!=n.indexOf(e)}function E(){return!!u&&(!!g&&g.brands.length>0)}function w(){return E()?_("Chromium"):(v("Chrome")||v("CriOS"))&&!(!E()&&v("Edge"))||v("Silk")}function T(t){return T[" "](t),t}g=y&&y.userAgentData||null,T[" "]=function(){};var b=!E()&&(v("Trident")||v("MSIE"));!v("Android")||w(),w(),v("Safari")&&(w()||!E()&&v("Coast")||!E()&&v("Opera")||!E()&&v("Edge")||(E()?_("Microsoft Edge"):v("Edg/"))||E()&&_("Opera"));var A={},k=null;function x(t){const e=t.length;let n=3*e/4;n%3?n=Math.floor(n):-1!="=.".indexOf(t[e-1])&&(n=-1!="=.".indexOf(t[e-2])?n-2:n-1);const r=new Uint8Array(n);let i=0;return function(t,e){function n(e){for(;r<t.length;){const e=t.charAt(r++),n=k[e];if(null!=n)return n;if(!/^[\\s\\xa0]*$/.test(e))throw Error("Unknown base64 encoding at char: "+e)}return e}S();let r=0;for(;;){const t=n(-1),r=n(0),i=n(64),s=n(64);if(64===s&&-1===t)break;e(t<<2|r>>4),64!=i&&(e(r<<4&240|i>>2),64!=s&&e(i<<6&192|s))}}(t,(function(t){r[i++]=t})),i!==n?r.subarray(0,i):r}function S(){if(!k){k={};var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),e=["+/=","+/","-_=","-_.","-_"];for(let n=0;n<5;n++){const r=t.concat(e[n].split(""));A[n]=r;for(let t=0;t<r.length;t++){const e=r[t];void 0===k[e]&&(k[e]=t)}}}}var L="undefined"!=typeof Uint8Array,R=!b&&"function"==typeof btoa;function F(t){if(!R){var e;void 0===e&&(e=0),S(),e=A[e];var n=Array(Math.floor(t.length/3)),r=e[64]||"";let c=0,h=0;for(;c<t.length-2;c+=3){var i=t[c],s=t[c+1],o=t[c+2],a=e[i>>2];i=e[(3&i)<<4|s>>4],s=e[(15&s)<<2|o>>6],o=e[63&o],n[h++]=a+i+s+o}switch(a=0,o=r,t.length-c){case 2:o=e[(15&(a=t[c+1]))<<2]||r;case 1:t=t[c],n[h]=e[t>>2]+e[(3&t)<<4|a>>4]+o+r}return n.join("")}for(e="",n=0,r=t.length-10240;n<r;)e+=String.fromCharCode.apply(null,t.subarray(n,n+=10240));return e+=String.fromCharCode.apply(null,n?t.subarray(n):t),btoa(e)}const I=/[-_.]/g,M={"-":"+",_:"/",".":"="};function P(t){return M[t]||""}function O(t){if(!R)return x(t);I.test(t)&&(t=t.replace(I,P)),t=atob(t);const e=new Uint8Array(t.length);for(let n=0;n<t.length;n++)e[n]=t.charCodeAt(n);return e}function C(t){return L&&null!=t&&t instanceof Uint8Array}var U={};function N(){return G||=new B(null,U)}function D(t){V(U);var e=t.g;return null==(e=null==e||C(e)?e:"string"==typeof e?O(e):null)?e:t.g=e}var B=class{h(){return new Uint8Array(D(this)||0)}constructor(t,e){if(V(e),this.g=t,null!=t&&0===t.length)throw Error("ByteString should be constructed with non-empty values")}};let G,j;function V(t){if(t!==U)throw Error("illegal external caller")}function X(t,e){t.__closure__error__context__984382||(t.__closure__error__context__984382={}),t.__closure__error__context__984382.severity=e}function H(){const e=Error();X(e,"incident"),function(e){t.setTimeout((()=>{throw e}),0)}(e)}function W(t){return X(t=Error(t),"warning"),t}function z(){return"function"==typeof BigInt}function K(t){return Array.prototype.slice.call(t)}var Y="function"==typeof Symbol&&"symbol"==typeof Symbol();function $(t){return"function"==typeof Symbol&&"symbol"==typeof Symbol()?Symbol():t}var q=$(),J=$("0di"),Z=$("2ex"),Q=$("1oa"),tt=Y?(t,e)=>{t[q]|=e}:(t,e)=>{void 0!==t.G?t.G|=e:Object.defineProperties(t,{G:{value:e,configurable:!0,writable:!0,enumerable:!1}})},et=Y?(t,e)=>{t[q]&=~e}:(t,e)=>{void 0!==t.G&&(t.G&=~e)},nt=Y?t=>0|t[q]:t=>0|t.G,rt=Y?t=>t[q]:t=>t.G,it=Y?(t,e)=>{t[q]=e}:(t,e)=>{void 0!==t.G?t.G=e:Object.defineProperties(t,{G:{value:e,configurable:!0,writable:!0,enumerable:!1}})};function st(t){return tt(t,34),t}function ot(t,e){it(e,-30975&(0|t))}function at(t,e){it(e,-30941&(34|t))}var ct,ht={},ut={};function lt(t){return!(!t||"object"!=typeof t||t.Ia!==ut)}function ft(t){return null!==t&&"object"==typeof t&&!Array.isArray(t)&&t.constructor===Object}function dt(t,e){if(null!=t)if("string"==typeof t)t=t?new B(t,U):N();else if(t.constructor!==B)if(C(t))t=t.length?new B(new Uint8Array(t),U):N();else{if(!e)throw Error();t=void 0}return t}function pt(t){return!(!Array.isArray(t)||t.length)&&!!(1&nt(t))}const gt=[];function mt(t){if(2&t)throw Error()}it(gt,55),ct=Object.freeze(gt);class yt{constructor(t,e,n){this.l=0,this.g=t,this.h=e,this.m=n}next(){if(this.l<this.g.length){const t=this.g[this.l++];return{done:!1,value:this.h?this.h.call(this.m,t):t}}return{done:!0,value:void 0}}[Symbol.iterator](){return new yt(this.g,this.h,this.m)}}let _t;function vt(t,e){(e=_t?e[_t]:void 0)&&(t[_t]=K(e))}var Et=Object.freeze({});function wt(t){return t.Pa=!0,t}var Tt=wt((t=>"number"==typeof t)),bt=wt((t=>"string"==typeof t)),At=wt((t=>"boolean"==typeof t)),kt="function"==typeof t.BigInt&&"bigint"==typeof t.BigInt(0),xt=wt((t=>kt?t>=Lt&&t<=Ft:"-"===t[0]?It(t,St):It(t,Rt)));const St=Number.MIN_SAFE_INTEGER.toString(),Lt=kt?BigInt(Number.MIN_SAFE_INTEGER):void 0,Rt=Number.MAX_SAFE_INTEGER.toString(),Ft=kt?BigInt(Number.MAX_SAFE_INTEGER):void 0;function It(t,e){if(t.length>e.length)return!1;if(t.length<e.length||t===e)return!0;for(let n=0;n<t.length;n++){const r=t[n],i=e[n];if(r>i)return!1;if(r<i)return!0}}const Mt="function"==typeof Uint8Array.prototype.slice;let Pt,Ot=0,Ct=0;function Ut(t){const e=t>>>0;Ot=e,Ct=(t-e)/4294967296>>>0}function Nt(t){if(t<0){Ut(-t);const[e,n]=Ht(Ot,Ct);Ot=e>>>0,Ct=n>>>0}else Ut(t)}function Dt(t){const e=Pt||=new DataView(new ArrayBuffer(8));e.setFloat32(0,+t,!0),Ct=0,Ot=e.getUint32(0,!0)}function Bt(t,e){const n=4294967296*e+(t>>>0);return Number.isSafeInteger(n)?n:jt(t,e)}function Gt(t,e){const n=2147483648&e;return n&&(e=~e>>>0,0==(t=1+~t>>>0)&&(e=e+1>>>0)),"number"==typeof(t=Bt(t,e))?n?-t:t:n?"-"+t:t}function jt(t,e){if(t>>>=0,(e>>>=0)<=2097151)var n=""+(4294967296*e+t);else z()?n=""+(BigInt(e)<<BigInt(32)|BigInt(t)):(t=(16777215&t)+6777216*(n=16777215&(t>>>24|e<<8))+6710656*(e=e>>16&65535),n+=8147497*e,e*=2,t>=1e7&&(n+=t/1e7>>>0,t%=1e7),n>=1e7&&(e+=n/1e7>>>0,n%=1e7),n=e+Vt(n)+Vt(t));return n}function Vt(t){return t=String(t),"0000000".slice(t.length)+t}function Xt(t){if(t.length<16)Nt(Number(t));else if(z())t=BigInt(t),Ot=Number(t&BigInt(4294967295))>>>0,Ct=Number(t>>BigInt(32)&BigInt(4294967295));else{const e=+("-"===t[0]);Ct=Ot=0;const n=t.length;for(let r=e,i=(n-e)%6+e;i<=n;r=i,i+=6){const e=Number(t.slice(r,i));Ct*=1e6,Ot=1e6*Ot+e,Ot>=4294967296&&(Ct+=Math.trunc(Ot/4294967296),Ct>>>=0,Ot>>>=0)}if(e){const[t,e]=Ht(Ot,Ct);Ot=t,Ct=e}}}function Ht(t,e){return e=~e,t?t=1+~t:e+=1,[t,e]}function Wt(t){return null==t||"number"==typeof t?t:"NaN"===t||"Infinity"===t||"-Infinity"===t?Number(t):void 0}function zt(t){return null==t||"boolean"==typeof t?t:"number"==typeof t?!!t:void 0}const Kt=/^-?([1-9][0-9]*|0)(\\.[0-9]+)?$/;function Yt(t){const e=typeof t;switch(e){case"bigint":return!0;case"number":return Number.isFinite(t)}return"string"===e&&Kt.test(t)}function $t(t){if(null==t)return t;if("string"==typeof t){if(!t)return;t=+t}return"number"==typeof t&&Number.isFinite(t)?0|t:void 0}function qt(t){if(null==t)return t;if("string"==typeof t){if(!t)return;t=+t}return"number"==typeof t&&Number.isFinite(t)?t>>>0:void 0}function Jt(t){return"-"!==t[0]&&(t.length<20||20===t.length&&Number(t.substring(0,6))<184467)}function Zt(t){return t=Math.trunc(t),Number.isSafeInteger(t)||(Nt(t),t=Gt(Ot,Ct)),t}function Qt(t){var e=Math.trunc(Number(t));if(Number.isSafeInteger(e))return String(e);if(-1!==(e=t.indexOf("."))&&(t=t.substring(0,e)),!("-"===t[0]?t.length<20||20===t.length&&Number(t.substring(0,7))>-922337:t.length<19||19===t.length&&Number(t.substring(0,6))<922337))if(Xt(t),t=Ot,2147483648&(e=Ct))if(z())t=""+(BigInt(0|e)<<BigInt(32)|BigInt(t>>>0));else{const[n,r]=Ht(t,e);t="-"+jt(n,r)}else t=jt(t,e);return t}function te(t){return null==t?t:"bigint"==typeof t?(xt(t)?t=Number(t):(t=BigInt.asIntN(64,t),t=xt(t)?Number(t):String(t)),t):Yt(t)?"number"==typeof t?Zt(t):Qt(t):void 0}function ee(t){if(null==t)return t;var e=typeof t;if("bigint"===e)return String(BigInt.asUintN(64,t));if(Yt(t)){if("string"===e)return e=Math.trunc(Number(t)),Number.isSafeInteger(e)&&e>=0?t=String(e):(-1!==(e=t.indexOf("."))&&(t=t.substring(0,e)),Jt(t)||(Xt(t),t=jt(Ot,Ct))),t;if("number"===e)return(t=Math.trunc(t))>=0&&Number.isSafeInteger(t)?t:function(t){if(t<0){Nt(t);var e=jt(Ot,Ct);return t=Number(e),Number.isSafeInteger(t)?t:e}return Jt(e=String(t))?e:(Nt(t),Bt(Ot,Ct))}(t)}}function ne(t){if("string"!=typeof t)throw Error();return t}function re(t){if(null!=t&&"string"!=typeof t)throw Error();return t}function ie(t){return null==t||"string"==typeof t?t:void 0}function se(t,e,n,r){if(null!=t&&"object"==typeof t&&t.X===ht)return t;if(!Array.isArray(t))return n?2&r?(t=e[J])?e=t:(st((t=new e).u),e=e[J]=t):e=new e:e=void 0,e;let i=n=nt(t);return 0===i&&(i|=32&r),i|=2&r,i!==n&&it(t,i),new e(t)}function oe(t,e,n){if(e)t:{if(!Yt(e=t))throw W("int64");switch(typeof e){case"string":e=Qt(e);break t;case"bigint":if(t=e=BigInt.asIntN(64,e),bt(t)){if(!/^\\s*(?:-?[1-9]\\d*|0)?\\s*$/.test(t))throw Error(String(t))}else if(Tt(t)&&!Number.isSafeInteger(t))throw Error(String(t));e=kt?BigInt(e):At(e)?e?"1":"0":bt(e)?e.trim()||"0":String(e);break t;default:e=Zt(e)}}else e=te(t);return"string"==typeof(n=null==(t=e)?n?0:void 0:t)&&(e=+n,Number.isSafeInteger(e))?e:n}function ae(t){var e;return void 0===ue&&(ue="function"==typeof Proxy?me(Proxy):null),(e=!ue)||(void 0===le&&(le="function"==typeof WeakMap?me(WeakMap):null),e=!le),e?t:(e=ce?.get(t))?e:Math.random()>.01?t:(function(t){if(void 0===fe){const t=new ue([],{});fe=1===Array.prototype.concat.call([],t).length}fe&&"function"==typeof Symbol&&Symbol.isConcatSpreadable&&(t[Symbol.isConcatSpreadable]=!0)}(t),function(t,e){(ce||=new le).set(t,e),(he||=new le).set(e,t)}(t,e=new ue(t,{set:(t,e,n)=>(H(),t[e]=n,!0)})),e)}let ce,he,ue,le,fe,de,pe,ge;function me(t){try{return-1!==t.toString().indexOf("[native code]")?t:null}catch{return null}}function ye(t,e,n){return t=_e(t,e[0],e[1],n?1:2),e!==pe&&n&&tt(t,16384),t}function _e(t,e,n,r){if(r=r??0,null==t&&(t=de),de=void 0,null==t){var i=96;n?(t=[n],i|=512):t=[],e&&(i=-33521665&i|(1023&e)<<15)}else{if(!Array.isArray(t))throw Error("narr");if(2048&(i=nt(t)))throw Error("farr");if(64&i)return t;if(1===r||2===r||(i|=64),n&&(i|=512,n!==t[0]))throw Error("mid");t:{if(r=(n=t).length){const t=r-1;if(ft(n[t])){if((e=t-(+!!(512&(i|=256))-1))>=1024)throw Error("pvtlmt");i=-33521665&i|(1023&e)<<15;break t}}if(e){if((e=Math.max(e,r-(+!!(512&i)-1)))>1024)throw Error("spvt");i=-33521665&i|(1023&e)<<15}}}return it(t,i),t}const ve={};let Ee=function(){try{return T(new class extends Map{constructor(){super()}}),!1}catch{return!0}}();class we{constructor(){this.g=new Map}get(t){return this.g.get(t)}set(t,e){return this.g.set(t,e),this.size=this.g.size,this}delete(t){return t=this.g.delete(t),this.size=this.g.size,t}clear(){this.g.clear(),this.size=this.g.size}has(t){return this.g.has(t)}entries(){return this.g.entries()}keys(){return this.g.keys()}values(){return this.g.values()}forEach(t,e){return this.g.forEach(t,e)}[Symbol.iterator](){return this.entries()}}const Te=Ee?(Object.setPrototypeOf(we.prototype,Map.prototype),Object.defineProperties(we.prototype,{size:{value:0,configurable:!0,enumerable:!0,writable:!0}}),we):class extends Map{constructor(){super()}};function be(t){return t}function Ae(t){if(2&t.M)throw Error("Cannot mutate an immutable Map")}var ke=class extends Te{constructor(t,e,n=be,r=be){super();let i=nt(t);i|=64,it(t,i),this.M=i,this.T=e,this.S=n,this.Z=this.T?xe:r;for(let s=0;s<t.length;s++){const o=t[s],a=n(o[0],!1,!0);let c=o[1];e?void 0===c&&(c=null):c=r(o[1],!1,!0,void 0,void 0,i),super.set(a,c)}}oa(t=Se){if(0!==this.size)return this.Y(t)}Y(t=Se){const e=[],n=super.entries();for(var r;!(r=n.next()).done;)(r=r.value)[0]=t(r[0]),r[1]=t(r[1]),e.push(r);return e}clear(){Ae(this),super.clear()}delete(t){return Ae(this),super.delete(this.S(t,!0,!1))}entries(){var t=this.na();return new yt(t,Le,this)}keys(){return this.Ha()}values(){var t=this.na();return new yt(t,ke.prototype.get,this)}forEach(t,e){super.forEach(((n,r)=>{t.call(e,this.get(r),r,this)}))}set(t,e){return Ae(this),null==(t=this.S(t,!0,!1))?this:null==e?(super.delete(t),this):super.set(t,this.Z(e,!0,!0,this.T,!1,this.M))}Na(t){const e=this.S(t[0],!1,!0);t=t[1],t=this.T?void 0===t?null:t:this.Z(t,!1,!0,void 0,!1,this.M),super.set(e,t)}has(t){return super.has(this.S(t,!1,!1))}get(t){t=this.S(t,!1,!1);const e=super.get(t);if(void 0!==e){var n=this.T;return n?((n=this.Z(e,!1,!0,n,this.sa,this.M))!==e&&super.set(t,n),n):e}}na(){return Array.from(super.keys())}Ha(){return super.keys()}[Symbol.iterator](){return this.entries()}};function xe(t,e,n,r,i,s){return t=se(t,r,n,s),i&&(t=De(t)),t}function Se(t){return t}function Le(t){return[t,this.get(t)]}let Re;function Fe(){return Re||=new ke(st([]),void 0,void 0,void 0,ve)}function Ie(t,e,n,r,i){if(null!=t){if(Array.isArray(t))t=pt(t)?void 0:i&&2&nt(t)?t:Me(t,e,n,void 0!==r,i);else if(ft(t)){const s={};for(let o in t)s[o]=Ie(t[o],e,n,r,i);t=s}else t=e(t,r);return t}}function Me(t,e,n,r,i){const s=r||n?nt(t):0;r=r?!!(32&s):void 0;const o=K(t);for(let t=0;t<o.length;t++)o[t]=Ie(o[t],e,n,r,i);return n&&(vt(o,t),n(s,o)),o}function Pe(t){return Ie(t,Oe,void 0,void 0,!1)}function Oe(t){return t.X===ht?t.toJSON():t instanceof ke?t.oa(Pe):function(t){switch(typeof t){case"number":return isFinite(t)?t:String(t);case"bigint":return xt(t)?Number(t):String(t);case"boolean":return t?1:0;case"object":if(t)if(Array.isArray(t)){if(pt(t))return}else{if(C(t))return F(t);if(t instanceof B){const e=t.g;return null==e?"":"string"==typeof e?e:t.g=F(e)}if(t instanceof ke)return t.oa()}}return t}(t)}function Ce(t,e,n=at){if(null!=t){if(L&&t instanceof Uint8Array)return e?t:new Uint8Array(t);if(Array.isArray(t)){var r=nt(t);return 2&r?t:(e&&=0===r||!!(32&r)&&!(64&r||!(16&r)),e?(it(t,-12293&(34|r)),t):Me(t,Ce,4&r?at:n,!0,!0))}return t.X===ht?(n=t.u,t=2&(r=rt(n))?t:Ue(t,n,r,!0)):t instanceof ke&&!(2&t.M)&&(n=st(t.Y(Ce)),t=new ke(n,t.T,t.S,t.Z)),t}}function Ue(t,e,n,r){return t=t.constructor,de=e=Ne(e,n,r),e=new t(e),de=void 0,e}function Ne(t,e,n){const r=n||2&e?at:ot,i=!!(32&e);return t=function(t,e,n){const r=K(t);var i=r.length;const s=256&e?r[i-1]:void 0;for(i+=s?-1:0,e=512&e?1:0;e<i;e++)r[e]=n(r[e]);if(s){e=r[e]={};for(const t in s)e[t]=n(s[t])}return vt(r,t),r}(t,e,(t=>Ce(t,i,r))),tt(t,32|(n?2:0)),t}function De(t){const e=t.u,n=rt(e);return 2&n?Ue(t,e,n,!1):t}function Be(t,e){return je(t=t.u,rt(t),e)}function Ge(t,e,n,r){if(!((e=r+(+!!(512&e)-1))<0||e>=t.length||e>=n))return t[e]}function je(t,e,n,r){if(-1===n)return null;const i=e>>15&1023||536870912;if(!(n>=i)){var s=t.length;return r&&256&e&&null!=(r=t[s-1][n])?(Ge(t,e,i,n)&&null!=Z&&((e=(t=j??={})[Z]||0)>=4||(t[Z]=e+1,H())),r):Ge(t,e,i,n)}return 256&e?t[t.length-1][n]:void 0}function Ve(t,e,n){const r=t.u;let i=rt(r);return mt(i),Xe(r,i,e,n),t}function Xe(t,e,n,r){const i=e>>15&1023||536870912;if(n>=i){let s,o=e;if(256&e)s=t[t.length-1];else{if(null==r)return o;s=t[i+(+!!(512&e)-1)]={},o|=256}return s[n]=r,n<i&&(t[n+(+!!(512&e)-1)]=void 0),o!==e&&it(t,o),o}return t[n+(+!!(512&e)-1)]=r,256&e&&(n in(t=t[t.length-1])&&delete t[n]),e}function He(t,e){t=t.u;let n=rt(t);const r=je(t,n,e),i=Wt(r);return null!=i&&i!==r&&Xe(t,n,e,i),i}function We(t){t=t.u;let e=rt(t);const n=je(t,e,1),r=dt(n,!0);return null!=r&&r!==n&&Xe(t,e,1,r),r}function ze(){return void 0===Et?2:4}function Ke(t,e,n,r,i){const s=t.u,o=2&(t=rt(s))?1:r;i=!!i,r=Ye(s,t,e);var a=nt(r);if(!(4&a)){4&a&&(r=K(r),a=fn(a,t),t=Xe(s,t,e,r));let i=0,o=0;for(;i<r.length;i++){const t=n(r[i]);null!=t&&(r[o++]=t)}o<i&&(r.length=o),a=-4097&(20|(a=$e(a,t))),it(r,a&=-8193),2&a&&Object.freeze(r)}let c;return 1===o||4===o&&32&a?qe(a)||(i=a,(a|=2)!==i&&it(r,a),Object.freeze(r)):(n=5===o&&(!!(32&a)||qe(a)||!!ce?.get(r)),(2===o||n)&&qe(a)&&(r=K(r),a=dn(a=fn(a,t),t,i),it(r,a),t=Xe(s,t,e,r)),qe(a)||(e=a,(a=dn(a,t,i))!==e&&it(r,a)),n?c=ae(r):2!==o||i||ce?.delete(r)),c||r}function Ye(t,e,n,r){return t=je(t,e,n,r),Array.isArray(t)?t:ct}function $e(t,e){return 0===t&&(t=fn(t,e)),1|t}function qe(t){return!!(2&t)&&!!(4&t)||!!(2048&t)}function Je(t){t=K(t);for(let e=0;e<t.length;e++){const n=t[e]=K(t[e]);Array.isArray(n[1])&&(n[1]=st(n[1]))}return t}function Ze(t,e,n,r){t=t.u;let i=rt(t);mt(i),Xe(t,i,e,("0"===r?0===Number(n):n===r)?void 0:n)}function Qe(t,e,n,r,i){mt(e);var s=!(!(64&e)&&16384&e);const o=(i=Ye(t,e,n,i))!==ct;if(s||!o){let a=s=o?nt(i):0;(!o||2&a||qe(a)||4&a&&!(32&a))&&(i=K(i),a=fn(a,e),e=Xe(t,e,n,i)),a=-13&$e(a,e),a=dn(r?-17&a:16|a,e,!0),a!==s&&it(i,a)}return i}function tn(t,e){var n=As;return rn(en(t=t.u),t,rt(t),n)===e?e:-1}function en(t){if(Y)return t[Q]??(t[Q]=new Map);if(Q in t)return t[Q];const e=new Map;return Object.defineProperty(t,Q,{value:e}),e}function nn(t,e,n,r){const i=en(t),s=rn(i,t,e,n);return s!==r&&(s&&(e=Xe(t,e,s)),i.set(n,r)),e}function rn(t,e,n,r){let i=t.get(r);if(null!=i)return i;i=0;for(let t=0;t<r.length;t++){const s=r[t];null!=je(e,n,s)&&(0!==i&&(n=Xe(e,n,i)),i=s)}return t.set(r,i),i}function sn(t,e,n,r){let i,s=rt(t);if(null!=(r=je(t,s,n,r))&&r.X===ht)return(e=De(r))!==r&&Xe(t,s,n,e),e.u;if(Array.isArray(r)){const t=nt(r);i=2&t?ye(Ne(r,t,!1),e,!0):64&t?r:ye(i,e,!0)}else i=ye(void 0,e,!0);return i!==r&&Xe(t,s,n,i),i}function on(t,e,n,r){t=t.u;let i=rt(t);return(e=se(r=je(t,i,n,r),e,!1,i))!==r&&null!=e&&Xe(t,i,n,e),e}function an(t,e,n,r=!1){if(null==(e=on(t,e,n,r)))return e;if(t=t.u,!(2&(r=rt(t)))){const i=De(e);i!==e&&Xe(t,r,n,e=i)}return e}function cn(t,e,n,r,i,s,o){t=t.u;var a=!!(2&e);i=a?1:i,s=!!s,o&&=!a,a=Ye(t,e,r);var c=nt(a),h=!!(4&c);if(!h){var u=a,l=e;const t=!!(2&(c=$e(c,e)));t&&(l|=2);let r=!t,i=!0,s=0,o=0;for(;s<u.length;s++){const e=se(u[s],n,!1,l);if(e instanceof n){if(!t){const t=!!(2&nt(e.u));r&&=!t,i&&=t}u[o++]=e}}o<s&&(u.length=o),c|=4,c=i?16|c:-17&c,it(u,c=r?8|c:-9&c),t&&Object.freeze(u)}if(o&&!(8&c||!a.length&&(1===i||4===i&&32&c))){for(qe(c)&&(a=K(a),c=fn(c,e),e=Xe(t,e,r,a)),n=a,o=c,u=0;u<n.length;u++)(c=n[u])!==(l=De(c))&&(n[u]=l);o|=8,o=n.length?-17&o:16|o,it(n,o),c=o}let f;return 1===i||4===i&&32&c?qe(c)||(e=c,(c|=!a.length||16&c&&(!h||32&c)?2:2048)!==e&&it(a,c),Object.freeze(a)):(h=5===i&&(!!(32&c)||qe(c)||!!ce?.get(a)),(2===i||h)&&qe(c)&&(a=K(a),c=dn(c=fn(c,e),e,s),it(a,c),e=Xe(t,e,r,a)),qe(c)||(r=c,(c=dn(c,e,s))!==r&&it(a,c)),h?f=ae(a):2!==i||s||ce?.delete(a)),f||a}function hn(t,e,n){const r=rt(t.u);return cn(t,r,e,n,ze(),!1,!(2&r))}function un(t,e,n,r){return null==r&&(r=void 0),Ve(t,n,r)}function ln(t,e,n,r){null==r&&(r=void 0);t:{t=t.u;let i=rt(t);if(mt(i),null==r){const r=en(t);if(rn(r,t,i,n)!==e)break t;r.set(n,0)}else i=nn(t,i,n,e);Xe(t,i,e,r)}}function fn(t,e){return-2049&(t=32|(2&e?2|t:-3&t))}function dn(t,e,n){return 32&e&&n||(t&=-33),t}function pn(t,e,n,r){const i=rt(t.u);mt(i),t=cn(t,i,n,e,2,!0),r=null!=r?r:new n,t.push(r),2&nt(r.u)?et(t,8):et(t,16)}function gn(t,e){return t??e}function mn(t,e){return $t(Be(t,e))}function yn(t,e){return gn(He(t,e),0)}function _n(t,e){return gn(ie(Be(t,e)),"")}function vn(t,e,n){if(null!=n&&"boolean"!=typeof n)throw t=typeof n,Error(`Expected boolean but got ${"object"!=t?t:n?Array.isArray(n)?"array":t:"null"}: ${n}`);Ve(t,e,n)}function En(t,e,n){if(null!=n){if("number"!=typeof n)throw W("int32");if(!Number.isFinite(n))throw W("int32");n|=0}Ve(t,e,n)}function wn(t,e,n){if(null!=n&&"number"!=typeof n)throw Error(`Value of float/double field must be a number, found ${typeof n}: ${n}`);Ve(t,e,n)}function Tn(t,e,n){{const o=t.u;let a=rt(o);if(mt(a),null==n)Xe(o,a,e);else{n=he?.get(n)||n;var r=t=nt(n),i=qe(t),s=i||Object.isFrozen(n);for(i||(t=0),s||(n=K(n),r=0,t=dn(t=fn(t,a),a,!0),s=!1),t|=21,i=0;i<n.length;i++){const e=n[i],o=ne(e);Object.is(e,o)||(s&&(n=K(n),r=0,t=dn(t=fn(t,a),a,!0),s=!1),n[i]=o)}t!==r&&(s&&(n=K(n),t=dn(t=fn(t,a),a,!0)),it(n,t)),Xe(o,a,e,n)}}}function bn(t,e,n){mt(rt(t.u)),Ke(t,e,ie,2,!0).push(ne(n))}function An(t,e){return Error(`Invalid wire type: ${t} (at position ${e})`)}function kn(){return Error("Failed to read varint, encoding is invalid.")}function xn(t,e){return Error(`Tried to read past the end of the data ${e} > ${t}`)}function Sn(t){if("string"==typeof t)return{buffer:O(t),O:!1};if(Array.isArray(t))return{buffer:new Uint8Array(t),O:!1};if(t.constructor===Uint8Array)return{buffer:t,O:!1};if(t.constructor===ArrayBuffer)return{buffer:new Uint8Array(t),O:!1};if(t.constructor===B)return{buffer:D(t)||new Uint8Array(0),O:!0};if(t instanceof Uint8Array)return{buffer:new Uint8Array(t.buffer,t.byteOffset,t.byteLength),O:!1};throw Error("Type not convertible to a Uint8Array, expected a Uint8Array, an ArrayBuffer, a base64 encoded string, a ByteString or an Array of numbers")}function Ln(t,e){let n,r=0,i=0,s=0;const o=t.h;let a=t.g;do{n=o[a++],r|=(127&n)<<s,s+=7}while(s<32&&128&n);for(s>32&&(i|=(127&n)>>4),s=3;s<32&&128&n;s+=7)n=o[a++],i|=(127&n)<<s;if(Un(t,a),n<128)return e(r>>>0,i>>>0);throw kn()}function Rn(t){let e=0,n=t.g;const r=n+10,i=t.h;for(;n<r;){const r=i[n++];if(e|=r,0==(128&r))return Un(t,n),!!(127&e)}throw kn()}function Fn(t){const e=t.h;let n=t.g,r=e[n++],i=127&r;if(128&r&&(r=e[n++],i|=(127&r)<<7,128&r&&(r=e[n++],i|=(127&r)<<14,128&r&&(r=e[n++],i|=(127&r)<<21,128&r&&(r=e[n++],i|=r<<28,128&r&&128&e[n++]&&128&e[n++]&&128&e[n++]&&128&e[n++]&&128&e[n++])))))throw kn();return Un(t,n),i}function In(t){return Fn(t)>>>0}function Mn(t){var e=t.h;const n=t.g,r=e[n],i=e[n+1],s=e[n+2];return e=e[n+3],Un(t,t.g+4),(r<<0|i<<8|s<<16|e<<24)>>>0}function Pn(t){var e=Mn(t);t=2*(e>>31)+1;const n=e>>>23&255;return e&=8388607,255==n?e?NaN:t*(1/0):0==n?1401298464324817e-60*t*e:t*Math.pow(2,n-150)*(e+8388608)}function On(t){return Fn(t)}function Cn(t,e,{ca:n=!1}={}){t.ca=n,e&&(e=Sn(e),t.h=e.buffer,t.m=e.O,t.j=0,t.l=t.h.length,t.g=t.j)}function Un(t,e){if(t.g=e,e>t.l)throw xn(t.l,e)}function Nn(t,e){if(e<0)throw Error(`Tried to read a negative byte length: ${e}`);const n=t.g,r=n+e;if(r>t.l)throw xn(e,t.l-n);return t.g=r,n}function Dn(t,e){if(0==e)return N();var n=Nn(t,e);return t.ca&&t.m?n=t.h.subarray(n,n+e):(t=t.h,n=n===(e=n+e)?new Uint8Array(0):Mt?t.slice(n,e):new Uint8Array(t.subarray(n,e))),0==n.length?N():new B(n,U)}ke.prototype.toJSON=void 0,ke.prototype.Ia=ut;var Bn=[];function Gn(t){var e=t.g;if(e.g==e.l)return!1;t.l=t.g.g;var n=In(t.g);if(e=n>>>3,!((n&=7)>=0&&n<=5))throw An(n,t.l);if(e<1)throw Error(`Invalid field number: ${e} (at position ${t.l})`);return t.m=e,t.h=n,!0}function jn(t){switch(t.h){case 0:0!=t.h?jn(t):Rn(t.g);break;case 1:Un(t=t.g,t.g+8);break;case 2:if(2!=t.h)jn(t);else{var e=In(t.g);Un(t=t.g,t.g+e)}break;case 5:Un(t=t.g,t.g+4);break;case 3:for(e=t.m;;){if(!Gn(t))throw Error("Unmatched start-group tag: stream EOF");if(4==t.h){if(t.m!=e)throw Error("Unmatched end-group tag");break}jn(t)}break;default:throw An(t.h,t.l)}}function Vn(t,e,n){const r=t.g.l,i=In(t.g),s=t.g.g+i;let o=s-r;if(o<=0&&(t.g.l=s,n(e,t,void 0,void 0,void 0),o=s-t.g.g),o)throw Error(`Message parsing ended unexpectedly. Expected to read ${i} bytes, instead read ${i-o} bytes, either the data ended unexpectedly or the message misreported its own length`);return t.g.g=s,t.g.l=r,e}function Xn(t){var e=In(t.g),a=Nn(t=t.g,e);if(t=t.h,o){var c,h=t;(c=s)||(c=s=new TextDecoder("utf-8",{fatal:!0})),e=a+e,h=0===a&&e===h.length?h:h.subarray(a,e);try{var u=c.decode(h)}catch(t){if(void 0===i){try{c.decode(new Uint8Array([128]))}catch(t){}try{c.decode(new Uint8Array([97])),i=!0}catch(t){i=!1}}throw!i&&(s=void 0),t}}else{e=(u=a)+e,a=[];let i,s=null;for(;u<e;){var l=t[u++];l<128?a.push(l):l<224?u>=e?n():(i=t[u++],l<194||128!=(192&i)?(u--,n()):a.push((31&l)<<6|63&i)):l<240?u>=e-1?n():(i=t[u++],128!=(192&i)||224===l&&i<160||237===l&&i>=160||128!=(192&(c=t[u++]))?(u--,n()):a.push((15&l)<<12|(63&i)<<6|63&c)):l<=244?u>=e-2?n():(i=t[u++],128!=(192&i)||i-144+(l<<28)>>30!=0||128!=(192&(c=t[u++]))||128!=(192&(h=t[u++]))?(u--,n()):(l=(7&l)<<18|(63&i)<<12|(63&c)<<6|63&h,l-=65536,a.push(55296+(l>>10&1023),56320+(1023&l)))):n(),a.length>=8192&&(s=r(s,a),a.length=0)}u=r(s,a)}return u}function Hn(t){const e=In(t.g);return Dn(t.g,e)}function Wn(t,e,n){var r=In(t.g);for(r=t.g.g+r;t.g.g<r;)n.push(e(t.g))}var zn=[];let Kn;function Yn(t,e,n){e.g?e.m(t,e.g,e.h,n,!0):e.m(t,e.h,n,!0)}var $n=class{constructor(t,e){this.u=_e(t,e)}toJSON(){return qn(this)}l(){var t=Eo;return t.g?t.l(this,t.g,t.h,!0):t.l(this,t.h,t.defaultValue,!0)}clone(){const t=this.u;return Ue(this,t,rt(t),!1)}O(){return!!(2&nt(this.u))}};function qn(t){t=t.u,t=Kn?t:Me(t,Oe,void 0,void 0,!1);{var e=!Kn;let h=t.length;if(h){var n=t[h-1],r=ft(n);r?h--:n=void 0;var i=t;if(r){t:{var s,o=n,a=!1;if(o)for(let t in o)isNaN(+t)?(s??={})[t]=o[t]:(r=o[t],Array.isArray(r)&&(pt(r)||lt(r)&&0===r.size)&&(r=null),null==r&&(a=!0),null!=r&&((s??={})[t]=r));if(a||(s=o),s)for(let t in s){a=s;break t}a=null}o=null==a?null!=n:a!==n}for(;h>0&&(null==(s=i[h-1])||pt(s)||lt(s)&&0===s.size);h--)var c=!0;(i!==t||o||c)&&(e?(c||o||a)&&(i.length=h):i=Array.prototype.slice.call(i,0,h),a&&i.push(a)),c=i}else c=t}return c}function Jn(t){return t?/^\\d+$/.test(t)?(Xt(t),new Zn(Ot,Ct)):null:Qn||=new Zn(0,0)}$n.prototype.X=ht,$n.prototype.toString=function(){try{return Kn=!0,qn(this).toString()}finally{Kn=!1}};var Zn=class{constructor(t,e){this.h=t>>>0,this.g=e>>>0}};let Qn;function tr(t){return t?/^-?\\d+$/.test(t)?(Xt(t),new er(Ot,Ct)):null:nr||=new er(0,0)}var er=class{constructor(t,e){this.h=t>>>0,this.g=e>>>0}};let nr;function rr(t,e,n){for(;n>0||e>127;)t.g.push(127&e|128),e=(e>>>7|n<<25)>>>0,n>>>=7;t.g.push(e)}function ir(t,e){for(;e>127;)t.g.push(127&e|128),e>>>=7;t.g.push(e)}function sr(t,e){if(e>=0)ir(t,e);else{for(let n=0;n<9;n++)t.g.push(127&e|128),e>>=7;t.g.push(1)}}function or(t,e){t.g.push(e>>>0&255),t.g.push(e>>>8&255),t.g.push(e>>>16&255),t.g.push(e>>>24&255)}function ar(t,e){0!==e.length&&(t.l.push(e),t.h+=e.length)}function cr(t,e,n){ir(t.g,8*e+n)}function hr(t,e){return cr(t,e,2),e=t.g.end(),ar(t,e),e.push(t.h),e}function ur(t,e){var n=e.pop();for(n=t.h+t.g.length()-n;n>127;)e.push(127&n|128),n>>>=7,t.h++;e.push(n),t.h++}function lr(t,e,n){cr(t,e,2),ir(t.g,n.length),ar(t,t.g.end()),ar(t,n)}function fr(t,e,n,r){null!=n&&(e=hr(t,e),r(n,t),ur(t,e))}function dr(){const t=class{constructor(){throw Error()}};return Object.setPrototypeOf(t,t.prototype),t}var pr=dr(),gr=dr(),mr=dr(),yr=dr(),_r=dr(),vr=dr(),Er=dr(),wr=dr(),Tr=dr(),br=class{constructor(t,e,n){this.g=t,this.h=e,t=pr,this.l=!!t&&n===t||!1}};function Ar(t,e){return new br(t,e,pr)}function kr(t,e,n,r,i){fr(t,n,Ur(e,r),i)}const xr=Ar((function(t,e,n,r,i){return 2===t.h&&(Vn(t,sn(e,r,n),i),!0)}),kr),Sr=Ar((function(t,e,n,r,i){return 2===t.h&&(Vn(t,sn(e,r,n,!0),i),!0)}),kr);var Lr=Symbol(),Rr=Symbol(),Fr=Symbol(),Ir=Symbol();let Mr,Pr;function Or(t,e,n,r){var i=r[t];if(i)return i;(i={}).W=function(t){switch(typeof t){case"boolean":return pe||=[0,void 0,!0];case"number":return t>0?void 0:0===t?ge||=[0,void 0]:[-t,void 0];case"string":return[0,t];case"object":return t}}(r[0]);var s=r[1];let o=1;s&&s.constructor===Object&&(i.ha=s,"function"==typeof(s=r[++o])&&(i.ma=!0,Mr??=s,Pr??=r[o+1],s=r[o+=2]));const a={};for(;s&&Array.isArray(s)&&s.length&&"number"==typeof s[0]&&s[0]>0;){for(var c=0;c<s.length;c++)a[s[c]]=s;s=r[++o]}for(c=1;void 0!==s;){let t;"number"==typeof s&&(c+=s,s=r[++o]);var h=void 0;if(s instanceof br?t=s:(t=xr,o--),t?.l){s=r[++o],h=r;var u=o;"function"==typeof s&&(s=s(),h[u]=s),h=s}for(u=c+1,"number"==typeof(s=r[++o])&&s<0&&(u-=s,s=r[++o]);c<u;c++){const r=a[c];h?n(i,c,t,h,r):e(i,c,t,r)}}return r[t]=i}function Cr(t){return Array.isArray(t)?t[0]instanceof br?t:[Sr,t]:[t,void 0]}function Ur(t,e){return t instanceof $n?t.u:Array.isArray(t)?ye(t,e,!1):void 0}function Nr(t,e,n,r){const i=n.g;t[e]=r?(t,e,n)=>i(t,e,n,r):i}function Dr(t,e,n,r,i){const s=n.g;let o,a;t[e]=(t,e,n)=>s(t,e,n,a||=Or(Rr,Nr,Dr,r).W,o||=Br(r),i)}function Br(t){let e=t[Fr];if(null!=e)return e;const n=Or(Rr,Nr,Dr,t);return e=n.ma?(t,e)=>Mr(t,e,n):(t,e)=>{const r=rt(t);for(;Gn(e)&&4!=e.h;){var i=e.m,s=n[i];if(null==s){var o=n.ha;o&&(o=o[i])&&(null!=(o=Gr(o))&&(s=n[i]=o))}null!=s&&s(e,t,i)||(i=(s=e).l,jn(s),s.ga?s=void 0:(o=s.g.g-i,s.g.g=i,s=Dn(s.g,o)),i=t,s&&(_t||=Symbol(),(o=i[_t])?o.push(s):i[_t]=[s]))}return 16384&r&&st(t),!0},t[Fr]=e}function Gr(t){const e=(t=Cr(t))[0].g;if(t=t[1]){const n=Br(t),r=Or(Rr,Nr,Dr,t).W;return(t,i,s)=>e(t,i,s,r,n)}return e}function jr(t,e,n){t[e]=n.h}function Vr(t,e,n,r){let i,s;const o=n.h;t[e]=(t,e,n)=>o(t,e,n,s||=Or(Lr,jr,Vr,r).W,i||=Xr(r))}function Xr(t){let e=t[Ir];if(!e){const n=Or(Lr,jr,Vr,t);e=(t,e)=>Hr(t,e,n),t[Ir]=e}return e}function Hr(t,e,n){for(var r=nt(t),i=+!!(512&r)-1,s=t.length,o=512&r?1:0,a=s+(256&r?-1:0);o<a;o++){const r=t[o];if(null==r)continue;const s=o-i,a=Wr(n,s);a&&a(e,r,s)}if(256&r){r=t[s-1];for(const t in r)i=+t,Number.isNaN(i)||null!=(s=r[i])&&(a=Wr(n,i))&&a(e,s,i)}if(t=_t?t[_t]:void 0)for(ar(e,e.g.end()),n=0;n<t.length;n++)ar(e,D(t[n])||new Uint8Array(0))}function Wr(t,e){var n=t[e];if(n)return n;if((n=t.ha)&&(n=n[e])){var r=(n=Cr(n))[0].h;if(n=n[1]){const e=Xr(n),i=Or(Lr,jr,Vr,n).W;n=t.ma?Pr(i,e):(t,n,s)=>r(t,n,s,i,e)}else n=r;return t[e]=n}}function zr(t,e){if(Array.isArray(e)){var n=nt(e);if(4&n)return e;for(var r=0,i=0;r<e.length;r++){const n=t(e[r]);null!=n&&(e[i++]=n)}return i<r&&(e.length=i),it(e,-12289&(5|n)),2&n&&Object.freeze(e),e}}function Kr(t,e,n){return new br(t,e,n)}function Yr(t,e,n){return new br(t,e,n)}function $r(t,e,n){Xe(t,rt(t),e,n)}var qr=Ar((function(t,e,n,r,i){return 2===t.h&&(t=Vn(t,ye([void 0,void 0],r,!0),i),mt(r=rt(e)),(i=je(e,r,n))instanceof ke?0!=(2&i.M)?((i=i.Y()).push(t),Xe(e,r,n,i)):i.Na(t):Array.isArray(i)?(2&nt(i)&&Xe(e,r,n,i=Je(i)),i.push(t)):Xe(e,r,n,[t]),!0)}),(function(t,e,n,r,i){if(e instanceof ke)e.forEach(((e,s)=>{fr(t,n,ye([s,e],r,!1),i)}));else if(Array.isArray(e))for(let s=0;s<e.length;s++){const o=e[s];Array.isArray(o)&&fr(t,n,ye(o,r,!1),i)}}));function Jr(t,e,n){if(e=function(t){if(null==t)return t;const e=typeof t;if("bigint"===e)return String(BigInt.asIntN(64,t));if(Yt(t)){if("string"===e)return Qt(t);if("number"===e)return Zt(t)}}(e),null!=e){if("string"==typeof e)tr(e);if(null!=e)switch(cr(t,n,0),typeof e){case"number":t=t.g,Nt(e),rr(t,Ot,Ct);break;case"bigint":n=BigInt.asUintN(64,e),n=new er(Number(n&BigInt(4294967295)),Number(n>>BigInt(32))),rr(t.g,n.h,n.g);break;default:n=tr(e),rr(t.g,n.h,n.g)}}}function Zr(t,e,n){null!=(e=$t(e))&&null!=e&&(cr(t,n,0),sr(t.g,e))}function Qr(t,e,n){null!=(e=zt(e))&&(cr(t,n,0),t.g.g.push(e?1:0))}function ti(t,e,n){null!=(e=ie(e))&&lr(t,n,h(e))}function ei(t,e,n,r,i){fr(t,n,Ur(e,r),i)}function ni(t,e,n){null!=(e=null==e||"string"==typeof e||C(e)||e instanceof B?e:void 0)&&lr(t,n,Sn(e).buffer)}function ri(t,e,n){return(5===t.h||2===t.h)&&(e=Qe(e,rt(e),n,!1,!1),2==t.h?Wn(t,Pn,e):e.push(Pn(t.g)),!0)}var ii=Kr((function(t,e,n){if(1!==t.h)return!1;var r=t.g;t=Mn(r);const i=Mn(r);r=2*(i>>31)+1;const s=i>>>20&2047;return t=4294967296*(1048575&i)+t,$r(e,n,2047==s?t?NaN:r*(1/0):0==s?5e-324*r*t:r*Math.pow(2,s-1075)*(t+4503599627370496)),!0}),(function(t,e,n){null!=(e=Wt(e))&&(cr(t,n,1),t=t.g,(n=Pt||=new DataView(new ArrayBuffer(8))).setFloat64(0,+e,!0),Ot=n.getUint32(0,!0),Ct=n.getUint32(4,!0),or(t,Ot),or(t,Ct))}),dr()),si=Kr((function(t,e,n){return 5===t.h&&($r(e,n,Pn(t.g)),!0)}),(function(t,e,n){null!=(e=Wt(e))&&(cr(t,n,5),t=t.g,Dt(e),or(t,Ot))}),Er),oi=Yr(ri,(function(t,e,n){if(null!=(e=zr(Wt,e)))for(let o=0;o<e.length;o++){var r=t,i=n,s=e[o];null!=s&&(cr(r,i,5),r=r.g,Dt(s),or(r,Ot))}}),Er),ai=Yr(ri,(function(t,e,n){if(null!=(e=zr(Wt,e))&&e.length){cr(t,n,2),ir(t.g,4*e.length);for(let r=0;r<e.length;r++)n=t.g,Dt(e[r]),or(n,Ot)}}),Er),ci=Kr((function(t,e,n){return 0===t.h&&($r(e,n,Ln(t.g,Gt)),!0)}),Jr,vr),hi=Kr((function(t,e,n){return 0===t.h&&($r(e,n,0===(t=Ln(t.g,Gt))?void 0:t),!0)}),Jr,vr),ui=Kr((function(t,e,n){return 0===t.h&&($r(e,n,Ln(t.g,Bt)),!0)}),(function(t,e,n){if(null!=(e=ee(e))){if("string"==typeof e)Jn(e);if(null!=e)switch(cr(t,n,0),typeof e){case"number":t=t.g,Nt(e),rr(t,Ot,Ct);break;case"bigint":n=BigInt.asUintN(64,e),n=new Zn(Number(n&BigInt(4294967295)),Number(n>>BigInt(32))),rr(t.g,n.h,n.g);break;default:n=Jn(e),rr(t.g,n.h,n.g)}}}),dr()),li=Kr((function(t,e,n){return 0===t.h&&($r(e,n,Fn(t.g)),!0)}),Zr,yr),fi=Yr((function(t,e,n){return(0===t.h||2===t.h)&&(e=Qe(e,rt(e),n,!1,!1),2==t.h?Wn(t,Fn,e):e.push(Fn(t.g)),!0)}),(function(t,e,n){if(null!=(e=zr($t,e))&&e.length){n=hr(t,n);for(let n=0;n<e.length;n++)sr(t.g,e[n]);ur(t,n)}}),yr),di=Kr((function(t,e,n){return 0===t.h&&($r(e,n,0===(t=Fn(t.g))?void 0:t),!0)}),Zr,yr),pi=Kr((function(t,e,n){return 0===t.h&&($r(e,n,Rn(t.g)),!0)}),Qr,gr),gi=Kr((function(t,e,n){return 0===t.h&&($r(e,n,!1===(t=Rn(t.g))?void 0:t),!0)}),Qr,gr),mi=Yr((function(t,e,n){return 2===t.h&&(t=Xn(t),Qe(e,rt(e),n,!1).push(t),!0)}),(function(t,e,n){if(null!=(e=zr(ie,e)))for(let o=0;o<e.length;o++){var r=t,i=n,s=e[o];null!=s&&lr(r,i,h(s))}}),mr),yi=Kr((function(t,e,n){return 2===t.h&&($r(e,n,""===(t=Xn(t))?void 0:t),!0)}),ti,mr),_i=Kr((function(t,e,n){return 2===t.h&&($r(e,n,Xn(t)),!0)}),ti,mr),vi=function(t,e,n=pr){return new br(t,e,n)}((function(t,e,n,r,i){return 2===t.h&&(r=ye(void 0,r,!0),Qe(e,rt(e),n,!0).push(r),Vn(t,r,i),!0)}),(function(t,e,n,r,i){if(Array.isArray(e))for(let s=0;s<e.length;s++)ei(t,e[s],n,r,i)})),Ei=Ar((function(t,e,n,r,i,s){return 2===t.h&&(nn(e,nt(e),s,n),Vn(t,e=sn(e,r,n),i),!0)}),ei),wi=Kr((function(t,e,n){return 2===t.h&&($r(e,n,Hn(t)),!0)}),ni,wr),Ti=Yr((function(t,e,n){return(0===t.h||2===t.h)&&(e=Qe(e,rt(e),n,!1,!1),2==t.h?Wn(t,In,e):e.push(In(t.g)),!0)}),(function(t,e,n){if(null!=(e=zr(qt,e)))for(let o=0;o<e.length;o++){var r=t,i=n,s=e[o];null!=s&&(cr(r,i,0),ir(r.g,s))}}),_r),bi=Kr((function(t,e,n){return 0===t.h&&($r(e,n,0===(t=In(t.g))?void 0:t),!0)}),(function(t,e,n){null!=(e=qt(e))&&null!=e&&(cr(t,n,0),ir(t.g,e))}),_r),Ai=Kr((function(t,e,n){return 0===t.h&&($r(e,n,Fn(t.g)),!0)}),(function(t,e,n){null!=(e=$t(e))&&(e=parseInt(e,10),cr(t,n,0),sr(t.g,e))}),Tr);class ki{constructor(t,e){this.h=t,this.g=e,this.l=an,this.m=un,this.defaultValue=void 0}}function xi(t,e){return new ki(t,e)}function Si(t,e){return(n,r)=>{if(zn.length){const t=zn.pop();t.o(r),Cn(t.g,n,r),n=t}else n=new class{constructor(t,e){if(Bn.length){const n=Bn.pop();Cn(n,t,e),t=n}else t=new class{constructor(t,e){this.h=null,this.m=!1,this.g=this.l=this.j=0,Cn(this,t,e)}clear(){this.h=null,this.m=!1,this.g=this.l=this.j=0,this.ca=!1}}(t,e);this.g=t,this.l=this.g.g,this.h=this.m=-1,this.o(e)}o({ga:t=!1}={}){this.ga=t}}(n,r);try{const r=new t,s=r.u;Br(e)(s,n);var i=r}finally{n.g.clear(),n.m=-1,n.h=-1,zn.length<100&&zn.push(n)}return i}}function Li(t){return function(){const e=new class{constructor(){this.l=[],this.h=0,this.g=new class{constructor(){this.g=[]}length(){return this.g.length}end(){const t=this.g;return this.g=[],t}}}};Hr(this.u,e,Or(Lr,jr,Vr,t)),ar(e,e.g.end());const n=new Uint8Array(e.h),r=e.l,i=r.length;let s=0;for(let t=0;t<i;t++){const e=r[t];n.set(e,s),s+=e.length}return e.l=[n],n}}var Ri=class extends $n{constructor(t){super(t)}},Fi=[0,yi,Kr((function(t,e,n){return 2===t.h&&($r(e,n,(t=Hn(t))===N()?void 0:t),!0)}),(function(t,e,n){if(null!=e){if(e instanceof $n){const r=e.Qa;return void(r&&(e=r(e),null!=e&&lr(t,n,Sn(e).buffer)))}if(Array.isArray(e))return}ni(t,e,n)}),wr)];let Ii,Mi=globalThis.trustedTypes;function Pi(t){void 0===Ii&&(Ii=function(){let t=null;if(!Mi)return t;try{const e=t=>t;t=Mi.createPolicy("goog#html",{createHTML:e,createScript:e,createScriptURL:e})}catch(t){}return t}());var e=Ii;return new class{constructor(t){this.g=t}toString(){return this.g+""}}(e?e.createScriptURL(t):t)}function Oi(t,...e){if(0===e.length)return Pi(t[0]);let n=t[0];for(let r=0;r<e.length;r++)n+=encodeURIComponent(e[r])+t[r+1];return Pi(n)}var Ci=[0,li,Ai,pi,-1,fi,Ai,-1],Ui=class extends $n{constructor(){super()}},Ni=[0,pi,_i,pi,Ai,-1,Yr((function(t,e,n){return(0===t.h||2===t.h)&&(e=Qe(e,rt(e),n,!1,!1),2==t.h?Wn(t,On,e):e.push(Fn(t.g)),!0)}),(function(t,e,n){if(null!=(e=zr($t,e))&&e.length){n=hr(t,n);for(let n=0;n<e.length;n++)sr(t.g,e[n]);ur(t,n)}}),Tr),_i,-1,[0,pi,-1],Ai,pi,-1],Di=[0,_i,-2],Bi=class extends $n{constructor(){super()}},Gi=[0],ji=[0,li,pi,1,pi,-3],Vi=class extends $n{constructor(t){super(t,2)}},Xi={};Xi[336783863]=[0,_i,pi,-1,li,[0,[1,2,3,4,5,6,7],Ei,Gi,Ei,Ni,Ei,Di,Ei,ji,Ei,Ci,Ei,[0,_i,-2],Ei,[0,_i,Ai]],[0,_i],pi,[0,[1,3],[2,4],Ei,[0,fi],-1,Ei,[0,mi],-1,vi,[0,_i,-1]],_i];var Hi=[0,hi,-1,gi,-3,hi,fi,yi,di,hi,-1,gi,di,gi,-2,yi];function Wi(t,e){Ze(t,2,re(e),"")}function zi(t,e){bn(t,3,e)}function Ki(t,e){bn(t,4,e)}var Yi=class extends $n{constructor(t){super(t,500)}o(t){return un(this,0,7,t)}},$i=[-1,{}],qi=[0,_i,1,$i],Ji=[0,_i,mi,$i];function Zi(t,e){pn(t,1,Yi,e)}function Qi(t,e){bn(t,10,e)}function ts(t,e){bn(t,15,e)}var es=class extends $n{constructor(t){super(t,500)}o(t){return un(this,0,1001,t)}},ns=[-500,vi,[-500,yi,-1,mi,-3,[-2,Xi,pi],vi,Fi,di,-1,qi,Ji,vi,[0,yi,gi],yi,Hi,di,mi,987,mi],4,vi,[-500,_i,-1,[-1,{}],998,_i],vi,[-500,_i,mi,-1,[-2,{},pi],997,mi,-1],di,vi,[-500,_i,mi,$i,998,mi],mi,di,qi,Ji,vi,[0,yi,-1,$i],mi,-2,Hi,yi,-1,gi,[0,gi,bi],978,$i,vi,Fi];es.prototype.g=Li(ns);var rs=Si(es,ns),is=class extends $n{constructor(t){super(t)}},ss=class extends $n{constructor(t){super(t)}g(){return hn(this,is,1)}},os=[0,vi,[0,li,si,_i,-1]],as=Si(ss,os),cs=class extends $n{constructor(t){super(t)}},hs=class extends $n{constructor(t){super(t)}},us=class extends $n{constructor(t){super(t)}h(){return an(this,cs,2)}g(){return hn(this,hs,5)}},ls=Si(class extends $n{constructor(t){super(t)}},[0,mi,fi,ai,[0,Ai,[0,li,-3],[0,si,-3],[0,li,-1,[0,vi,[0,li,-2]]],vi,[0,si,-1,_i,si]],_i,-1,ci,vi,[0,li,si],mi,ci]),fs=class extends $n{constructor(t){super(t)}},ds=Si(class extends $n{constructor(t){super(t)}},[0,vi,[0,si,-4]]),ps=class extends $n{constructor(t){super(t)}},gs=Si(class extends $n{constructor(t){super(t)}},[0,vi,[0,si,-4]]),ms=class extends $n{constructor(t){super(t)}},ys=[0,li,-1,ai,Ai],_s=class extends $n{constructor(){super()}};_s.prototype.g=Li([0,si,-4,ci]);var vs=class extends $n{constructor(t){super(t)}},Es=Si(class extends $n{constructor(t){super(t)}},[0,vi,[0,1,li,_i,os],ci]),ws=class extends $n{constructor(t){super(t)}},Ts=class extends $n{constructor(t){super(t)}pa(){const t=We(this);return null==t?N():t}},bs=class extends $n{constructor(t){super(t)}},As=[1,2],ks=Si(class extends $n{constructor(t){super(t)}},[0,vi,[0,As,Ei,[0,ai],Ei,[0,wi],li,_i],ci]),xs=class extends $n{constructor(t){super(t)}},Ss=[0,_i,li,si,mi,-1],Ls=class extends $n{constructor(t){super(t)}},Rs=[0,pi,-1],Fs=class extends $n{constructor(t){super(t)}},Is=[1,2,3,4,5],Ms=class extends $n{constructor(t){super(t)}g(){return null!=We(this)}h(){return null!=ie(Be(this,2))}},Ps=class extends $n{constructor(t){super(t)}g(){return zt(Be(this,2))??!1}},Os=[0,wi,_i,[0,li,ci,-1],[0,ui,ci]],Cs=[0,Os,pi,[0,Is,Ei,ji,Ei,Ni,Ei,Ci,Ei,Gi,Ei,Di],Ai],Us=class extends $n{constructor(t){super(t)}},Ns=[0,Cs,si,-1,li],Ds=xi(502141897,Us);Xi[502141897]=Ns;var Bs=Si(class extends $n{constructor(t){super(t)}},[0,[0,Ai,-1,oi,Ti],ys]),Gs=class extends $n{constructor(t){super(t)}},js=class extends $n{constructor(t){super(t)}},Vs=[0,Cs,si,[0,Cs],pi],Xs=[0,Cs,Ns,Vs,si,[0,[0,Os]]],Hs=xi(508968150,js);Xi[508968150]=Xs,Xi[508968149]=Vs;var Ws=class extends $n{constructor(t){super(t)}},zs=xi(513916220,Ws);Xi[513916220]=[0,Cs,Xs,li];var Ks=class extends $n{constructor(t){super(t)}h(){return an(this,xs,2)}g(){Ve(this,2)}},Ys=[0,Cs,Ss];Xi[478825465]=Ys;var $s=class extends $n{constructor(t){super(t)}},qs=class extends $n{constructor(t){super(t)}},Js=class extends $n{constructor(t){super(t)}},Zs=class extends $n{constructor(t){super(t)}},Qs=class extends $n{constructor(t){super(t)}},to=[0,Cs,[0,Cs],Ys,-1],eo=[0,Cs,si,li],no=[0,Cs,si],ro=[0,Cs,eo,no,si],io=xi(479097054,Qs);Xi[479097054]=[0,Cs,ro,to],Xi[463370452]=to,Xi[464864288]=eo;var so=xi(462713202,Zs);Xi[462713202]=ro,Xi[474472470]=no;var oo=class extends $n{constructor(t){super(t)}},ao=class extends $n{constructor(t){super(t)}},co=class extends $n{constructor(t){super(t)}},ho=class extends $n{constructor(){super()}},uo=[0,Cs,si,-1,li],lo=[0,Cs,si,pi];ho.prototype.g=Li([0,Cs,no,[0,Cs],Ns,Vs,uo,lo]);var fo=class extends $n{constructor(t){super(t)}},po=xi(456383383,fo);Xi[456383383]=[0,Cs,Ss];var go=class extends $n{constructor(t){super(t)}},mo=xi(476348187,go);Xi[476348187]=[0,Cs,Rs];var yo=class extends $n{constructor(t){super(t)}},_o=class extends $n{constructor(t){super(t)}},vo=[0,Ai,-1],Eo=xi(458105876,class extends $n{constructor(t){super(t)}g(){var t=this.u;const e=rt(t);const n=2&e;return t=function(t,e,n){var r=_o;const i=2&e;let s=!1;if(null==n){if(i)return Fe();n=[]}else if(n.constructor===ke){if(0==(2&n.M)||i)return n;n=n.Y()}else Array.isArray(n)?s=!!(2&nt(n)):n=[];if(i){if(!n.length)return Fe();s||(s=!0,st(n))}else s&&(s=!1,n=Je(n));return s||(64&nt(n)?et(n,32):32&e&&tt(n,32)),Xe(t,e,2,r=new ke(n,r,oe,void 0)),r}(t,e,je(t,e,2)),!n&&_o&&(t.sa=!0),t}});Xi[458105876]=[0,vo,qr,[!0,ci,[0,_i,-1,mi]]];var wo=class extends $n{constructor(t){super(t)}},To=xi(458105758,wo);Xi[458105758]=[0,Cs,_i,vo];var bo=class extends $n{constructor(t){super(t)}},Ao=xi(443442058,bo);Xi[443442058]=[0,Cs,_i,li,si,mi,-1],Xi[514774813]=uo;var ko=class extends $n{constructor(t){super(t)}},xo=xi(516587230,ko);function So(t,e){return e=e?e.clone():new xs,void 0!==t.displayNamesLocale?Ve(e,1,re(t.displayNamesLocale)):void 0===t.displayNamesLocale&&Ve(e,1),void 0!==t.maxResults?En(e,2,t.maxResults):"maxResults"in t&&Ve(e,2),void 0!==t.scoreThreshold?wn(e,3,t.scoreThreshold):"scoreThreshold"in t&&Ve(e,3),void 0!==t.categoryAllowlist?Tn(e,4,t.categoryAllowlist):"categoryAllowlist"in t&&Ve(e,4),void 0!==t.categoryDenylist?Tn(e,5,t.categoryDenylist):"categoryDenylist"in t&&Ve(e,5),e}function Lo(t,e=-1,n=""){return{categories:t.map((t=>({index:gn(mn(t,1),0)??-1,score:yn(t,2)??0,categoryName:_n(t,3)??"",displayName:_n(t,4)??""}))),headIndex:e,headName:n}}function Ro(t){var e=Ke(t,3,Wt,ze()),n=Ke(t,2,$t,ze()),r=Ke(t,1,ie,ze()),i=Ke(t,9,ie,ze());const s={categories:[],keypoints:[]};for(let t=0;t<e.length;t++)s.categories.push({score:e[t],index:n[t]??-1,categoryName:r[t]??"",displayName:i[t]??""});if((e=an(t,us,4)?.h())&&(s.boundingBox={originX:mn(e,1)??0,originY:mn(e,2)??0,width:mn(e,3)??0,height:mn(e,4)??0,angle:0}),an(t,us,4)?.g().length)for(const e of an(t,us,4).g())s.keypoints.push({x:He(e,1)??0,y:He(e,2)??0,score:He(e,4)??0,label:ie(Be(e,3))??""});return s}function Fo(t){const e=[];for(const n of hn(t,ps,1))e.push({x:yn(n,1)??0,y:yn(n,2)??0,z:yn(n,3)??0,visibility:yn(n,4)??0});return e}function Io(t){const e=[];for(const n of hn(t,fs,1))e.push({x:yn(n,1)??0,y:yn(n,2)??0,z:yn(n,3)??0,visibility:yn(n,4)??0});return e}function Mo(t){return Array.from(t,(t=>t>127?t-256:t))}function Po(t,e){if(t.length!==e.length)throw Error(`Cannot compute cosine similarity between embeddings of different sizes (${t.length} vs. ${e.length}).`);let n=0,r=0,i=0;for(let s=0;s<t.length;s++)n+=t[s]*e[s],r+=t[s]*t[s],i+=e[s]*e[s];if(r<=0||i<=0)throw Error("Cannot compute cosine similarity on embedding with 0 norm.");return n/Math.sqrt(r*i)}let Oo;Xi[516587230]=[0,Cs,uo,lo,si],Xi[518928384]=lo;const Co=new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,10,1,8,0,65,0,253,15,253,98,11]);async function Uo(){if(void 0===Oo)try{await WebAssembly.instantiate(Co),Oo=!0}catch{Oo=!1}return Oo}async function No(t,e=Oi``){const n=await Uo()?"wasm_internal":"wasm_nosimd_internal";return{wasmLoaderPath:`${e}/${t}_${n}.js`,wasmBinaryPath:`${e}/${t}_${n}.wasm`}}var Do=class{};function Bo(){var t=navigator;return"undefined"!=typeof OffscreenCanvas&&(!function(t=navigator){return(t=t.userAgent).includes("Safari")&&!t.includes("Chrome")}(t)||!!((t=t.userAgent.match(/Version\\/([\\d]+).*Safari/))&&t.length>=1&&Number(t[1])>=17))}async function Go(t){if("function"!=typeof importScripts){const e=document.createElement("script");return e.src=t.toString(),e.crossOrigin="anonymous",new Promise(((t,n)=>{e.addEventListener("load",(()=>{t()}),!1),e.addEventListener("error",(t=>{n(t)}),!1),document.body.appendChild(e)}))}importScripts(t.toString())}function jo(t){return void 0!==t.videoWidth?[t.videoWidth,t.videoHeight]:void 0!==t.naturalWidth?[t.naturalWidth,t.naturalHeight]:void 0!==t.displayWidth?[t.displayWidth,t.displayHeight]:[t.width,t.height]}function Vo(t,e,n){t.m||console.error("No wasm multistream support detected: ensure dependency inclusion of :gl_graph_runner_internal_multi_input target"),n(e=t.i.stringToNewUTF8(e)),t.i._free(e)}function Xo(t,e,n){if(!t.i.canvas)throw Error("No OpenGL canvas configured.");if(n?t.i._bindTextureToStream(n):t.i._bindTextureToCanvas(),!(n=t.i.canvas.getContext("webgl2")||t.i.canvas.getContext("webgl")))throw Error("Failed to obtain WebGL context from the provided canvas. `getContext()` should only be invoked with `webgl` or `webgl2`.");t.i.gpuOriginForWebTexturesIsBottomLeft&&n.pixelStorei(n.UNPACK_FLIP_Y_WEBGL,!0),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,e),t.i.gpuOriginForWebTexturesIsBottomLeft&&n.pixelStorei(n.UNPACK_FLIP_Y_WEBGL,!1);const[r,i]=jo(e);return!t.l||r===t.i.canvas.width&&i===t.i.canvas.height||(t.i.canvas.width=r,t.i.canvas.height=i),[r,i]}function Ho(t,e,n){t.m||console.error("No wasm multistream support detected: ensure dependency inclusion of :gl_graph_runner_internal_multi_input target");const r=new Uint32Array(e.length);for(let n=0;n<e.length;n++)r[n]=t.i.stringToNewUTF8(e[n]);e=t.i._malloc(4*r.length),t.i.HEAPU32.set(r,e>>2),n(e);for(const e of r)t.i._free(e);t.i._free(e)}function Wo(t,e,n){t.i.simpleListeners=t.i.simpleListeners||{},t.i.simpleListeners[e]=n}function zo(t,e,n){let r=[];t.i.simpleListeners=t.i.simpleListeners||{},t.i.simpleListeners[e]=(t,e,i)=>{e?(n(r,i),r=[]):r.push(t)}}Do.forVisionTasks=function(t){return No("vision",t)},Do.forTextTasks=function(t){return No("text",t)},Do.forGenAiExperimentalTasks=function(t){return No("genai_experimental",t)},Do.forGenAiTasks=function(t){return No("genai",t)},Do.forAudioTasks=function(t){return No("audio",t)},Do.isSimdSupported=function(){return Uo()};async function Ko(t,e,n,r){return t=await(async(t,e,n,r,i)=>{if(e&&await Go(e),!self.ModuleFactory)throw Error("ModuleFactory not set.");if(n&&(await Go(n),!self.ModuleFactory))throw Error("ModuleFactory not set.");return self.Module&&i&&((e=self.Module).locateFile=i.locateFile,i.mainScriptUrlOrBlob&&(e.mainScriptUrlOrBlob=i.mainScriptUrlOrBlob)),i=await self.ModuleFactory(self.Module||i),self.ModuleFactory=self.Module=void 0,new t(i,r)})(t,n.wasmLoaderPath,n.assetLoaderPath,e,{locateFile:t=>t.endsWith(".wasm")?n.wasmBinaryPath.toString():n.assetBinaryPath&&t.endsWith(".data")?n.assetBinaryPath.toString():t}),await t.o(r),t}function Yo(t,e){const n=an(t.baseOptions,Ms,1)||new Ms;"string"==typeof e?(Ve(n,2,re(e)),Ve(n,1)):e instanceof Uint8Array&&(Ve(n,1,dt(e,!1)),Ve(n,2)),un(t.baseOptions,0,1,n)}function $o(t){try{const e=t.H.length;if(1===e)throw Error(t.H[0].message);if(e>1)throw Error("Encountered multiple errors: "+t.H.map((t=>t.message)).join(", "))}finally{t.H=[]}}function qo(t,e){t.B=Math.max(t.B,e)}function Jo(t,e){t.A=new Yi,Wi(t.A,"PassThroughCalculator"),zi(t.A,"free_memory"),Ki(t.A,"free_memory_unused_out"),Qi(e,"free_memory"),Zi(e,t.A)}function Zo(t,e){zi(t.A,e),Ki(t.A,e+"_unused_out")}function Qo(t){t.g.addBoolToStream(!0,"free_memory",t.B)}var ta=class{constructor(t){this.g=t,this.H=[],this.B=0,this.g.setAutoRenderToScreen(!1)}l(t,e=!0){if(e){const e=t.baseOptions||{};if(t.baseOptions?.modelAssetBuffer&&t.baseOptions?.modelAssetPath)throw Error("Cannot set both baseOptions.modelAssetPath and baseOptions.modelAssetBuffer");if(!(an(this.baseOptions,Ms,1)?.g()||an(this.baseOptions,Ms,1)?.h()||t.baseOptions?.modelAssetBuffer||t.baseOptions?.modelAssetPath))throw Error("Either baseOptions.modelAssetPath or baseOptions.modelAssetBuffer must be set");if(function(t,e){let n=an(t.baseOptions,Fs,3);if(!n){var r=n=new Fs,i=new Bi;ln(r,4,Is,i)}"delegate"in e&&("GPU"===e.delegate?(e=n,r=new Ui,ln(e,2,Is,r)):(e=n,r=new Bi,ln(e,4,Is,r))),un(t.baseOptions,0,3,n)}(this,e),e.modelAssetPath)return fetch(e.modelAssetPath.toString()).then((t=>{if(t.ok)return t.arrayBuffer();throw Error(`Failed to fetch model: ${e.modelAssetPath} (${t.status})`)})).then((t=>{try{this.g.i.FS_unlink("/model.dat")}catch{}this.g.i.FS_createDataFile("/","model.dat",new Uint8Array(t),!0,!1,!1),Yo(this,"/model.dat"),this.m(),this.J()}));if(e.modelAssetBuffer instanceof Uint8Array)Yo(this,e.modelAssetBuffer);else if(e.modelAssetBuffer)return async function(t){const e=[];for(var n=0;;){const{done:r,value:i}=await t.read();if(r)break;e.push(i),n+=i.length}if(0===e.length)return new Uint8Array(0);if(1===e.length)return e[0];t=new Uint8Array(n),n=0;for(const r of e)t.set(r,n),n+=r.length;return t}(e.modelAssetBuffer).then((t=>{Yo(this,t),this.m(),this.J()}))}return this.m(),this.J(),Promise.resolve()}J(){}ea(){let t;if(this.g.ea((e=>{t=rs(e)})),!t)throw Error("Failed to retrieve CalculatorGraphConfig");return t}setGraph(t,e){this.g.attachErrorListener(((t,e)=>{this.H.push(Error(e))})),this.g.La(),this.g.setGraph(t,e),this.A=void 0,$o(this)}finishProcessing(){this.g.finishProcessing(),$o(this)}close(){this.A=void 0,this.g.closeGraph()}};function ea(t,e){if(!t)throw Error(`Unable to obtain required WebGL resource: ${e}`);return t}ta.prototype.close=ta.prototype.close,e("TaskRunner",ta);class na{constructor(t,e,n,r){this.g=t,this.h=e,this.m=n,this.l=r}bind(){this.g.bindVertexArray(this.h)}close(){this.g.deleteVertexArray(this.h),this.g.deleteBuffer(this.m),this.g.deleteBuffer(this.l)}}function ra(t,e,n){const r=t.g;if(n=ea(r.createShader(n),"Failed to create WebGL shader"),r.shaderSource(n,e),r.compileShader(n),!r.getShaderParameter(n,r.COMPILE_STATUS))throw Error(`Could not compile WebGL shader: ${r.getShaderInfoLog(n)}`);return r.attachShader(t.h,n),n}function ia(t,e){const n=t.g,r=ea(n.createVertexArray(),"Failed to create vertex array");n.bindVertexArray(r);const i=ea(n.createBuffer(),"Failed to create buffer");n.bindBuffer(n.ARRAY_BUFFER,i),n.enableVertexAttribArray(t.P),n.vertexAttribPointer(t.P,2,n.FLOAT,!1,0,0),n.bufferData(n.ARRAY_BUFFER,new Float32Array([-1,-1,-1,1,1,1,1,-1]),n.STATIC_DRAW);const s=ea(n.createBuffer(),"Failed to create buffer");return n.bindBuffer(n.ARRAY_BUFFER,s),n.enableVertexAttribArray(t.J),n.vertexAttribPointer(t.J,2,n.FLOAT,!1,0,0),n.bufferData(n.ARRAY_BUFFER,new Float32Array(e?[0,1,0,0,1,0,1,1]:[0,0,0,1,1,1,1,0]),n.STATIC_DRAW),n.bindBuffer(n.ARRAY_BUFFER,null),n.bindVertexArray(null),new na(n,r,i,s)}function sa(t,e){if(t.g){if(e!==t.g)throw Error("Cannot change GL context once initialized")}else t.g=e}function oa(t,e,n,r){return sa(t,e),t.h||(t.m(),t.C()),n?(t.s||(t.s=ia(t,!0)),n=t.s):(t.v||(t.v=ia(t,!1)),n=t.v),e.useProgram(t.h),n.bind(),t.l(),t=r(),n.g.bindVertexArray(null),t}function aa(t,e,n){return sa(t,e),t=ea(e.createTexture(),"Failed to create texture"),e.bindTexture(e.TEXTURE_2D,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,n??e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,n??e.LINEAR),e.bindTexture(e.TEXTURE_2D,null),t}function ca(t,e,n){sa(t,e),t.A||(t.A=ea(e.createFramebuffer(),"Failed to create framebuffe.")),e.bindFramebuffer(e.FRAMEBUFFER,t.A),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,n,0)}function ha(t){t.g?.bindFramebuffer(t.g.FRAMEBUFFER,null)}var ua=class{H(){return"\\n precision mediump float;\\n varying vec2 vTex;\\n uniform sampler2D inputTexture;\\n void main() {\\n gl_FragColor = texture2D(inputTexture, vTex);\\n }\\n "}m(){const t=this.g;if(this.h=ea(t.createProgram(),"Failed to create WebGL program"),this.ba=ra(this,"\\n attribute vec2 aVertex;\\n attribute vec2 aTex;\\n varying vec2 vTex;\\n void main(void) {\\n gl_Position = vec4(aVertex, 0.0, 1.0);\\n vTex = aTex;\\n }",t.VERTEX_SHADER),this.aa=ra(this,this.H(),t.FRAGMENT_SHADER),t.linkProgram(this.h),!t.getProgramParameter(this.h,t.LINK_STATUS))throw Error(`Error during program linking: ${t.getProgramInfoLog(this.h)}`);this.P=t.getAttribLocation(this.h,"aVertex"),this.J=t.getAttribLocation(this.h,"aTex")}C(){}l(){}close(){if(this.h){const t=this.g;t.deleteProgram(this.h),t.deleteShader(this.ba),t.deleteShader(this.aa)}this.A&&this.g.deleteFramebuffer(this.A),this.v&&this.v.close(),this.s&&this.s.close()}};var la=class extends ua{H(){return"\\n precision mediump float;\\n uniform sampler2D backgroundTexture;\\n uniform sampler2D maskTexture;\\n uniform sampler2D colorMappingTexture;\\n varying vec2 vTex;\\n void main() {\\n vec4 backgroundColor = texture2D(backgroundTexture, vTex);\\n float category = texture2D(maskTexture, vTex).r;\\n vec4 categoryColor = texture2D(colorMappingTexture, vec2(category, 0.0));\\n gl_FragColor = mix(backgroundColor, categoryColor, categoryColor.a);\\n }\\n "}C(){const t=this.g;t.activeTexture(t.TEXTURE1),this.B=aa(this,t,t.LINEAR),t.activeTexture(t.TEXTURE2),this.j=aa(this,t,t.NEAREST)}m(){super.m();const t=this.g;this.L=ea(t.getUniformLocation(this.h,"backgroundTexture"),"Uniform location"),this.U=ea(t.getUniformLocation(this.h,"colorMappingTexture"),"Uniform location"),this.K=ea(t.getUniformLocation(this.h,"maskTexture"),"Uniform location")}l(){super.l();const t=this.g;t.uniform1i(this.K,0),t.uniform1i(this.L,1),t.uniform1i(this.U,2)}close(){this.B&&this.g.deleteTexture(this.B),this.j&&this.g.deleteTexture(this.j),super.close()}},fa=class extends ua{H(){return"\\n precision mediump float;\\n uniform sampler2D maskTexture;\\n uniform sampler2D defaultTexture;\\n uniform sampler2D overlayTexture;\\n varying vec2 vTex;\\n void main() {\\n float confidence = texture2D(maskTexture, vTex).r;\\n vec4 defaultColor = texture2D(defaultTexture, vTex);\\n vec4 overlayColor = texture2D(overlayTexture, vTex);\\n // Apply the alpha from the overlay and merge in the default color\\n overlayColor = mix(defaultColor, overlayColor, overlayColor.a);\\n gl_FragColor = mix(defaultColor, overlayColor, confidence);\\n }\\n "}C(){const t=this.g;t.activeTexture(t.TEXTURE1),this.j=aa(this,t),t.activeTexture(t.TEXTURE2),this.B=aa(this,t)}m(){super.m();const t=this.g;this.K=ea(t.getUniformLocation(this.h,"defaultTexture"),"Uniform location"),this.L=ea(t.getUniformLocation(this.h,"overlayTexture"),"Uniform location"),this.I=ea(t.getUniformLocation(this.h,"maskTexture"),"Uniform location")}l(){super.l();const t=this.g;t.uniform1i(this.I,0),t.uniform1i(this.K,1),t.uniform1i(this.L,2)}close(){this.j&&this.g.deleteTexture(this.j),this.B&&this.g.deleteTexture(this.B),super.close()}};function da(t,e){switch(e){case 0:return t.g.find((t=>t instanceof Uint8Array));case 1:return t.g.find((t=>t instanceof Float32Array));case 2:return t.g.find((t=>"undefined"!=typeof WebGLTexture&&t instanceof WebGLTexture));default:throw Error(`Type is not supported: ${e}`)}}function pa(t){var e=da(t,1);if(!e){if(e=da(t,0))e=new Float32Array(e).map((t=>t/255));else{e=new Float32Array(t.width*t.height);const r=ma(t);var n=_a(t);if(ca(n,r,ga(t)),"iPad Simulator;iPhone Simulator;iPod Simulator;iPad;iPhone;iPod".split(";").includes(navigator.platform)||navigator.userAgent.includes("Mac")&&"document"in self&&"ontouchend"in self.document){n=new Float32Array(t.width*t.height*4),r.readPixels(0,0,t.width,t.height,r.RGBA,r.FLOAT,n);for(let t=0,r=0;t<e.length;++t,r+=4)e[t]=n[r]}else r.readPixels(0,0,t.width,t.height,r.RED,r.FLOAT,e)}t.g.push(e)}return e}function ga(t){let e=da(t,2);if(!e){const n=ma(t);e=va(t);const r=pa(t),i=ya(t);n.texImage2D(n.TEXTURE_2D,0,i,t.width,t.height,0,n.RED,n.FLOAT,r),Ea(t)}return e}function ma(t){if(!t.canvas)throw Error("Conversion to different image formats require that a canvas is passed when initializing the image.");return t.h||(t.h=ea(t.canvas.getContext("webgl2"),"You cannot use a canvas that is already bound to a different type of rendering context.")),t.h}function ya(t){if(t=ma(t),!wa)if(t.getExtension("EXT_color_buffer_float")&&t.getExtension("OES_texture_float_linear")&&t.getExtension("EXT_float_blend"))wa=t.R32F;else{if(!t.getExtension("EXT_color_buffer_half_float"))throw Error("GPU does not fully support 4-channel float32 or float16 formats");wa=t.R16F}return wa}function _a(t){return t.l||(t.l=new ua),t.l}function va(t){const e=ma(t);e.viewport(0,0,t.width,t.height),e.activeTexture(e.TEXTURE0);let n=da(t,2);return n||(n=aa(_a(t),e,t.m?e.LINEAR:e.NEAREST),t.g.push(n),t.j=!0),e.bindTexture(e.TEXTURE_2D,n),n}function Ea(t){t.h.bindTexture(t.h.TEXTURE_2D,null)}var wa,Ta=class{constructor(t,e,n,r,i,s,o){this.g=t,this.m=e,this.j=n,this.canvas=r,this.l=i,this.width=s,this.height=o,this.j&&(0===--ba&&console.error("You seem to be creating MPMask instances without invoking .close(). This leaks resources."))}Ga(){return!!da(this,0)}ka(){return!!da(this,1)}R(){return!!da(this,2)}ja(){return(e=da(t=this,0))||(e=pa(t),e=new Uint8Array(e.map((t=>255*t))),t.g.push(e)),e;var t,e}ia(){return pa(this)}N(){return ga(this)}clone(){const t=[];for(const e of this.g){let n;if(e instanceof Uint8Array)n=new Uint8Array(e);else if(e instanceof Float32Array)n=new Float32Array(e);else{if(!(e instanceof WebGLTexture))throw Error(`Type is not supported: ${e}`);{const t=ma(this),e=_a(this);t.activeTexture(t.TEXTURE1),n=aa(e,t,this.m?t.LINEAR:t.NEAREST),t.bindTexture(t.TEXTURE_2D,n);const r=ya(this);t.texImage2D(t.TEXTURE_2D,0,r,this.width,this.height,0,t.RED,t.FLOAT,null),t.bindTexture(t.TEXTURE_2D,null),ca(e,t,n),oa(e,t,!1,(()=>{va(this),t.clearColor(0,0,0,0),t.clear(t.COLOR_BUFFER_BIT),t.drawArrays(t.TRIANGLE_FAN,0,4),Ea(this)})),ha(e),Ea(this)}}t.push(n)}return new Ta(t,this.m,this.R(),this.canvas,this.l,this.width,this.height)}close(){this.j&&ma(this).deleteTexture(da(this,2)),ba=-1}};Ta.prototype.close=Ta.prototype.close,Ta.prototype.clone=Ta.prototype.clone,Ta.prototype.getAsWebGLTexture=Ta.prototype.N,Ta.prototype.getAsFloat32Array=Ta.prototype.ia,Ta.prototype.getAsUint8Array=Ta.prototype.ja,Ta.prototype.hasWebGLTexture=Ta.prototype.R,Ta.prototype.hasFloat32Array=Ta.prototype.ka,Ta.prototype.hasUint8Array=Ta.prototype.Ga;var ba=250;const Aa={color:"white",lineWidth:4,radius:6};function ka(t){return{...Aa,fillColor:(t=t||{}).color,...t}}function xa(t,e){return t instanceof Function?t(e):t}function Sa(t,e,n){return Math.max(Math.min(e,n),Math.min(Math.max(e,n),t))}function La(t){if(!t.l)throw Error("CPU rendering requested but CanvasRenderingContext2D not provided.");return t.l}function Ra(t){if(!t.j)throw Error("GPU rendering requested but WebGL2RenderingContext not provided.");return t.j}function Fa(t,e,n){if(e.R())n(e.N());else{const r=e.ka()?e.ia():e.ja();t.m=t.m??new ua;const i=Ra(t);n((t=new Ta([r],e.m,!1,i.canvas,t.m,e.width,e.height)).N()),t.close()}}function Ia(t,e,n,r){const i=function(t){return t.g||(t.g=new la),t.g}(t),s=Ra(t),o=Array.isArray(n)?new ImageData(new Uint8ClampedArray(n),1,1):n;oa(i,s,!0,(()=>{!function(t,e,n,r){const i=t.g;if(i.activeTexture(i.TEXTURE0),i.bindTexture(i.TEXTURE_2D,e),i.activeTexture(i.TEXTURE1),i.bindTexture(i.TEXTURE_2D,t.B),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,i.RGBA,i.UNSIGNED_BYTE,n),t.I&&function(t,e){if(t!==e)return!1;t=t.entries(),e=e.entries();for(const[r,i]of t){t=r;const s=i;var n=e.next();if(n.done)return!1;const[o,a]=n.value;if(n=a,t!==o||s[0]!==n[0]||s[1]!==n[1]||s[2]!==n[2]||s[3]!==n[3])return!1}return!!e.next().done}(t.I,r))i.activeTexture(i.TEXTURE2),i.bindTexture(i.TEXTURE_2D,t.j);else{t.I=r;const e=Array(1024).fill(0);r.forEach(((t,n)=>{if(4!==t.length)throw Error(`Color at index ${n} is not a four-channel value.`);e[4*n]=t[0],e[4*n+1]=t[1],e[4*n+2]=t[2],e[4*n+3]=t[3]})),i.activeTexture(i.TEXTURE2),i.bindTexture(i.TEXTURE_2D,t.j),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,256,1,0,i.RGBA,i.UNSIGNED_BYTE,new Uint8Array(e))}}(i,e,o,r),s.clearColor(0,0,0,0),s.clear(s.COLOR_BUFFER_BIT),s.drawArrays(s.TRIANGLE_FAN,0,4);const t=i.g;t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,null),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,null),t.activeTexture(t.TEXTURE2),t.bindTexture(t.TEXTURE_2D,null)}))}function Ma(t,e,n,r){const i=Ra(t),s=function(t){return t.h||(t.h=new fa),t.h}(t),o=Array.isArray(n)?new ImageData(new Uint8ClampedArray(n),1,1):n,a=Array.isArray(r)?new ImageData(new Uint8ClampedArray(r),1,1):r;oa(s,i,!0,(()=>{var t=s.g;t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,e),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,s.j),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,o),t.activeTexture(t.TEXTURE2),t.bindTexture(t.TEXTURE_2D,s.B),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,a),i.clearColor(0,0,0,0),i.clear(i.COLOR_BUFFER_BIT),i.drawArrays(i.TRIANGLE_FAN,0,4),i.bindTexture(i.TEXTURE_2D,null),(t=s.g).activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,null),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,null),t.activeTexture(t.TEXTURE2),t.bindTexture(t.TEXTURE_2D,null)}))}var Pa=class{constructor(t,e){t instanceof CanvasRenderingContext2D||t instanceof OffscreenCanvasRenderingContext2D?(this.l=t,this.j=e):this.j=t}za(t,e){if(t){var n=La(this);e=ka(e),n.save();var r=n.canvas,i=0;for(const s of t)n.fillStyle=xa(e.fillColor,{index:i,from:s}),n.strokeStyle=xa(e.color,{index:i,from:s}),n.lineWidth=xa(e.lineWidth,{index:i,from:s}),(t=new Path2D).arc(s.x*r.width,s.y*r.height,xa(e.radius,{index:i,from:s}),0,2*Math.PI),n.fill(t),n.stroke(t),++i;n.restore()}}ya(t,e,n){if(t&&e){var r=La(this);n=ka(n),r.save();var i=r.canvas,s=0;for(const o of e){r.beginPath(),e=t[o.start];const a=t[o.end];e&&a&&(r.strokeStyle=xa(n.color,{index:s,from:e,to:a}),r.lineWidth=xa(n.lineWidth,{index:s,from:e,to:a}),r.moveTo(e.x*i.width,e.y*i.height),r.lineTo(a.x*i.width,a.y*i.height)),++s,r.stroke()}r.restore()}}va(t,e){const n=La(this);e=ka(e),n.save(),n.beginPath(),n.lineWidth=xa(e.lineWidth,{}),n.strokeStyle=xa(e.color,{}),n.fillStyle=xa(e.fillColor,{}),n.moveTo(t.originX,t.originY),n.lineTo(t.originX+t.width,t.originY),n.lineTo(t.originX+t.width,t.originY+t.height),n.lineTo(t.originX,t.originY+t.height),n.lineTo(t.originX,t.originY),n.stroke(),n.fill(),n.restore()}wa(t,e,n=[0,0,0,255]){this.l?function(t,e,n,r){const i=Ra(t);Fa(t,e,(e=>{Ia(t,e,n,r),(e=La(t)).drawImage(i.canvas,0,0,e.canvas.width,e.canvas.height)}))}(this,t,n,e):Ia(this,t.N(),n,e)}xa(t,e,n){this.l?function(t,e,n,r){const i=Ra(t);Fa(t,e,(e=>{Ma(t,e,n,r),(e=La(t)).drawImage(i.canvas,0,0,e.canvas.width,e.canvas.height)}))}(this,t,e,n):Ma(this,t.N(),e,n)}close(){this.g?.close(),this.g=void 0,this.h?.close(),this.h=void 0,this.m?.close(),this.m=void 0}};function Oa(t,e){switch(e){case 0:return t.g.find((t=>t instanceof ImageData));case 1:return t.g.find((t=>"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap));case 2:return t.g.find((t=>"undefined"!=typeof WebGLTexture&&t instanceof WebGLTexture));default:throw Error(`Type is not supported: ${e}`)}}function Ca(t){var e=Oa(t,0);if(!e){e=Na(t);const n=Da(t),r=new Uint8Array(t.width*t.height*4);ca(n,e,Ua(t)),e.readPixels(0,0,t.width,t.height,e.RGBA,e.UNSIGNED_BYTE,r),ha(n),e=new ImageData(new Uint8ClampedArray(r.buffer),t.width,t.height),t.g.push(e)}return e}function Ua(t){let e=Oa(t,2);if(!e){const n=Na(t);e=Ba(t);const r=Oa(t,1)||Ca(t);n.texImage2D(n.TEXTURE_2D,0,n.RGBA,n.RGBA,n.UNSIGNED_BYTE,r),Ga(t)}return e}function Na(t){if(!t.canvas)throw Error("Conversion to different image formats require that a canvas is passed when iniitializing the image.");return t.h||(t.h=ea(t.canvas.getContext("webgl2"),"You cannot use a canvas that is already bound to a different type of rendering context.")),t.h}function Da(t){return t.l||(t.l=new ua),t.l}function Ba(t){const e=Na(t);e.viewport(0,0,t.width,t.height),e.activeTexture(e.TEXTURE0);let n=Oa(t,2);return n||(n=aa(Da(t),e),t.g.push(n),t.m=!0),e.bindTexture(e.TEXTURE_2D,n),n}function Ga(t){t.h.bindTexture(t.h.TEXTURE_2D,null)}function ja(t){const e=Na(t);return oa(Da(t),e,!0,(()=>function(t,e){const n=t.canvas;if(n.width===t.width&&n.height===t.height)return e();const r=n.width,i=n.height;return n.width=t.width,n.height=t.height,t=e(),n.width=r,n.height=i,t}(t,(()=>{if(e.bindFramebuffer(e.FRAMEBUFFER,null),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT),e.drawArrays(e.TRIANGLE_FAN,0,4),!(t.canvas instanceof OffscreenCanvas))throw Error("Conversion to ImageBitmap requires that the MediaPipe Tasks is initialized with an OffscreenCanvas");return t.canvas.transferToImageBitmap()}))))}Pa.prototype.close=Pa.prototype.close,Pa.prototype.drawConfidenceMask=Pa.prototype.xa,Pa.prototype.drawCategoryMask=Pa.prototype.wa,Pa.prototype.drawBoundingBox=Pa.prototype.va,Pa.prototype.drawConnectors=Pa.prototype.ya,Pa.prototype.drawLandmarks=Pa.prototype.za,Pa.lerp=function(t,e,n,r,i){return Sa(r*(1-(t-e)/(n-e))+i*(1-(n-t)/(n-e)),r,i)},Pa.clamp=Sa,e("DrawingUtils",Pa);var Va=class{constructor(t,e,n,r,i,s,o){this.g=t,this.j=e,this.m=n,this.canvas=r,this.l=i,this.width=s,this.height=o,(this.j||this.m)&&(0===--Xa&&console.error("You seem to be creating MPImage instances without invoking .close(). This leaks resources."))}Fa(){return!!Oa(this,0)}la(){return!!Oa(this,1)}R(){return!!Oa(this,2)}Da(){return Ca(this)}Ca(){var t=Oa(this,1);return t||(Ua(this),Ba(this),t=ja(this),Ga(this),this.g.push(t),this.j=!0),t}N(){return Ua(this)}clone(){const t=[];for(const e of this.g){let n;if(e instanceof ImageData)n=new ImageData(e.data,this.width,this.height);else if(e instanceof WebGLTexture){const t=Na(this),e=Da(this);t.activeTexture(t.TEXTURE1),n=aa(e,t),t.bindTexture(t.TEXTURE_2D,n),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.width,this.height,0,t.RGBA,t.UNSIGNED_BYTE,null),t.bindTexture(t.TEXTURE_2D,null),ca(e,t,n),oa(e,t,!1,(()=>{Ba(this),t.clearColor(0,0,0,0),t.clear(t.COLOR_BUFFER_BIT),t.drawArrays(t.TRIANGLE_FAN,0,4),Ga(this)})),ha(e),Ga(this)}else{if(!(e instanceof ImageBitmap))throw Error(`Type is not supported: ${e}`);Ua(this),Ba(this),n=ja(this),Ga(this)}t.push(n)}return new Va(t,this.la(),this.R(),this.canvas,this.l,this.width,this.height)}close(){this.j&&Oa(this,1).close(),this.m&&Na(this).deleteTexture(Oa(this,2)),Xa=-1}};Va.prototype.close=Va.prototype.close,Va.prototype.clone=Va.prototype.clone,Va.prototype.getAsWebGLTexture=Va.prototype.N,Va.prototype.getAsImageBitmap=Va.prototype.Ca,Va.prototype.getAsImageData=Va.prototype.Da,Va.prototype.hasWebGLTexture=Va.prototype.R,Va.prototype.hasImageBitmap=Va.prototype.la,Va.prototype.hasImageData=Va.prototype.Fa;var Xa=250;function Ha(...t){return t.map((([t,e])=>({start:t,end:e})))}const Wa=function(t){return class extends t{La(){this.i._registerModelResourcesGraphService()}}}((za=class{constructor(t,e){this.l=!0,this.i=t,this.g=null,this.h=0,this.m="function"==typeof this.i._addIntToInputStream,void 0!==e?this.i.canvas=e:Bo()?this.i.canvas=new OffscreenCanvas(1,1):(console.warn("OffscreenCanvas not supported and GraphRunner constructor glCanvas parameter is undefined. Creating backup canvas."),this.i.canvas=document.createElement("canvas"))}async initializeGraph(t){const e=await(await fetch(t)).arrayBuffer();t=!(t.endsWith(".pbtxt")||t.endsWith(".textproto")),this.setGraph(new Uint8Array(e),t)}setGraphFromString(t){this.setGraph((new TextEncoder).encode(t),!1)}setGraph(t,e){const n=t.length,r=this.i._malloc(n);this.i.HEAPU8.set(t,r),e?this.i._changeBinaryGraph(n,r):this.i._changeTextGraph(n,r),this.i._free(r)}configureAudio(t,e,n,r,i){this.i._configureAudio||console.warn(\'Attempting to use configureAudio without support for input audio. Is build dep ":gl_graph_runner_audio" missing?\'),Vo(this,r||"input_audio",(r=>{Vo(this,i=i||"audio_header",(i=>{this.i._configureAudio(r,i,t,e??0,n)}))}))}setAutoResizeCanvas(t){this.l=t}setAutoRenderToScreen(t){this.i._setAutoRenderToScreen(t)}setGpuBufferVerticalFlip(t){this.i.gpuOriginForWebTexturesIsBottomLeft=t}ea(t){Wo(this,"__graph_config__",(e=>{t(e)})),Vo(this,"__graph_config__",(t=>{this.i._getGraphConfig(t,void 0)})),delete this.i.simpleListeners.__graph_config__}attachErrorListener(t){this.i.errorListener=t}attachEmptyPacketListener(t,e){this.i.emptyPacketListeners=this.i.emptyPacketListeners||{},this.i.emptyPacketListeners[t]=e}addAudioToStream(t,e,n){this.addAudioToStreamWithShape(t,0,0,e,n)}addAudioToStreamWithShape(t,e,n,r,i){const s=4*t.length;this.h!==s&&(this.g&&this.i._free(this.g),this.g=this.i._malloc(s),this.h=s),this.i.HEAPF32.set(t,this.g/4),Vo(this,r,(t=>{this.i._addAudioToInputStream(this.g,e,n,t,i)}))}addGpuBufferToStream(t,e,n){Vo(this,e,(e=>{const[r,i]=Xo(this,t,e);this.i._addBoundTextureToStream(e,r,i,n)}))}addBoolToStream(t,e,n){Vo(this,e,(e=>{this.i._addBoolToInputStream(t,e,n)}))}addDoubleToStream(t,e,n){Vo(this,e,(e=>{this.i._addDoubleToInputStream(t,e,n)}))}addFloatToStream(t,e,n){Vo(this,e,(e=>{this.i._addFloatToInputStream(t,e,n)}))}addIntToStream(t,e,n){Vo(this,e,(e=>{this.i._addIntToInputStream(t,e,n)}))}addUintToStream(t,e,n){Vo(this,e,(e=>{this.i._addUintToInputStream(t,e,n)}))}addStringToStream(t,e,n){Vo(this,e,(e=>{Vo(this,t,(t=>{this.i._addStringToInputStream(t,e,n)}))}))}addStringRecordToStream(t,e,n){Vo(this,e,(e=>{Ho(this,Object.keys(t),(r=>{Ho(this,Object.values(t),(i=>{this.i._addFlatHashMapToInputStream(r,i,Object.keys(t).length,e,n)}))}))}))}addProtoToStream(t,e,n,r){Vo(this,n,(n=>{Vo(this,e,(e=>{const i=this.i._malloc(t.length);this.i.HEAPU8.set(t,i),this.i._addProtoToInputStream(i,t.length,e,n,r),this.i._free(i)}))}))}addEmptyPacketToStream(t,e){Vo(this,t,(t=>{this.i._addEmptyPacketToInputStream(t,e)}))}addBoolVectorToStream(t,e,n){Vo(this,e,(e=>{const r=this.i._allocateBoolVector(t.length);if(!r)throw Error("Unable to allocate new bool vector on heap.");for(const e of t)this.i._addBoolVectorEntry(r,e);this.i._addBoolVectorToInputStream(r,e,n)}))}addDoubleVectorToStream(t,e,n){Vo(this,e,(e=>{const r=this.i._allocateDoubleVector(t.length);if(!r)throw Error("Unable to allocate new double vector on heap.");for(const e of t)this.i._addDoubleVectorEntry(r,e);this.i._addDoubleVectorToInputStream(r,e,n)}))}addFloatVectorToStream(t,e,n){Vo(this,e,(e=>{const r=this.i._allocateFloatVector(t.length);if(!r)throw Error("Unable to allocate new float vector on heap.");for(const e of t)this.i._addFloatVectorEntry(r,e);this.i._addFloatVectorToInputStream(r,e,n)}))}addIntVectorToStream(t,e,n){Vo(this,e,(e=>{const r=this.i._allocateIntVector(t.length);if(!r)throw Error("Unable to allocate new int vector on heap.");for(const e of t)this.i._addIntVectorEntry(r,e);this.i._addIntVectorToInputStream(r,e,n)}))}addUintVectorToStream(t,e,n){Vo(this,e,(e=>{const r=this.i._allocateUintVector(t.length);if(!r)throw Error("Unable to allocate new unsigned int vector on heap.");for(const e of t)this.i._addUintVectorEntry(r,e);this.i._addUintVectorToInputStream(r,e,n)}))}addStringVectorToStream(t,e,n){Vo(this,e,(e=>{const r=this.i._allocateStringVector(t.length);if(!r)throw Error("Unable to allocate new string vector on heap.");for(const e of t)Vo(this,e,(t=>{this.i._addStringVectorEntry(r,t)}));this.i._addStringVectorToInputStream(r,e,n)}))}addBoolToInputSidePacket(t,e){Vo(this,e,(e=>{this.i._addBoolToInputSidePacket(t,e)}))}addDoubleToInputSidePacket(t,e){Vo(this,e,(e=>{this.i._addDoubleToInputSidePacket(t,e)}))}addFloatToInputSidePacket(t,e){Vo(this,e,(e=>{this.i._addFloatToInputSidePacket(t,e)}))}addIntToInputSidePacket(t,e){Vo(this,e,(e=>{this.i._addIntToInputSidePacket(t,e)}))}addUintToInputSidePacket(t,e){Vo(this,e,(e=>{this.i._addUintToInputSidePacket(t,e)}))}addStringToInputSidePacket(t,e){Vo(this,e,(e=>{Vo(this,t,(t=>{this.i._addStringToInputSidePacket(t,e)}))}))}addProtoToInputSidePacket(t,e,n){Vo(this,n,(n=>{Vo(this,e,(e=>{const r=this.i._malloc(t.length);this.i.HEAPU8.set(t,r),this.i._addProtoToInputSidePacket(r,t.length,e,n),this.i._free(r)}))}))}addBoolVectorToInputSidePacket(t,e){Vo(this,e,(e=>{const n=this.i._allocateBoolVector(t.length);if(!n)throw Error("Unable to allocate new bool vector on heap.");for(const e of t)this.i._addBoolVectorEntry(n,e);this.i._addBoolVectorToInputSidePacket(n,e)}))}addDoubleVectorToInputSidePacket(t,e){Vo(this,e,(e=>{const n=this.i._allocateDoubleVector(t.length);if(!n)throw Error("Unable to allocate new double vector on heap.");for(const e of t)this.i._addDoubleVectorEntry(n,e);this.i._addDoubleVectorToInputSidePacket(n,e)}))}addFloatVectorToInputSidePacket(t,e){Vo(this,e,(e=>{const n=this.i._allocateFloatVector(t.length);if(!n)throw Error("Unable to allocate new float vector on heap.");for(const e of t)this.i._addFloatVectorEntry(n,e);this.i._addFloatVectorToInputSidePacket(n,e)}))}addIntVectorToInputSidePacket(t,e){Vo(this,e,(e=>{const n=this.i._allocateIntVector(t.length);if(!n)throw Error("Unable to allocate new int vector on heap.");for(const e of t)this.i._addIntVectorEntry(n,e);this.i._addIntVectorToInputSidePacket(n,e)}))}addUintVectorToInputSidePacket(t,e){Vo(this,e,(e=>{const n=this.i._allocateUintVector(t.length);if(!n)throw Error("Unable to allocate new unsigned int vector on heap.");for(const e of t)this.i._addUintVectorEntry(n,e);this.i._addUintVectorToInputSidePacket(n,e)}))}addStringVectorToInputSidePacket(t,e){Vo(this,e,(e=>{const n=this.i._allocateStringVector(t.length);if(!n)throw Error("Unable to allocate new string vector on heap.");for(const e of t)Vo(this,e,(t=>{this.i._addStringVectorEntry(n,t)}));this.i._addStringVectorToInputSidePacket(n,e)}))}attachBoolListener(t,e){Wo(this,t,e),Vo(this,t,(t=>{this.i._attachBoolListener(t)}))}attachBoolVectorListener(t,e){zo(this,t,e),Vo(this,t,(t=>{this.i._attachBoolVectorListener(t)}))}attachIntListener(t,e){Wo(this,t,e),Vo(this,t,(t=>{this.i._attachIntListener(t)}))}attachIntVectorListener(t,e){zo(this,t,e),Vo(this,t,(t=>{this.i._attachIntVectorListener(t)}))}attachUintListener(t,e){Wo(this,t,e),Vo(this,t,(t=>{this.i._attachUintListener(t)}))}attachUintVectorListener(t,e){zo(this,t,e),Vo(this,t,(t=>{this.i._attachUintVectorListener(t)}))}attachDoubleListener(t,e){Wo(this,t,e),Vo(this,t,(t=>{this.i._attachDoubleListener(t)}))}attachDoubleVectorListener(t,e){zo(this,t,e),Vo(this,t,(t=>{this.i._attachDoubleVectorListener(t)}))}attachFloatListener(t,e){Wo(this,t,e),Vo(this,t,(t=>{this.i._attachFloatListener(t)}))}attachFloatVectorListener(t,e){zo(this,t,e),Vo(this,t,(t=>{this.i._attachFloatVectorListener(t)}))}attachStringListener(t,e){Wo(this,t,e),Vo(this,t,(t=>{this.i._attachStringListener(t)}))}attachStringVectorListener(t,e){zo(this,t,e),Vo(this,t,(t=>{this.i._attachStringVectorListener(t)}))}attachProtoListener(t,e,n){Wo(this,t,e),Vo(this,t,(t=>{this.i._attachProtoListener(t,n||!1)}))}attachProtoVectorListener(t,e,n){zo(this,t,e),Vo(this,t,(t=>{this.i._attachProtoVectorListener(t,n||!1)}))}attachAudioListener(t,e,n){this.i._attachAudioListener||console.warn(\'Attempting to use attachAudioListener without support for output audio. Is build dep ":gl_graph_runner_audio_out" missing?\'),Wo(this,t,((t,n)=>{t=new Float32Array(t.buffer,t.byteOffset,t.length/4),e(t,n)})),Vo(this,t,(t=>{this.i._attachAudioListener(t,n||!1)}))}finishProcessing(){this.i._waitUntilIdle()}closeGraph(){this.i._closeGraph(),this.i.simpleListeners=void 0,this.i.emptyPacketListeners=void 0}},class extends za{get fa(){return this.i}ra(t,e,n){Vo(this,e,(e=>{const[r,i]=Xo(this,t,e);this.fa._addBoundTextureAsImageToStream(e,r,i,n)}))}V(t,e){Wo(this,t,e),Vo(this,t,(t=>{this.fa._attachImageListener(t)}))}da(t,e){zo(this,t,e),Vo(this,t,(t=>{this.fa._attachImageVectorListener(t)}))}}));var za,Ka=class extends Wa{};async function Ya(t,e,n){return async function(t,e,n,r){return Ko(t,e,n,r)}(t,n.canvas??(Bo()?void 0:document.createElement("canvas")),e,n)}function $a(t,e,n,r){if(t.U){const s=new _s;if(n?.regionOfInterest){if(!t.qa)throw Error("This task doesn\'t support region-of-interest.");var i=n.regionOfInterest;if(i.left>=i.right||i.top>=i.bottom)throw Error("Expected RectF with left < right and top < bottom.");if(i.left<0||i.top<0||i.right>1||i.bottom>1)throw Error("Expected RectF values to be in [0,1].");wn(s,1,(i.left+i.right)/2),wn(s,2,(i.top+i.bottom)/2),wn(s,4,i.right-i.left),wn(s,3,i.bottom-i.top)}else wn(s,1,.5),wn(s,2,.5),wn(s,4,1),wn(s,3,1);if(n?.rotationDegrees){if(n?.rotationDegrees%90!=0)throw Error("Expected rotation to be a multiple of 90°.");if(wn(s,5,-Math.PI*n.rotationDegrees/180),n?.rotationDegrees%180!=0){const[t,r]=jo(e);n=yn(s,3)*r/t,i=yn(s,4)*t/r,wn(s,4,n),wn(s,3,i)}}t.g.addProtoToStream(s.g(),"mediapipe.NormalizedRect",t.U,r)}t.g.ra(e,t.ba,r??performance.now()),t.finishProcessing()}function qa(t,e,n){if(t.baseOptions?.g())throw Error("Task is not initialized with image mode. \'runningMode\' must be set to \'IMAGE\'.");$a(t,e,n,t.B+1)}function Ja(t,e,n,r){if(!t.baseOptions?.g())throw Error("Task is not initialized with video mode. \'runningMode\' must be set to \'VIDEO\'.");$a(t,e,n,r)}function Za(t,e,n,r){var i=e.data;const s=e.width,o=s*(e=e.height);if((i instanceof Uint8Array||i instanceof Float32Array)&&i.length!==o)throw Error("Unsupported channel count: "+i.length/o);return t=new Ta([i],n,!1,t.g.i.canvas,t.P,s,e),r?t.clone():t}var Qa=class extends ta{constructor(t,e,n,r){super(t),this.g=t,this.ba=e,this.U=n,this.qa=r,this.P=new ua}l(t,e=!0){if("runningMode"in t&&vn(this.baseOptions,2,!!t.runningMode&&"IMAGE"!==t.runningMode),void 0!==t.canvas&&this.g.i.canvas!==t.canvas)throw Error("You must create a new task to reset the canvas.");return super.l(t,e)}close(){this.P.close(),super.close()}};Qa.prototype.close=Qa.prototype.close;var tc=class extends Qa{constructor(t,e){super(new Ka(t,e),"image_in","norm_rect_in",!1),this.j={detections:[]},un(t=this.h=new Us,0,1,e=new Ps),wn(this.h,2,.5),wn(this.h,3,.3)}get baseOptions(){return an(this.h,Ps,1)}set baseOptions(t){un(this.h,0,1,t)}o(t){return"minDetectionConfidence"in t&&wn(this.h,2,t.minDetectionConfidence??.5),"minSuppressionThreshold"in t&&wn(this.h,3,t.minSuppressionThreshold??.3),this.l(t)}D(t,e){return this.j={detections:[]},qa(this,t,e),this.j}F(t,e,n){return this.j={detections:[]},Ja(this,t,n,e),this.j}m(){var t=new es;Qi(t,"image_in"),Qi(t,"norm_rect_in"),ts(t,"detections");const e=new Vi;Yn(e,Ds,this.h);const n=new Yi;Wi(n,"mediapipe.tasks.vision.face_detector.FaceDetectorGraph"),zi(n,"IMAGE:image_in"),zi(n,"NORM_RECT:norm_rect_in"),Ki(n,"DETECTIONS:detections"),n.o(e),Zi(t,n),this.g.attachProtoVectorListener("detections",((t,e)=>{for(const e of t)t=ls(e),this.j.detections.push(Ro(t));qo(this,e)})),this.g.attachEmptyPacketListener("detections",(t=>{qo(this,t)})),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};tc.prototype.detectForVideo=tc.prototype.F,tc.prototype.detect=tc.prototype.D,tc.prototype.setOptions=tc.prototype.o,tc.createFromModelPath=async function(t,e){return Ya(tc,t,{baseOptions:{modelAssetPath:e}})},tc.createFromModelBuffer=function(t,e){return Ya(tc,t,{baseOptions:{modelAssetBuffer:e}})},tc.createFromOptions=function(t,e){return Ya(tc,t,e)};var ec=Ha([61,146],[146,91],[91,181],[181,84],[84,17],[17,314],[314,405],[405,321],[321,375],[375,291],[61,185],[185,40],[40,39],[39,37],[37,0],[0,267],[267,269],[269,270],[270,409],[409,291],[78,95],[95,88],[88,178],[178,87],[87,14],[14,317],[317,402],[402,318],[318,324],[324,308],[78,191],[191,80],[80,81],[81,82],[82,13],[13,312],[312,311],[311,310],[310,415],[415,308]),nc=Ha([263,249],[249,390],[390,373],[373,374],[374,380],[380,381],[381,382],[382,362],[263,466],[466,388],[388,387],[387,386],[386,385],[385,384],[384,398],[398,362]),rc=Ha([276,283],[283,282],[282,295],[295,285],[300,293],[293,334],[334,296],[296,336]),ic=Ha([474,475],[475,476],[476,477],[477,474]),sc=Ha([33,7],[7,163],[163,144],[144,145],[145,153],[153,154],[154,155],[155,133],[33,246],[246,161],[161,160],[160,159],[159,158],[158,157],[157,173],[173,133]),oc=Ha([46,53],[53,52],[52,65],[65,55],[70,63],[63,105],[105,66],[66,107]),ac=Ha([469,470],[470,471],[471,472],[472,469]),cc=Ha([10,338],[338,297],[297,332],[332,284],[284,251],[251,389],[389,356],[356,454],[454,323],[323,361],[361,288],[288,397],[397,365],[365,379],[379,378],[378,400],[400,377],[377,152],[152,148],[148,176],[176,149],[149,150],[150,136],[136,172],[172,58],[58,132],[132,93],[93,234],[234,127],[127,162],[162,21],[21,54],[54,103],[103,67],[67,109],[109,10]),hc=[...ec,...nc,...rc,...sc,...oc,...cc],uc=Ha([127,34],[34,139],[139,127],[11,0],[0,37],[37,11],[232,231],[231,120],[120,232],[72,37],[37,39],[39,72],[128,121],[121,47],[47,128],[232,121],[121,128],[128,232],[104,69],[69,67],[67,104],[175,171],[171,148],[148,175],[118,50],[50,101],[101,118],[73,39],[39,40],[40,73],[9,151],[151,108],[108,9],[48,115],[115,131],[131,48],[194,204],[204,211],[211,194],[74,40],[40,185],[185,74],[80,42],[42,183],[183,80],[40,92],[92,186],[186,40],[230,229],[229,118],[118,230],[202,212],[212,214],[214,202],[83,18],[18,17],[17,83],[76,61],[61,146],[146,76],[160,29],[29,30],[30,160],[56,157],[157,173],[173,56],[106,204],[204,194],[194,106],[135,214],[214,192],[192,135],[203,165],[165,98],[98,203],[21,71],[71,68],[68,21],[51,45],[45,4],[4,51],[144,24],[24,23],[23,144],[77,146],[146,91],[91,77],[205,50],[50,187],[187,205],[201,200],[200,18],[18,201],[91,106],[106,182],[182,91],[90,91],[91,181],[181,90],[85,84],[84,17],[17,85],[206,203],[203,36],[36,206],[148,171],[171,140],[140,148],[92,40],[40,39],[39,92],[193,189],[189,244],[244,193],[159,158],[158,28],[28,159],[247,246],[246,161],[161,247],[236,3],[3,196],[196,236],[54,68],[68,104],[104,54],[193,168],[168,8],[8,193],[117,228],[228,31],[31,117],[189,193],[193,55],[55,189],[98,97],[97,99],[99,98],[126,47],[47,100],[100,126],[166,79],[79,218],[218,166],[155,154],[154,26],[26,155],[209,49],[49,131],[131,209],[135,136],[136,150],[150,135],[47,126],[126,217],[217,47],[223,52],[52,53],[53,223],[45,51],[51,134],[134,45],[211,170],[170,140],[140,211],[67,69],[69,108],[108,67],[43,106],[106,91],[91,43],[230,119],[119,120],[120,230],[226,130],[130,247],[247,226],[63,53],[53,52],[52,63],[238,20],[20,242],[242,238],[46,70],[70,156],[156,46],[78,62],[62,96],[96,78],[46,53],[53,63],[63,46],[143,34],[34,227],[227,143],[123,117],[117,111],[111,123],[44,125],[125,19],[19,44],[236,134],[134,51],[51,236],[216,206],[206,205],[205,216],[154,153],[153,22],[22,154],[39,37],[37,167],[167,39],[200,201],[201,208],[208,200],[36,142],[142,100],[100,36],[57,212],[212,202],[202,57],[20,60],[60,99],[99,20],[28,158],[158,157],[157,28],[35,226],[226,113],[113,35],[160,159],[159,27],[27,160],[204,202],[202,210],[210,204],[113,225],[225,46],[46,113],[43,202],[202,204],[204,43],[62,76],[76,77],[77,62],[137,123],[123,116],[116,137],[41,38],[38,72],[72,41],[203,129],[129,142],[142,203],[64,98],[98,240],[240,64],[49,102],[102,64],[64,49],[41,73],[73,74],[74,41],[212,216],[216,207],[207,212],[42,74],[74,184],[184,42],[169,170],[170,211],[211,169],[170,149],[149,176],[176,170],[105,66],[66,69],[69,105],[122,6],[6,168],[168,122],[123,147],[147,187],[187,123],[96,77],[77,90],[90,96],[65,55],[55,107],[107,65],[89,90],[90,180],[180,89],[101,100],[100,120],[120,101],[63,105],[105,104],[104,63],[93,137],[137,227],[227,93],[15,86],[86,85],[85,15],[129,102],[102,49],[49,129],[14,87],[87,86],[86,14],[55,8],[8,9],[9,55],[100,47],[47,121],[121,100],[145,23],[23,22],[22,145],[88,89],[89,179],[179,88],[6,122],[122,196],[196,6],[88,95],[95,96],[96,88],[138,172],[172,136],[136,138],[215,58],[58,172],[172,215],[115,48],[48,219],[219,115],[42,80],[80,81],[81,42],[195,3],[3,51],[51,195],[43,146],[146,61],[61,43],[171,175],[175,199],[199,171],[81,82],[82,38],[38,81],[53,46],[46,225],[225,53],[144,163],[163,110],[110,144],[52,65],[65,66],[66,52],[229,228],[228,117],[117,229],[34,127],[127,234],[234,34],[107,108],[108,69],[69,107],[109,108],[108,151],[151,109],[48,64],[64,235],[235,48],[62,78],[78,191],[191,62],[129,209],[209,126],[126,129],[111,35],[35,143],[143,111],[117,123],[123,50],[50,117],[222,65],[65,52],[52,222],[19,125],[125,141],[141,19],[221,55],[55,65],[65,221],[3,195],[195,197],[197,3],[25,7],[7,33],[33,25],[220,237],[237,44],[44,220],[70,71],[71,139],[139,70],[122,193],[193,245],[245,122],[247,130],[130,33],[33,247],[71,21],[21,162],[162,71],[170,169],[169,150],[150,170],[188,174],[174,196],[196,188],[216,186],[186,92],[92,216],[2,97],[97,167],[167,2],[141,125],[125,241],[241,141],[164,167],[167,37],[37,164],[72,38],[38,12],[12,72],[38,82],[82,13],[13,38],[63,68],[68,71],[71,63],[226,35],[35,111],[111,226],[101,50],[50,205],[205,101],[206,92],[92,165],[165,206],[209,198],[198,217],[217,209],[165,167],[167,97],[97,165],[220,115],[115,218],[218,220],[133,112],[112,243],[243,133],[239,238],[238,241],[241,239],[214,135],[135,169],[169,214],[190,173],[173,133],[133,190],[171,208],[208,32],[32,171],[125,44],[44,237],[237,125],[86,87],[87,178],[178,86],[85,86],[86,179],[179,85],[84,85],[85,180],[180,84],[83,84],[84,181],[181,83],[201,83],[83,182],[182,201],[137,93],[93,132],[132,137],[76,62],[62,183],[183,76],[61,76],[76,184],[184,61],[57,61],[61,185],[185,57],[212,57],[57,186],[186,212],[214,207],[207,187],[187,214],[34,143],[143,156],[156,34],[79,239],[239,237],[237,79],[123,137],[137,177],[177,123],[44,1],[1,4],[4,44],[201,194],[194,32],[32,201],[64,102],[102,129],[129,64],[213,215],[215,138],[138,213],[59,166],[166,219],[219,59],[242,99],[99,97],[97,242],[2,94],[94,141],[141,2],[75,59],[59,235],[235,75],[24,110],[110,228],[228,24],[25,130],[130,226],[226,25],[23,24],[24,229],[229,23],[22,23],[23,230],[230,22],[26,22],[22,231],[231,26],[112,26],[26,232],[232,112],[189,190],[190,243],[243,189],[221,56],[56,190],[190,221],[28,56],[56,221],[221,28],[27,28],[28,222],[222,27],[29,27],[27,223],[223,29],[30,29],[29,224],[224,30],[247,30],[30,225],[225,247],[238,79],[79,20],[20,238],[166,59],[59,75],[75,166],[60,75],[75,240],[240,60],[147,177],[177,215],[215,147],[20,79],[79,166],[166,20],[187,147],[147,213],[213,187],[112,233],[233,244],[244,112],[233,128],[128,245],[245,233],[128,114],[114,188],[188,128],[114,217],[217,174],[174,114],[131,115],[115,220],[220,131],[217,198],[198,236],[236,217],[198,131],[131,134],[134,198],[177,132],[132,58],[58,177],[143,35],[35,124],[124,143],[110,163],[163,7],[7,110],[228,110],[110,25],[25,228],[356,389],[389,368],[368,356],[11,302],[302,267],[267,11],[452,350],[350,349],[349,452],[302,303],[303,269],[269,302],[357,343],[343,277],[277,357],[452,453],[453,357],[357,452],[333,332],[332,297],[297,333],[175,152],[152,377],[377,175],[347,348],[348,330],[330,347],[303,304],[304,270],[270,303],[9,336],[336,337],[337,9],[278,279],[279,360],[360,278],[418,262],[262,431],[431,418],[304,408],[408,409],[409,304],[310,415],[415,407],[407,310],[270,409],[409,410],[410,270],[450,348],[348,347],[347,450],[422,430],[430,434],[434,422],[313,314],[314,17],[17,313],[306,307],[307,375],[375,306],[387,388],[388,260],[260,387],[286,414],[414,398],[398,286],[335,406],[406,418],[418,335],[364,367],[367,416],[416,364],[423,358],[358,327],[327,423],[251,284],[284,298],[298,251],[281,5],[5,4],[4,281],[373,374],[374,253],[253,373],[307,320],[320,321],[321,307],[425,427],[427,411],[411,425],[421,313],[313,18],[18,421],[321,405],[405,406],[406,321],[320,404],[404,405],[405,320],[315,16],[16,17],[17,315],[426,425],[425,266],[266,426],[377,400],[400,369],[369,377],[322,391],[391,269],[269,322],[417,465],[465,464],[464,417],[386,257],[257,258],[258,386],[466,260],[260,388],[388,466],[456,399],[399,419],[419,456],[284,332],[332,333],[333,284],[417,285],[285,8],[8,417],[346,340],[340,261],[261,346],[413,441],[441,285],[285,413],[327,460],[460,328],[328,327],[355,371],[371,329],[329,355],[392,439],[439,438],[438,392],[382,341],[341,256],[256,382],[429,420],[420,360],[360,429],[364,394],[394,379],[379,364],[277,343],[343,437],[437,277],[443,444],[444,283],[283,443],[275,440],[440,363],[363,275],[431,262],[262,369],[369,431],[297,338],[338,337],[337,297],[273,375],[375,321],[321,273],[450,451],[451,349],[349,450],[446,342],[342,467],[467,446],[293,334],[334,282],[282,293],[458,461],[461,462],[462,458],[276,353],[353,383],[383,276],[308,324],[324,325],[325,308],[276,300],[300,293],[293,276],[372,345],[345,447],[447,372],[352,345],[345,340],[340,352],[274,1],[1,19],[19,274],[456,248],[248,281],[281,456],[436,427],[427,425],[425,436],[381,256],[256,252],[252,381],[269,391],[391,393],[393,269],[200,199],[199,428],[428,200],[266,330],[330,329],[329,266],[287,273],[273,422],[422,287],[250,462],[462,328],[328,250],[258,286],[286,384],[384,258],[265,353],[353,342],[342,265],[387,259],[259,257],[257,387],[424,431],[431,430],[430,424],[342,353],[353,276],[276,342],[273,335],[335,424],[424,273],[292,325],[325,307],[307,292],[366,447],[447,345],[345,366],[271,303],[303,302],[302,271],[423,266],[266,371],[371,423],[294,455],[455,460],[460,294],[279,278],[278,294],[294,279],[271,272],[272,304],[304,271],[432,434],[434,427],[427,432],[272,407],[407,408],[408,272],[394,430],[430,431],[431,394],[395,369],[369,400],[400,395],[334,333],[333,299],[299,334],[351,417],[417,168],[168,351],[352,280],[280,411],[411,352],[325,319],[319,320],[320,325],[295,296],[296,336],[336,295],[319,403],[403,404],[404,319],[330,348],[348,349],[349,330],[293,298],[298,333],[333,293],[323,454],[454,447],[447,323],[15,16],[16,315],[315,15],[358,429],[429,279],[279,358],[14,15],[15,316],[316,14],[285,336],[336,9],[9,285],[329,349],[349,350],[350,329],[374,380],[380,252],[252,374],[318,402],[402,403],[403,318],[6,197],[197,419],[419,6],[318,319],[319,325],[325,318],[367,364],[364,365],[365,367],[435,367],[367,397],[397,435],[344,438],[438,439],[439,344],[272,271],[271,311],[311,272],[195,5],[5,281],[281,195],[273,287],[287,291],[291,273],[396,428],[428,199],[199,396],[311,271],[271,268],[268,311],[283,444],[444,445],[445,283],[373,254],[254,339],[339,373],[282,334],[334,296],[296,282],[449,347],[347,346],[346,449],[264,447],[447,454],[454,264],[336,296],[296,299],[299,336],[338,10],[10,151],[151,338],[278,439],[439,455],[455,278],[292,407],[407,415],[415,292],[358,371],[371,355],[355,358],[340,345],[345,372],[372,340],[346,347],[347,280],[280,346],[442,443],[443,282],[282,442],[19,94],[94,370],[370,19],[441,442],[442,295],[295,441],[248,419],[419,197],[197,248],[263,255],[255,359],[359,263],[440,275],[275,274],[274,440],[300,383],[383,368],[368,300],[351,412],[412,465],[465,351],[263,467],[467,466],[466,263],[301,368],[368,389],[389,301],[395,378],[378,379],[379,395],[412,351],[351,419],[419,412],[436,426],[426,322],[322,436],[2,164],[164,393],[393,2],[370,462],[462,461],[461,370],[164,0],[0,267],[267,164],[302,11],[11,12],[12,302],[268,12],[12,13],[13,268],[293,300],[300,301],[301,293],[446,261],[261,340],[340,446],[330,266],[266,425],[425,330],[426,423],[423,391],[391,426],[429,355],[355,437],[437,429],[391,327],[327,326],[326,391],[440,457],[457,438],[438,440],[341,382],[382,362],[362,341],[459,457],[457,461],[461,459],[434,430],[430,394],[394,434],[414,463],[463,362],[362,414],[396,369],[369,262],[262,396],[354,461],[461,457],[457,354],[316,403],[403,402],[402,316],[315,404],[404,403],[403,315],[314,405],[405,404],[404,314],[313,406],[406,405],[405,313],[421,418],[418,406],[406,421],[366,401],[401,361],[361,366],[306,408],[408,407],[407,306],[291,409],[409,408],[408,291],[287,410],[410,409],[409,287],[432,436],[436,410],[410,432],[434,416],[416,411],[411,434],[264,368],[368,383],[383,264],[309,438],[438,457],[457,309],[352,376],[376,401],[401,352],[274,275],[275,4],[4,274],[421,428],[428,262],[262,421],[294,327],[327,358],[358,294],[433,416],[416,367],[367,433],[289,455],[455,439],[439,289],[462,370],[370,326],[326,462],[2,326],[326,370],[370,2],[305,460],[460,455],[455,305],[254,449],[449,448],[448,254],[255,261],[261,446],[446,255],[253,450],[450,449],[449,253],[252,451],[451,450],[450,252],[256,452],[452,451],[451,256],[341,453],[453,452],[452,341],[413,464],[464,463],[463,413],[441,413],[413,414],[414,441],[258,442],[442,441],[441,258],[257,443],[443,442],[442,257],[259,444],[444,443],[443,259],[260,445],[445,444],[444,260],[467,342],[342,445],[445,467],[459,458],[458,250],[250,459],[289,392],[392,290],[290,289],[290,328],[328,460],[460,290],[376,433],[433,435],[435,376],[250,290],[290,392],[392,250],[411,416],[416,433],[433,411],[341,463],[463,464],[464,341],[453,464],[464,465],[465,453],[357,465],[465,412],[412,357],[343,412],[412,399],[399,343],[360,363],[363,440],[440,360],[437,399],[399,456],[456,437],[420,456],[456,363],[363,420],[401,435],[435,288],[288,401],[372,383],[383,353],[353,372],[339,255],[255,249],[249,339],[448,261],[261,255],[255,448],[133,243],[243,190],[190,133],[133,155],[155,112],[112,133],[33,246],[246,247],[247,33],[33,130],[130,25],[25,33],[398,384],[384,286],[286,398],[362,398],[398,414],[414,362],[362,463],[463,341],[341,362],[263,359],[359,467],[467,263],[263,249],[249,255],[255,263],[466,467],[467,260],[260,466],[75,60],[60,166],[166,75],[238,239],[239,79],[79,238],[162,127],[127,139],[139,162],[72,11],[11,37],[37,72],[121,232],[232,120],[120,121],[73,72],[72,39],[39,73],[114,128],[128,47],[47,114],[233,232],[232,128],[128,233],[103,104],[104,67],[67,103],[152,175],[175,148],[148,152],[119,118],[118,101],[101,119],[74,73],[73,40],[40,74],[107,9],[9,108],[108,107],[49,48],[48,131],[131,49],[32,194],[194,211],[211,32],[184,74],[74,185],[185,184],[191,80],[80,183],[183,191],[185,40],[40,186],[186,185],[119,230],[230,118],[118,119],[210,202],[202,214],[214,210],[84,83],[83,17],[17,84],[77,76],[76,146],[146,77],[161,160],[160,30],[30,161],[190,56],[56,173],[173,190],[182,106],[106,194],[194,182],[138,135],[135,192],[192,138],[129,203],[203,98],[98,129],[54,21],[21,68],[68,54],[5,51],[51,4],[4,5],[145,144],[144,23],[23,145],[90,77],[77,91],[91,90],[207,205],[205,187],[187,207],[83,201],[201,18],[18,83],[181,91],[91,182],[182,181],[180,90],[90,181],[181,180],[16,85],[85,17],[17,16],[205,206],[206,36],[36,205],[176,148],[148,140],[140,176],[165,92],[92,39],[39,165],[245,193],[193,244],[244,245],[27,159],[159,28],[28,27],[30,247],[247,161],[161,30],[174,236],[236,196],[196,174],[103,54],[54,104],[104,103],[55,193],[193,8],[8,55],[111,117],[117,31],[31,111],[221,189],[189,55],[55,221],[240,98],[98,99],[99,240],[142,126],[126,100],[100,142],[219,166],[166,218],[218,219],[112,155],[155,26],[26,112],[198,209],[209,131],[131,198],[169,135],[135,150],[150,169],[114,47],[47,217],[217,114],[224,223],[223,53],[53,224],[220,45],[45,134],[134,220],[32,211],[211,140],[140,32],[109,67],[67,108],[108,109],[146,43],[43,91],[91,146],[231,230],[230,120],[120,231],[113,226],[226,247],[247,113],[105,63],[63,52],[52,105],[241,238],[238,242],[242,241],[124,46],[46,156],[156,124],[95,78],[78,96],[96,95],[70,46],[46,63],[63,70],[116,143],[143,227],[227,116],[116,123],[123,111],[111,116],[1,44],[44,19],[19,1],[3,236],[236,51],[51,3],[207,216],[216,205],[205,207],[26,154],[154,22],[22,26],[165,39],[39,167],[167,165],[199,200],[200,208],[208,199],[101,36],[36,100],[100,101],[43,57],[57,202],[202,43],[242,20],[20,99],[99,242],[56,28],[28,157],[157,56],[124,35],[35,113],[113,124],[29,160],[160,27],[27,29],[211,204],[204,210],[210,211],[124,113],[113,46],[46,124],[106,43],[43,204],[204,106],[96,62],[62,77],[77,96],[227,137],[137,116],[116,227],[73,41],[41,72],[72,73],[36,203],[203,142],[142,36],[235,64],[64,240],[240,235],[48,49],[49,64],[64,48],[42,41],[41,74],[74,42],[214,212],[212,207],[207,214],[183,42],[42,184],[184,183],[210,169],[169,211],[211,210],[140,170],[170,176],[176,140],[104,105],[105,69],[69,104],[193,122],[122,168],[168,193],[50,123],[123,187],[187,50],[89,96],[96,90],[90,89],[66,65],[65,107],[107,66],[179,89],[89,180],[180,179],[119,101],[101,120],[120,119],[68,63],[63,104],[104,68],[234,93],[93,227],[227,234],[16,15],[15,85],[85,16],[209,129],[129,49],[49,209],[15,14],[14,86],[86,15],[107,55],[55,9],[9,107],[120,100],[100,121],[121,120],[153,145],[145,22],[22,153],[178,88],[88,179],[179,178],[197,6],[6,196],[196,197],[89,88],[88,96],[96,89],[135,138],[138,136],[136,135],[138,215],[215,172],[172,138],[218,115],[115,219],[219,218],[41,42],[42,81],[81,41],[5,195],[195,51],[51,5],[57,43],[43,61],[61,57],[208,171],[171,199],[199,208],[41,81],[81,38],[38,41],[224,53],[53,225],[225,224],[24,144],[144,110],[110,24],[105,52],[52,66],[66,105],[118,229],[229,117],[117,118],[227,34],[34,234],[234,227],[66,107],[107,69],[69,66],[10,109],[109,151],[151,10],[219,48],[48,235],[235,219],[183,62],[62,191],[191,183],[142,129],[129,126],[126,142],[116,111],[111,143],[143,116],[118,117],[117,50],[50,118],[223,222],[222,52],[52,223],[94,19],[19,141],[141,94],[222,221],[221,65],[65,222],[196,3],[3,197],[197,196],[45,220],[220,44],[44,45],[156,70],[70,139],[139,156],[188,122],[122,245],[245,188],[139,71],[71,162],[162,139],[149,170],[170,150],[150,149],[122,188],[188,196],[196,122],[206,216],[216,92],[92,206],[164,2],[2,167],[167,164],[242,141],[141,241],[241,242],[0,164],[164,37],[37,0],[11,72],[72,12],[12,11],[12,38],[38,13],[13,12],[70,63],[63,71],[71,70],[31,226],[226,111],[111,31],[36,101],[101,205],[205,36],[203,206],[206,165],[165,203],[126,209],[209,217],[217,126],[98,165],[165,97],[97,98],[237,220],[220,218],[218,237],[237,239],[239,241],[241,237],[210,214],[214,169],[169,210],[140,171],[171,32],[32,140],[241,125],[125,237],[237,241],[179,86],[86,178],[178,179],[180,85],[85,179],[179,180],[181,84],[84,180],[180,181],[182,83],[83,181],[181,182],[194,201],[201,182],[182,194],[177,137],[137,132],[132,177],[184,76],[76,183],[183,184],[185,61],[61,184],[184,185],[186,57],[57,185],[185,186],[216,212],[212,186],[186,216],[192,214],[214,187],[187,192],[139,34],[34,156],[156,139],[218,79],[79,237],[237,218],[147,123],[123,177],[177,147],[45,44],[44,4],[4,45],[208,201],[201,32],[32,208],[98,64],[64,129],[129,98],[192,213],[213,138],[138,192],[235,59],[59,219],[219,235],[141,242],[242,97],[97,141],[97,2],[2,141],[141,97],[240,75],[75,235],[235,240],[229,24],[24,228],[228,229],[31,25],[25,226],[226,31],[230,23],[23,229],[229,230],[231,22],[22,230],[230,231],[232,26],[26,231],[231,232],[233,112],[112,232],[232,233],[244,189],[189,243],[243,244],[189,221],[221,190],[190,189],[222,28],[28,221],[221,222],[223,27],[27,222],[222,223],[224,29],[29,223],[223,224],[225,30],[30,224],[224,225],[113,247],[247,225],[225,113],[99,60],[60,240],[240,99],[213,147],[147,215],[215,213],[60,20],[20,166],[166,60],[192,187],[187,213],[213,192],[243,112],[112,244],[244,243],[244,233],[233,245],[245,244],[245,128],[128,188],[188,245],[188,114],[114,174],[174,188],[134,131],[131,220],[220,134],[174,217],[217,236],[236,174],[236,198],[198,134],[134,236],[215,177],[177,58],[58,215],[156,143],[143,124],[124,156],[25,110],[110,7],[7,25],[31,228],[228,25],[25,31],[264,356],[356,368],[368,264],[0,11],[11,267],[267,0],[451,452],[452,349],[349,451],[267,302],[302,269],[269,267],[350,357],[357,277],[277,350],[350,452],[452,357],[357,350],[299,333],[333,297],[297,299],[396,175],[175,377],[377,396],[280,347],[347,330],[330,280],[269,303],[303,270],[270,269],[151,9],[9,337],[337,151],[344,278],[278,360],[360,344],[424,418],[418,431],[431,424],[270,304],[304,409],[409,270],[272,310],[310,407],[407,272],[322,270],[270,410],[410,322],[449,450],[450,347],[347,449],[432,422],[422,434],[434,432],[18,313],[313,17],[17,18],[291,306],[306,375],[375,291],[259,387],[387,260],[260,259],[424,335],[335,418],[418,424],[434,364],[364,416],[416,434],[391,423],[423,327],[327,391],[301,251],[251,298],[298,301],[275,281],[281,4],[4,275],[254,373],[373,253],[253,254],[375,307],[307,321],[321,375],[280,425],[425,411],[411,280],[200,421],[421,18],[18,200],[335,321],[321,406],[406,335],[321,320],[320,405],[405,321],[314,315],[315,17],[17,314],[423,426],[426,266],[266,423],[396,377],[377,369],[369,396],[270,322],[322,269],[269,270],[413,417],[417,464],[464,413],[385,386],[386,258],[258,385],[248,456],[456,419],[419,248],[298,284],[284,333],[333,298],[168,417],[417,8],[8,168],[448,346],[346,261],[261,448],[417,413],[413,285],[285,417],[326,327],[327,328],[328,326],[277,355],[355,329],[329,277],[309,392],[392,438],[438,309],[381,382],[382,256],[256,381],[279,429],[429,360],[360,279],[365,364],[364,379],[379,365],[355,277],[277,437],[437,355],[282,443],[443,283],[283,282],[281,275],[275,363],[363,281],[395,431],[431,369],[369,395],[299,297],[297,337],[337,299],[335,273],[273,321],[321,335],[348,450],[450,349],[349,348],[359,446],[446,467],[467,359],[283,293],[293,282],[282,283],[250,458],[458,462],[462,250],[300,276],[276,383],[383,300],[292,308],[308,325],[325,292],[283,276],[276,293],[293,283],[264,372],[372,447],[447,264],[346,352],[352,340],[340,346],[354,274],[274,19],[19,354],[363,456],[456,281],[281,363],[426,436],[436,425],[425,426],[380,381],[381,252],[252,380],[267,269],[269,393],[393,267],[421,200],[200,428],[428,421],[371,266],[266,329],[329,371],[432,287],[287,422],[422,432],[290,250],[250,328],[328,290],[385,258],[258,384],[384,385],[446,265],[265,342],[342,446],[386,387],[387,257],[257,386],[422,424],[424,430],[430,422],[445,342],[342,276],[276,445],[422,273],[273,424],[424,422],[306,292],[292,307],[307,306],[352,366],[366,345],[345,352],[268,271],[271,302],[302,268],[358,423],[423,371],[371,358],[327,294],[294,460],[460,327],[331,279],[279,294],[294,331],[303,271],[271,304],[304,303],[436,432],[432,427],[427,436],[304,272],[272,408],[408,304],[395,394],[394,431],[431,395],[378,395],[395,400],[400,378],[296,334],[334,299],[299,296],[6,351],[351,168],[168,6],[376,352],[352,411],[411,376],[307,325],[325,320],[320,307],[285,295],[295,336],[336,285],[320,319],[319,404],[404,320],[329,330],[330,349],[349,329],[334,293],[293,333],[333,334],[366,323],[323,447],[447,366],[316,15],[15,315],[315,316],[331,358],[358,279],[279,331],[317,14],[14,316],[316,317],[8,285],[285,9],[9,8],[277,329],[329,350],[350,277],[253,374],[374,252],[252,253],[319,318],[318,403],[403,319],[351,6],[6,419],[419,351],[324,318],[318,325],[325,324],[397,367],[367,365],[365,397],[288,435],[435,397],[397,288],[278,344],[344,439],[439,278],[310,272],[272,311],[311,310],[248,195],[195,281],[281,248],[375,273],[273,291],[291,375],[175,396],[396,199],[199,175],[312,311],[311,268],[268,312],[276,283],[283,445],[445,276],[390,373],[373,339],[339,390],[295,282],[282,296],[296,295],[448,449],[449,346],[346,448],[356,264],[264,454],[454,356],[337,336],[336,299],[299,337],[337,338],[338,151],[151,337],[294,278],[278,455],[455,294],[308,292],[292,415],[415,308],[429,358],[358,355],[355,429],[265,340],[340,372],[372,265],[352,346],[346,280],[280,352],[295,442],[442,282],[282,295],[354,19],[19,370],[370,354],[285,441],[441,295],[295,285],[195,248],[248,197],[197,195],[457,440],[440,274],[274,457],[301,300],[300,368],[368,301],[417,351],[351,465],[465,417],[251,301],[301,389],[389,251],[394,395],[395,379],[379,394],[399,412],[412,419],[419,399],[410,436],[436,322],[322,410],[326,2],[2,393],[393,326],[354,370],[370,461],[461,354],[393,164],[164,267],[267,393],[268,302],[302,12],[12,268],[312,268],[268,13],[13,312],[298,293],[293,301],[301,298],[265,446],[446,340],[340,265],[280,330],[330,425],[425,280],[322,426],[426,391],[391,322],[420,429],[429,437],[437,420],[393,391],[391,326],[326,393],[344,440],[440,438],[438,344],[458,459],[459,461],[461,458],[364,434],[434,394],[394,364],[428,396],[396,262],[262,428],[274,354],[354,457],[457,274],[317,316],[316,402],[402,317],[316,315],[315,403],[403,316],[315,314],[314,404],[404,315],[314,313],[313,405],[405,314],[313,421],[421,406],[406,313],[323,366],[366,361],[361,323],[292,306],[306,407],[407,292],[306,291],[291,408],[408,306],[291,287],[287,409],[409,291],[287,432],[432,410],[410,287],[427,434],[434,411],[411,427],[372,264],[264,383],[383,372],[459,309],[309,457],[457,459],[366,352],[352,401],[401,366],[1,274],[274,4],[4,1],[418,421],[421,262],[262,418],[331,294],[294,358],[358,331],[435,433],[433,367],[367,435],[392,289],[289,439],[439,392],[328,462],[462,326],[326,328],[94,2],[2,370],[370,94],[289,305],[305,455],[455,289],[339,254],[254,448],[448,339],[359,255],[255,446],[446,359],[254,253],[253,449],[449,254],[253,252],[252,450],[450,253],[252,256],[256,451],[451,252],[256,341],[341,452],[452,256],[414,413],[413,463],[463,414],[286,441],[441,414],[414,286],[286,258],[258,441],[441,286],[258,257],[257,442],[442,258],[257,259],[259,443],[443,257],[259,260],[260,444],[444,259],[260,467],[467,445],[445,260],[309,459],[459,250],[250,309],[305,289],[289,290],[290,305],[305,290],[290,460],[460,305],[401,376],[376,435],[435,401],[309,250],[250,392],[392,309],[376,411],[411,433],[433,376],[453,341],[341,464],[464,453],[357,453],[453,465],[465,357],[343,357],[357,412],[412,343],[437,343],[343,399],[399,437],[344,360],[360,440],[440,344],[420,437],[437,456],[456,420],[360,420],[420,363],[363,360],[361,401],[401,288],[288,361],[265,372],[372,353],[353,265],[390,339],[339,249],[249,390],[339,448],[448,255],[255,339]);function lc(t){t.j={faceLandmarks:[],faceBlendshapes:[],facialTransformationMatrixes:[]}}var fc=class extends Qa{constructor(t,e){super(new Ka(t,e),"image_in","norm_rect",!1),this.j={faceLandmarks:[],faceBlendshapes:[],facialTransformationMatrixes:[]},this.outputFacialTransformationMatrixes=this.outputFaceBlendshapes=!1,un(t=this.h=new js,0,1,e=new Ps),this.v=new Gs,un(this.h,0,3,this.v),this.s=new Us,un(this.h,0,2,this.s),En(this.s,4,1),wn(this.s,2,.5),wn(this.v,2,.5),wn(this.h,4,.5)}get baseOptions(){return an(this.h,Ps,1)}set baseOptions(t){un(this.h,0,1,t)}o(t){return"numFaces"in t&&En(this.s,4,t.numFaces??1),"minFaceDetectionConfidence"in t&&wn(this.s,2,t.minFaceDetectionConfidence??.5),"minTrackingConfidence"in t&&wn(this.h,4,t.minTrackingConfidence??.5),"minFacePresenceConfidence"in t&&wn(this.v,2,t.minFacePresenceConfidence??.5),"outputFaceBlendshapes"in t&&(this.outputFaceBlendshapes=!!t.outputFaceBlendshapes),"outputFacialTransformationMatrixes"in t&&(this.outputFacialTransformationMatrixes=!!t.outputFacialTransformationMatrixes),this.l(t)}D(t,e){return lc(this),qa(this,t,e),this.j}F(t,e,n){return lc(this),Ja(this,t,n,e),this.j}m(){var t=new es;Qi(t,"image_in"),Qi(t,"norm_rect"),ts(t,"face_landmarks");const e=new Vi;Yn(e,Hs,this.h);const n=new Yi;Wi(n,"mediapipe.tasks.vision.face_landmarker.FaceLandmarkerGraph"),zi(n,"IMAGE:image_in"),zi(n,"NORM_RECT:norm_rect"),Ki(n,"NORM_LANDMARKS:face_landmarks"),n.o(e),Zi(t,n),this.g.attachProtoVectorListener("face_landmarks",((t,e)=>{for(const e of t)t=gs(e),this.j.faceLandmarks.push(Fo(t));qo(this,e)})),this.g.attachEmptyPacketListener("face_landmarks",(t=>{qo(this,t)})),this.outputFaceBlendshapes&&(ts(t,"blendshapes"),Ki(n,"BLENDSHAPES:blendshapes"),this.g.attachProtoVectorListener("blendshapes",((t,e)=>{if(this.outputFaceBlendshapes)for(const e of t)t=as(e),this.j.faceBlendshapes.push(Lo(t.g()??[]));qo(this,e)})),this.g.attachEmptyPacketListener("blendshapes",(t=>{qo(this,t)}))),this.outputFacialTransformationMatrixes&&(ts(t,"face_geometry"),Ki(n,"FACE_GEOMETRY:face_geometry"),this.g.attachProtoVectorListener("face_geometry",((t,e)=>{if(this.outputFacialTransformationMatrixes)for(const e of t)(t=an(Bs(e),ms,2))&&this.j.facialTransformationMatrixes.push({rows:gn(mn(t,1),0)??0,columns:gn(mn(t,2),0)??0,data:Ke(t,3,Wt,ze()).slice()??[]});qo(this,e)})),this.g.attachEmptyPacketListener("face_geometry",(t=>{qo(this,t)}))),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};fc.prototype.detectForVideo=fc.prototype.F,fc.prototype.detect=fc.prototype.D,fc.prototype.setOptions=fc.prototype.o,fc.createFromModelPath=function(t,e){return Ya(fc,t,{baseOptions:{modelAssetPath:e}})},fc.createFromModelBuffer=function(t,e){return Ya(fc,t,{baseOptions:{modelAssetBuffer:e}})},fc.createFromOptions=function(t,e){return Ya(fc,t,e)},fc.FACE_LANDMARKS_LIPS=ec,fc.FACE_LANDMARKS_LEFT_EYE=nc,fc.FACE_LANDMARKS_LEFT_EYEBROW=rc,fc.FACE_LANDMARKS_LEFT_IRIS=ic,fc.FACE_LANDMARKS_RIGHT_EYE=sc,fc.FACE_LANDMARKS_RIGHT_EYEBROW=oc,fc.FACE_LANDMARKS_RIGHT_IRIS=ac,fc.FACE_LANDMARKS_FACE_OVAL=cc,fc.FACE_LANDMARKS_CONTOURS=hc,fc.FACE_LANDMARKS_TESSELATION=uc;var dc=class extends Qa{constructor(t,e){super(new Ka(t,e),"image_in","norm_rect",!0),un(t=this.j=new Ws,0,1,e=new Ps)}get baseOptions(){return an(this.j,Ps,1)}set baseOptions(t){un(this.j,0,1,t)}o(t){return super.l(t)}Oa(t,e,n){const r="function"!=typeof e?e:{};if(this.h="function"==typeof e?e:n,qa(this,t,r??{}),!this.h)return this.s}m(){var t=new es;Qi(t,"image_in"),Qi(t,"norm_rect"),ts(t,"stylized_image");const e=new Vi;Yn(e,zs,this.j);const n=new Yi;Wi(n,"mediapipe.tasks.vision.face_stylizer.FaceStylizerGraph"),zi(n,"IMAGE:image_in"),zi(n,"NORM_RECT:norm_rect"),Ki(n,"STYLIZED_IMAGE:stylized_image"),n.o(e),Zi(t,n),this.g.V("stylized_image",((t,e)=>{var n=!this.h,r=t.data,i=t.width;const s=i*(t=t.height);if(r instanceof Uint8Array)if(r.length===3*s){const e=new Uint8ClampedArray(4*s);for(let t=0;t<s;++t)e[4*t]=r[3*t],e[4*t+1]=r[3*t+1],e[4*t+2]=r[3*t+2],e[4*t+3]=255;r=new ImageData(e,i,t)}else{if(r.length!==4*s)throw Error("Unsupported channel count: "+r.length/s);r=new ImageData(new Uint8ClampedArray(r.buffer,r.byteOffset,r.length),i,t)}else if(!(r instanceof WebGLTexture))throw Error(`Unsupported format: ${r.constructor.name}`);i=new Va([r],!1,!1,this.g.i.canvas,this.P,i,t),this.s=n=n?i.clone():i,this.h&&this.h(n),qo(this,e)})),this.g.attachEmptyPacketListener("stylized_image",(t=>{this.s=null,this.h&&this.h(null),qo(this,t)})),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};dc.prototype.stylize=dc.prototype.Oa,dc.prototype.setOptions=dc.prototype.o,dc.createFromModelPath=function(t,e){return Ya(dc,t,{baseOptions:{modelAssetPath:e}})},dc.createFromModelBuffer=function(t,e){return Ya(dc,t,{baseOptions:{modelAssetBuffer:e}})},dc.createFromOptions=function(t,e){return Ya(dc,t,e)};var pc=Ha([0,1],[1,2],[2,3],[3,4],[0,5],[5,6],[6,7],[7,8],[5,9],[9,10],[10,11],[11,12],[9,13],[13,14],[14,15],[15,16],[13,17],[0,17],[17,18],[18,19],[19,20]);function gc(t){t.gestures=[],t.landmarks=[],t.worldLandmarks=[],t.handedness=[]}function mc(t){return 0===t.gestures.length?{gestures:[],landmarks:[],worldLandmarks:[],handedness:[],handednesses:[]}:{gestures:t.gestures,landmarks:t.landmarks,worldLandmarks:t.worldLandmarks,handedness:t.handedness,handednesses:t.handedness}}function yc(t,e=!0){const n=[];for(const i of t){var r=as(i);t=[];for(const n of r.g())r=e&&null!=mn(n,1)?gn(mn(n,1),0):-1,t.push({score:yn(n,2)??0,index:r,categoryName:_n(n,3)??"",displayName:_n(n,4)??""});n.push(t)}return n}var _c=class extends Qa{constructor(t,e){super(new Ka(t,e),"image_in","norm_rect",!1),this.gestures=[],this.landmarks=[],this.worldLandmarks=[],this.handedness=[],un(t=this.j=new Qs,0,1,e=new Ps),this.s=new Zs,un(this.j,0,2,this.s),this.C=new Js,un(this.s,0,3,this.C),this.v=new qs,un(this.s,0,2,this.v),this.h=new $s,un(this.j,0,3,this.h),wn(this.v,2,.5),wn(this.s,4,.5),wn(this.C,2,.5)}get baseOptions(){return an(this.j,Ps,1)}set baseOptions(t){un(this.j,0,1,t)}o(t){if(En(this.v,3,t.numHands??1),"minHandDetectionConfidence"in t&&wn(this.v,2,t.minHandDetectionConfidence??.5),"minTrackingConfidence"in t&&wn(this.s,4,t.minTrackingConfidence??.5),"minHandPresenceConfidence"in t&&wn(this.C,2,t.minHandPresenceConfidence??.5),t.cannedGesturesClassifierOptions){var e=new Ks,n=e,r=So(t.cannedGesturesClassifierOptions,an(this.h,Ks,3)?.h());un(n,0,2,r),un(this.h,0,3,e)}else void 0===t.cannedGesturesClassifierOptions&&an(this.h,Ks,3)?.g();return t.customGesturesClassifierOptions?(un(n=e=new Ks,0,2,r=So(t.customGesturesClassifierOptions,an(this.h,Ks,4)?.h())),un(this.h,0,4,e)):void 0===t.customGesturesClassifierOptions&&an(this.h,Ks,4)?.g(),this.l(t)}Ja(t,e){return gc(this),qa(this,t,e),mc(this)}Ka(t,e,n){return gc(this),Ja(this,t,n,e),mc(this)}m(){var t=new es;Qi(t,"image_in"),Qi(t,"norm_rect"),ts(t,"hand_gestures"),ts(t,"hand_landmarks"),ts(t,"world_hand_landmarks"),ts(t,"handedness");const e=new Vi;Yn(e,io,this.j);const n=new Yi;Wi(n,"mediapipe.tasks.vision.gesture_recognizer.GestureRecognizerGraph"),zi(n,"IMAGE:image_in"),zi(n,"NORM_RECT:norm_rect"),Ki(n,"HAND_GESTURES:hand_gestures"),Ki(n,"LANDMARKS:hand_landmarks"),Ki(n,"WORLD_LANDMARKS:world_hand_landmarks"),Ki(n,"HANDEDNESS:handedness"),n.o(e),Zi(t,n),this.g.attachProtoVectorListener("hand_landmarks",((t,e)=>{for(const e of t){t=gs(e);const n=[];for(const e of hn(t,ps,1))n.push({x:yn(e,1)??0,y:yn(e,2)??0,z:yn(e,3)??0,visibility:yn(e,4)??0});this.landmarks.push(n)}qo(this,e)})),this.g.attachEmptyPacketListener("hand_landmarks",(t=>{qo(this,t)})),this.g.attachProtoVectorListener("world_hand_landmarks",((t,e)=>{for(const e of t){t=ds(e);const n=[];for(const e of hn(t,fs,1))n.push({x:yn(e,1)??0,y:yn(e,2)??0,z:yn(e,3)??0,visibility:yn(e,4)??0});this.worldLandmarks.push(n)}qo(this,e)})),this.g.attachEmptyPacketListener("world_hand_landmarks",(t=>{qo(this,t)})),this.g.attachProtoVectorListener("hand_gestures",((t,e)=>{this.gestures.push(...yc(t,!1)),qo(this,e)})),this.g.attachEmptyPacketListener("hand_gestures",(t=>{qo(this,t)})),this.g.attachProtoVectorListener("handedness",((t,e)=>{this.handedness.push(...yc(t)),qo(this,e)})),this.g.attachEmptyPacketListener("handedness",(t=>{qo(this,t)})),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};function vc(t){return{landmarks:t.landmarks,worldLandmarks:t.worldLandmarks,handednesses:t.handedness,handedness:t.handedness}}_c.prototype.recognizeForVideo=_c.prototype.Ka,_c.prototype.recognize=_c.prototype.Ja,_c.prototype.setOptions=_c.prototype.o,_c.createFromModelPath=function(t,e){return Ya(_c,t,{baseOptions:{modelAssetPath:e}})},_c.createFromModelBuffer=function(t,e){return Ya(_c,t,{baseOptions:{modelAssetBuffer:e}})},_c.createFromOptions=function(t,e){return Ya(_c,t,e)},_c.HAND_CONNECTIONS=pc;var Ec=class extends Qa{constructor(t,e){super(new Ka(t,e),"image_in","norm_rect",!1),this.landmarks=[],this.worldLandmarks=[],this.handedness=[],un(t=this.h=new Zs,0,1,e=new Ps),this.s=new Js,un(this.h,0,3,this.s),this.j=new qs,un(this.h,0,2,this.j),En(this.j,3,1),wn(this.j,2,.5),wn(this.s,2,.5),wn(this.h,4,.5)}get baseOptions(){return an(this.h,Ps,1)}set baseOptions(t){un(this.h,0,1,t)}o(t){return"numHands"in t&&En(this.j,3,t.numHands??1),"minHandDetectionConfidence"in t&&wn(this.j,2,t.minHandDetectionConfidence??.5),"minTrackingConfidence"in t&&wn(this.h,4,t.minTrackingConfidence??.5),"minHandPresenceConfidence"in t&&wn(this.s,2,t.minHandPresenceConfidence??.5),this.l(t)}D(t,e){return this.landmarks=[],this.worldLandmarks=[],this.handedness=[],qa(this,t,e),vc(this)}F(t,e,n){return this.landmarks=[],this.worldLandmarks=[],this.handedness=[],Ja(this,t,n,e),vc(this)}m(){var t=new es;Qi(t,"image_in"),Qi(t,"norm_rect"),ts(t,"hand_landmarks"),ts(t,"world_hand_landmarks"),ts(t,"handedness");const e=new Vi;Yn(e,so,this.h);const n=new Yi;Wi(n,"mediapipe.tasks.vision.hand_landmarker.HandLandmarkerGraph"),zi(n,"IMAGE:image_in"),zi(n,"NORM_RECT:norm_rect"),Ki(n,"LANDMARKS:hand_landmarks"),Ki(n,"WORLD_LANDMARKS:world_hand_landmarks"),Ki(n,"HANDEDNESS:handedness"),n.o(e),Zi(t,n),this.g.attachProtoVectorListener("hand_landmarks",((t,e)=>{for(const e of t)t=gs(e),this.landmarks.push(Fo(t));qo(this,e)})),this.g.attachEmptyPacketListener("hand_landmarks",(t=>{qo(this,t)})),this.g.attachProtoVectorListener("world_hand_landmarks",((t,e)=>{for(const e of t)t=ds(e),this.worldLandmarks.push(Io(t));qo(this,e)})),this.g.attachEmptyPacketListener("world_hand_landmarks",(t=>{qo(this,t)})),this.g.attachProtoVectorListener("handedness",((t,e)=>{var n=this.handedness,r=n.push;const i=[];for(const e of t){t=as(e);const n=[];for(const e of t.g())n.push({score:yn(e,2)??0,index:gn(mn(e,1),0)??-1,categoryName:_n(e,3)??"",displayName:_n(e,4)??""});i.push(n)}r.call(n,...i),qo(this,e)})),this.g.attachEmptyPacketListener("handedness",(t=>{qo(this,t)})),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};Ec.prototype.detectForVideo=Ec.prototype.F,Ec.prototype.detect=Ec.prototype.D,Ec.prototype.setOptions=Ec.prototype.o,Ec.createFromModelPath=function(t,e){return Ya(Ec,t,{baseOptions:{modelAssetPath:e}})},Ec.createFromModelBuffer=function(t,e){return Ya(Ec,t,{baseOptions:{modelAssetBuffer:e}})},Ec.createFromOptions=function(t,e){return Ya(Ec,t,e)},Ec.HAND_CONNECTIONS=pc;var wc=Ha([0,1],[1,2],[2,3],[3,7],[0,4],[4,5],[5,6],[6,8],[9,10],[11,12],[11,13],[13,15],[15,17],[15,19],[15,21],[17,19],[12,14],[14,16],[16,18],[16,20],[16,22],[18,20],[11,23],[12,24],[23,24],[23,25],[24,26],[25,27],[26,28],[27,29],[28,30],[29,31],[30,32],[27,31],[28,32]);function Tc(t){t.h={faceLandmarks:[],faceBlendshapes:[],poseLandmarks:[],poseWorldLandmarks:[],poseSegmentationMasks:[],leftHandLandmarks:[],leftHandWorldLandmarks:[],rightHandLandmarks:[],rightHandWorldLandmarks:[]}}function bc(t){try{if(!t.C)return t.h;t.C(t.h)}finally{Qo(t)}}function Ac(t,e){t=gs(t),e.push(Fo(t))}var kc=class extends Qa{constructor(t,e){super(new Ka(t,e),"input_frames_image",null,!1),this.h={faceLandmarks:[],faceBlendshapes:[],poseLandmarks:[],poseWorldLandmarks:[],poseSegmentationMasks:[],leftHandLandmarks:[],leftHandWorldLandmarks:[],rightHandLandmarks:[],rightHandWorldLandmarks:[]},this.outputPoseSegmentationMasks=this.outputFaceBlendshapes=!1,un(t=this.j=new ho,0,1,e=new Ps),this.K=new Js,un(this.j,0,2,this.K),this.aa=new oo,un(this.j,0,3,this.aa),this.s=new Us,un(this.j,0,4,this.s),this.I=new Gs,un(this.j,0,5,this.I),this.v=new ao,un(this.j,0,6,this.v),this.L=new co,un(this.j,0,7,this.L),wn(this.s,2,.5),wn(this.s,3,.3),wn(this.I,2,.5),wn(this.v,2,.5),wn(this.v,3,.3),wn(this.L,2,.5),wn(this.K,2,.5)}get baseOptions(){return an(this.j,Ps,1)}set baseOptions(t){un(this.j,0,1,t)}o(t){return"minFaceDetectionConfidence"in t&&wn(this.s,2,t.minFaceDetectionConfidence??.5),"minFaceSuppressionThreshold"in t&&wn(this.s,3,t.minFaceSuppressionThreshold??.3),"minFacePresenceConfidence"in t&&wn(this.I,2,t.minFacePresenceConfidence??.5),"outputFaceBlendshapes"in t&&(this.outputFaceBlendshapes=!!t.outputFaceBlendshapes),"minPoseDetectionConfidence"in t&&wn(this.v,2,t.minPoseDetectionConfidence??.5),"minPoseSuppressionThreshold"in t&&wn(this.v,3,t.minPoseSuppressionThreshold??.3),"minPosePresenceConfidence"in t&&wn(this.L,2,t.minPosePresenceConfidence??.5),"outputPoseSegmentationMasks"in t&&(this.outputPoseSegmentationMasks=!!t.outputPoseSegmentationMasks),"minHandLandmarksConfidence"in t&&wn(this.K,2,t.minHandLandmarksConfidence??.5),this.l(t)}D(t,e,n){const r="function"!=typeof e?e:{};return this.C="function"==typeof e?e:n,Tc(this),qa(this,t,r),bc(this)}F(t,e,n,r){const i="function"!=typeof n?n:{};return this.C="function"==typeof n?n:r,Tc(this),Ja(this,t,i,e),bc(this)}m(){var t=new es;Qi(t,"input_frames_image"),ts(t,"pose_landmarks"),ts(t,"pose_world_landmarks"),ts(t,"face_landmarks"),ts(t,"left_hand_landmarks"),ts(t,"left_hand_world_landmarks"),ts(t,"right_hand_landmarks"),ts(t,"right_hand_world_landmarks");const e=new Vi,n=new Ri;Ze(n,1,re("type.googleapis.com/mediapipe.tasks.vision.holistic_landmarker.proto.HolisticLandmarkerGraphOptions"),""),function(t,e){if(null!=e)if(Array.isArray(e))Ve(t,2,Me(e,Oe,void 0,void 0,!1));else{if(!("string"==typeof e||e instanceof B||C(e)))throw Error("invalid value in Any.value field: "+e+" expected a ByteString, a base64 encoded string, a Uint8Array or a jspb array");Ze(t,2,dt(e,!1),N())}}(n,this.j.g());const r=new Yi;Wi(r,"mediapipe.tasks.vision.holistic_landmarker.HolisticLandmarkerGraph"),pn(r,8,Ri,n),zi(r,"IMAGE:input_frames_image"),Ki(r,"POSE_LANDMARKS:pose_landmarks"),Ki(r,"POSE_WORLD_LANDMARKS:pose_world_landmarks"),Ki(r,"FACE_LANDMARKS:face_landmarks"),Ki(r,"LEFT_HAND_LANDMARKS:left_hand_landmarks"),Ki(r,"LEFT_HAND_WORLD_LANDMARKS:left_hand_world_landmarks"),Ki(r,"RIGHT_HAND_LANDMARKS:right_hand_landmarks"),Ki(r,"RIGHT_HAND_WORLD_LANDMARKS:right_hand_world_landmarks"),r.o(e),Zi(t,r),Jo(this,t),this.g.attachProtoListener("pose_landmarks",((t,e)=>{Ac(t,this.h.poseLandmarks),qo(this,e)})),this.g.attachEmptyPacketListener("pose_landmarks",(t=>{qo(this,t)})),this.g.attachProtoListener("pose_world_landmarks",((t,e)=>{var n=this.h.poseWorldLandmarks;t=ds(t),n.push(Io(t)),qo(this,e)})),this.g.attachEmptyPacketListener("pose_world_landmarks",(t=>{qo(this,t)})),this.outputPoseSegmentationMasks&&(Ki(r,"POSE_SEGMENTATION_MASK:pose_segmentation_mask"),Zo(this,"pose_segmentation_mask"),this.g.V("pose_segmentation_mask",((t,e)=>{this.h.poseSegmentationMasks=[Za(this,t,!0,!this.C)],qo(this,e)})),this.g.attachEmptyPacketListener("pose_segmentation_mask",(t=>{this.h.poseSegmentationMasks=[],qo(this,t)}))),this.g.attachProtoListener("face_landmarks",((t,e)=>{Ac(t,this.h.faceLandmarks),qo(this,e)})),this.g.attachEmptyPacketListener("face_landmarks",(t=>{qo(this,t)})),this.outputFaceBlendshapes&&(ts(t,"extra_blendshapes"),Ki(r,"FACE_BLENDSHAPES:extra_blendshapes"),this.g.attachProtoListener("extra_blendshapes",((t,e)=>{var n=this.h.faceBlendshapes;this.outputFaceBlendshapes&&(t=as(t),n.push(Lo(t.g()??[]))),qo(this,e)})),this.g.attachEmptyPacketListener("extra_blendshapes",(t=>{qo(this,t)}))),this.g.attachProtoListener("left_hand_landmarks",((t,e)=>{Ac(t,this.h.leftHandLandmarks),qo(this,e)})),this.g.attachEmptyPacketListener("left_hand_landmarks",(t=>{qo(this,t)})),this.g.attachProtoListener("left_hand_world_landmarks",((t,e)=>{var n=this.h.leftHandWorldLandmarks;t=ds(t),n.push(Io(t)),qo(this,e)})),this.g.attachEmptyPacketListener("left_hand_world_landmarks",(t=>{qo(this,t)})),this.g.attachProtoListener("right_hand_landmarks",((t,e)=>{Ac(t,this.h.rightHandLandmarks),qo(this,e)})),this.g.attachEmptyPacketListener("right_hand_landmarks",(t=>{qo(this,t)})),this.g.attachProtoListener("right_hand_world_landmarks",((t,e)=>{var n=this.h.rightHandWorldLandmarks;t=ds(t),n.push(Io(t)),qo(this,e)})),this.g.attachEmptyPacketListener("right_hand_world_landmarks",(t=>{qo(this,t)})),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};kc.prototype.detectForVideo=kc.prototype.F,kc.prototype.detect=kc.prototype.D,kc.prototype.setOptions=kc.prototype.o,kc.createFromModelPath=function(t,e){return Ya(kc,t,{baseOptions:{modelAssetPath:e}})},kc.createFromModelBuffer=function(t,e){return Ya(kc,t,{baseOptions:{modelAssetBuffer:e}})},kc.createFromOptions=function(t,e){return Ya(kc,t,e)},kc.HAND_CONNECTIONS=pc,kc.POSE_CONNECTIONS=wc,kc.FACE_LANDMARKS_LIPS=ec,kc.FACE_LANDMARKS_LEFT_EYE=nc,kc.FACE_LANDMARKS_LEFT_EYEBROW=rc,kc.FACE_LANDMARKS_LEFT_IRIS=ic,kc.FACE_LANDMARKS_RIGHT_EYE=sc,kc.FACE_LANDMARKS_RIGHT_EYEBROW=oc,kc.FACE_LANDMARKS_RIGHT_IRIS=ac,kc.FACE_LANDMARKS_FACE_OVAL=cc,kc.FACE_LANDMARKS_CONTOURS=hc,kc.FACE_LANDMARKS_TESSELATION=uc;var xc=class extends Qa{constructor(t,e){super(new Ka(t,e),"input_image","norm_rect",!0),this.j={classifications:[]},un(t=this.h=new fo,0,1,e=new Ps)}get baseOptions(){return an(this.h,Ps,1)}set baseOptions(t){un(this.h,0,1,t)}o(t){return un(this.h,0,2,So(t,an(this.h,xs,2))),this.l(t)}ta(t,e){return this.j={classifications:[]},qa(this,t,e),this.j}ua(t,e,n){return this.j={classifications:[]},Ja(this,t,n,e),this.j}m(){var t=new es;Qi(t,"input_image"),Qi(t,"norm_rect"),ts(t,"classifications");const e=new Vi;Yn(e,po,this.h);const n=new Yi;Wi(n,"mediapipe.tasks.vision.image_classifier.ImageClassifierGraph"),zi(n,"IMAGE:input_image"),zi(n,"NORM_RECT:norm_rect"),Ki(n,"CLASSIFICATIONS:classifications"),n.o(e),Zi(t,n),this.g.attachProtoListener("classifications",((t,e)=>{this.j=function(t){const e={classifications:hn(t,vs,1).map((t=>Lo(an(t,ss,4)?.g()??[],gn(mn(t,2),0),_n(t,3))))};return null!=te(Be(t,2))&&(e.timestampMs=gn(te(Be(t,2)),0)),e}(Es(t)),qo(this,e)})),this.g.attachEmptyPacketListener("classifications",(t=>{qo(this,t)})),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};xc.prototype.classifyForVideo=xc.prototype.ua,xc.prototype.classify=xc.prototype.ta,xc.prototype.setOptions=xc.prototype.o,xc.createFromModelPath=function(t,e){return Ya(xc,t,{baseOptions:{modelAssetPath:e}})},xc.createFromModelBuffer=function(t,e){return Ya(xc,t,{baseOptions:{modelAssetBuffer:e}})},xc.createFromOptions=function(t,e){return Ya(xc,t,e)};var Sc=class extends Qa{constructor(t,e){super(new Ka(t,e),"image_in","norm_rect",!0),this.h=new go,this.embeddings={embeddings:[]},un(t=this.h,0,1,e=new Ps)}get baseOptions(){return an(this.h,Ps,1)}set baseOptions(t){un(this.h,0,1,t)}o(t){var e=this.h,n=an(this.h,Ls,2);return n=n?n.clone():new Ls,void 0!==t.l2Normalize?vn(n,1,t.l2Normalize):"l2Normalize"in t&&Ve(n,1),void 0!==t.quantize?vn(n,2,t.quantize):"quantize"in t&&Ve(n,2),un(e,0,2,n),this.l(t)}Aa(t,e){return qa(this,t,e),this.embeddings}Ba(t,e,n){return Ja(this,t,n,e),this.embeddings}m(){var t=new es;Qi(t,"image_in"),Qi(t,"norm_rect"),ts(t,"embeddings_out");const e=new Vi;Yn(e,mo,this.h);const n=new Yi;Wi(n,"mediapipe.tasks.vision.image_embedder.ImageEmbedderGraph"),zi(n,"IMAGE:image_in"),zi(n,"NORM_RECT:norm_rect"),Ki(n,"EMBEDDINGS:embeddings_out"),n.o(e),Zi(t,n),this.g.attachProtoListener("embeddings_out",((t,e)=>{t=ks(t),this.embeddings=function(t){return{embeddings:hn(t,bs,1).map((t=>{const e={headIndex:gn(mn(t,3),0)??-1,headName:_n(t,4)??""};if(void 0!==on(t,ws,tn(t,1)))t=Ke(t=an(t,ws,tn(t,1)),1,Wt,ze()),e.floatEmbedding=t.slice();else{const n=new Uint8Array(0);e.quantizedEmbedding=an(t,Ts,tn(t,2))?.pa()?.h()??n}return e})),timestampMs:gn(te(Be(t,2)),0)}}(t),qo(this,e)})),this.g.attachEmptyPacketListener("embeddings_out",(t=>{qo(this,t)})),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};Sc.cosineSimilarity=function(t,e){if(t.floatEmbedding&&e.floatEmbedding)t=Po(t.floatEmbedding,e.floatEmbedding);else{if(!t.quantizedEmbedding||!e.quantizedEmbedding)throw Error("Cannot compute cosine similarity between quantized and float embeddings.");t=Po(Mo(t.quantizedEmbedding),Mo(e.quantizedEmbedding))}return t},Sc.prototype.embedForVideo=Sc.prototype.Ba,Sc.prototype.embed=Sc.prototype.Aa,Sc.prototype.setOptions=Sc.prototype.o,Sc.createFromModelPath=function(t,e){return Ya(Sc,t,{baseOptions:{modelAssetPath:e}})},Sc.createFromModelBuffer=function(t,e){return Ya(Sc,t,{baseOptions:{modelAssetBuffer:e}})},Sc.createFromOptions=function(t,e){return Ya(Sc,t,e)};var Lc=class{constructor(t,e,n){this.confidenceMasks=t,this.categoryMask=e,this.qualityScores=n}close(){this.confidenceMasks?.forEach((t=>{t.close()})),this.categoryMask?.close()}};function Rc(t){t.categoryMask=void 0,t.confidenceMasks=void 0,t.qualityScores=void 0}function Fc(t){try{const e=new Lc(t.confidenceMasks,t.categoryMask,t.qualityScores);if(!t.j)return e;t.j(e)}finally{Qo(t)}}Lc.prototype.close=Lc.prototype.close;var Ic=class extends Qa{constructor(t,e){super(new Ka(t,e),"image_in","norm_rect",!1),this.s=[],this.outputCategoryMask=!1,this.outputConfidenceMasks=!0,this.h=new wo,this.v=new yo,un(this.h,0,3,this.v),un(t=this.h,0,1,e=new Ps)}get baseOptions(){return an(this.h,Ps,1)}set baseOptions(t){un(this.h,0,1,t)}o(t){return void 0!==t.displayNamesLocale?Ve(this.h,2,re(t.displayNamesLocale)):"displayNamesLocale"in t&&Ve(this.h,2),"outputCategoryMask"in t&&(this.outputCategoryMask=t.outputCategoryMask??!1),"outputConfidenceMasks"in t&&(this.outputConfidenceMasks=t.outputConfidenceMasks??!0),super.l(t)}J(){!function(t){const e=hn(t.ea(),Yi,1).filter((t=>_n(t,1).includes("mediapipe.tasks.TensorsToSegmentationCalculator")));if(t.s=[],e.length>1)throw Error("The graph has more than one mediapipe.tasks.TensorsToSegmentationCalculator.");1===e.length&&(an(e[0],Vi,7)?.l()?.g()??new Map).forEach(((e,n)=>{t.s[Number(n)]=_n(e,1)}))}(this)}segment(t,e,n){const r="function"!=typeof e?e:{};return this.j="function"==typeof e?e:n,Rc(this),qa(this,t,r),Fc(this)}Ma(t,e,n,r){const i="function"!=typeof n?n:{};return this.j="function"==typeof n?n:r,Rc(this),Ja(this,t,i,e),Fc(this)}Ea(){return this.s}m(){var t=new es;Qi(t,"image_in"),Qi(t,"norm_rect");const e=new Vi;Yn(e,To,this.h);const n=new Yi;Wi(n,"mediapipe.tasks.vision.image_segmenter.ImageSegmenterGraph"),zi(n,"IMAGE:image_in"),zi(n,"NORM_RECT:norm_rect"),n.o(e),Zi(t,n),Jo(this,t),this.outputConfidenceMasks&&(ts(t,"confidence_masks"),Ki(n,"CONFIDENCE_MASKS:confidence_masks"),Zo(this,"confidence_masks"),this.g.da("confidence_masks",((t,e)=>{this.confidenceMasks=t.map((t=>Za(this,t,!0,!this.j))),qo(this,e)})),this.g.attachEmptyPacketListener("confidence_masks",(t=>{this.confidenceMasks=[],qo(this,t)}))),this.outputCategoryMask&&(ts(t,"category_mask"),Ki(n,"CATEGORY_MASK:category_mask"),Zo(this,"category_mask"),this.g.V("category_mask",((t,e)=>{this.categoryMask=Za(this,t,!1,!this.j),qo(this,e)})),this.g.attachEmptyPacketListener("category_mask",(t=>{this.categoryMask=void 0,qo(this,t)}))),ts(t,"quality_scores"),Ki(n,"QUALITY_SCORES:quality_scores"),this.g.attachFloatVectorListener("quality_scores",((t,e)=>{this.qualityScores=t,qo(this,e)})),this.g.attachEmptyPacketListener("quality_scores",(t=>{this.categoryMask=void 0,qo(this,t)})),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};Ic.prototype.getLabels=Ic.prototype.Ea,Ic.prototype.segmentForVideo=Ic.prototype.Ma,Ic.prototype.segment=Ic.prototype.segment,Ic.prototype.setOptions=Ic.prototype.o,Ic.createFromModelPath=function(t,e){return Ya(Ic,t,{baseOptions:{modelAssetPath:e}})},Ic.createFromModelBuffer=function(t,e){return Ya(Ic,t,{baseOptions:{modelAssetBuffer:e}})},Ic.createFromOptions=function(t,e){return Ya(Ic,t,e)};var Mc=class{constructor(t,e,n){this.confidenceMasks=t,this.categoryMask=e,this.qualityScores=n}close(){this.confidenceMasks?.forEach((t=>{t.close()})),this.categoryMask?.close()}};Mc.prototype.close=Mc.prototype.close;var Pc=class extends $n{constructor(t){super(t)}},Oc=[0,li,-2],Cc=[0,ii,-3,pi,ii,-1],Uc=[0,Cc],Nc=[0,Cc,li,-1],Dc=class extends $n{constructor(t){super(t)}},Bc=[0,ii,-1,pi],Gc=class extends $n{constructor(){super()}},jc=class extends $n{constructor(t){super(t)}},Vc=[1,2,3,4,5,6,7,8,9,10,14,15],Xc=class extends $n{constructor(){super()}};Xc.prototype.g=Li([0,vi,[0,Vc,Ei,Cc,Ei,[0,Cc,Oc],Ei,Uc,Ei,[0,Uc,Oc],Ei,Bc,Ei,[0,ii,-3,pi,Ai],Ei,[0,ii,-3,pi],Ei,[0,_i,ii,-2,pi,li,pi,-1,2,ii,Oc],Ei,Nc,Ei,[0,Nc,Oc],ii,Oc,_i,Ei,[0,ii,-3,pi,Oc,-1],Ei,[0,vi,Bc]],_i,[0,_i,li,-1,pi]]);var Hc=class extends Qa{constructor(t,e){super(new Ka(t,e),"image_in","norm_rect_in",!1),this.outputCategoryMask=!1,this.outputConfidenceMasks=!0,this.h=new wo,this.s=new yo,un(this.h,0,3,this.s),un(t=this.h,0,1,e=new Ps)}get baseOptions(){return an(this.h,Ps,1)}set baseOptions(t){un(this.h,0,1,t)}o(t){return"outputCategoryMask"in t&&(this.outputCategoryMask=t.outputCategoryMask??!1),"outputConfidenceMasks"in t&&(this.outputConfidenceMasks=t.outputConfidenceMasks??!0),super.l(t)}segment(t,e,n,r){const i="function"!=typeof n?n:{};this.j="function"==typeof n?n:r,this.qualityScores=this.categoryMask=this.confidenceMasks=void 0,n=this.B+1,r=new Xc;const s=new jc;var o=new Pc;if(En(o,1,255),un(s,0,12,o),e.keypoint&&e.scribble)throw Error("Cannot provide both keypoint and scribble.");if(e.keypoint){var a=new Dc;vn(a,3,!0),wn(a,1,e.keypoint.x),wn(a,2,e.keypoint.y),ln(s,5,Vc,a)}else{if(!e.scribble)throw Error("Must provide either a keypoint or a scribble.");for(a of(o=new Gc,e.scribble))vn(e=new Dc,3,!0),wn(e,1,a.x),wn(e,2,a.y),pn(o,1,Dc,e);ln(s,15,Vc,o)}pn(r,1,jc,s),this.g.addProtoToStream(r.g(),"drishti.RenderData","roi_in",n),qa(this,t,i);t:{try{const t=new Mc(this.confidenceMasks,this.categoryMask,this.qualityScores);if(!this.j){var c=t;break t}this.j(t)}finally{Qo(this)}c=void 0}return c}m(){var t=new es;Qi(t,"image_in"),Qi(t,"roi_in"),Qi(t,"norm_rect_in");const e=new Vi;Yn(e,To,this.h);const n=new Yi;Wi(n,"mediapipe.tasks.vision.interactive_segmenter.InteractiveSegmenterGraph"),zi(n,"IMAGE:image_in"),zi(n,"ROI:roi_in"),zi(n,"NORM_RECT:norm_rect_in"),n.o(e),Zi(t,n),Jo(this,t),this.outputConfidenceMasks&&(ts(t,"confidence_masks"),Ki(n,"CONFIDENCE_MASKS:confidence_masks"),Zo(this,"confidence_masks"),this.g.da("confidence_masks",((t,e)=>{this.confidenceMasks=t.map((t=>Za(this,t,!0,!this.j))),qo(this,e)})),this.g.attachEmptyPacketListener("confidence_masks",(t=>{this.confidenceMasks=[],qo(this,t)}))),this.outputCategoryMask&&(ts(t,"category_mask"),Ki(n,"CATEGORY_MASK:category_mask"),Zo(this,"category_mask"),this.g.V("category_mask",((t,e)=>{this.categoryMask=Za(this,t,!1,!this.j),qo(this,e)})),this.g.attachEmptyPacketListener("category_mask",(t=>{this.categoryMask=void 0,qo(this,t)}))),ts(t,"quality_scores"),Ki(n,"QUALITY_SCORES:quality_scores"),this.g.attachFloatVectorListener("quality_scores",((t,e)=>{this.qualityScores=t,qo(this,e)})),this.g.attachEmptyPacketListener("quality_scores",(t=>{this.categoryMask=void 0,qo(this,t)})),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};Hc.prototype.segment=Hc.prototype.segment,Hc.prototype.setOptions=Hc.prototype.o,Hc.createFromModelPath=function(t,e){return Ya(Hc,t,{baseOptions:{modelAssetPath:e}})},Hc.createFromModelBuffer=function(t,e){return Ya(Hc,t,{baseOptions:{modelAssetBuffer:e}})},Hc.createFromOptions=function(t,e){return Ya(Hc,t,e)};var Wc=class extends Qa{constructor(t,e){super(new Ka(t,e),"input_frame_gpu","norm_rect",!1),this.j={detections:[]},un(t=this.h=new bo,0,1,e=new Ps)}get baseOptions(){return an(this.h,Ps,1)}set baseOptions(t){un(this.h,0,1,t)}o(t){return void 0!==t.displayNamesLocale?Ve(this.h,2,re(t.displayNamesLocale)):"displayNamesLocale"in t&&Ve(this.h,2),void 0!==t.maxResults?En(this.h,3,t.maxResults):"maxResults"in t&&Ve(this.h,3),void 0!==t.scoreThreshold?wn(this.h,4,t.scoreThreshold):"scoreThreshold"in t&&Ve(this.h,4),void 0!==t.categoryAllowlist?Tn(this.h,5,t.categoryAllowlist):"categoryAllowlist"in t&&Ve(this.h,5),void 0!==t.categoryDenylist?Tn(this.h,6,t.categoryDenylist):"categoryDenylist"in t&&Ve(this.h,6),this.l(t)}D(t,e){return this.j={detections:[]},qa(this,t,e),this.j}F(t,e,n){return this.j={detections:[]},Ja(this,t,n,e),this.j}m(){var t=new es;Qi(t,"input_frame_gpu"),Qi(t,"norm_rect"),ts(t,"detections");const e=new Vi;Yn(e,Ao,this.h);const n=new Yi;Wi(n,"mediapipe.tasks.vision.ObjectDetectorGraph"),zi(n,"IMAGE:input_frame_gpu"),zi(n,"NORM_RECT:norm_rect"),Ki(n,"DETECTIONS:detections"),n.o(e),Zi(t,n),this.g.attachProtoVectorListener("detections",((t,e)=>{for(const e of t)t=ls(e),this.j.detections.push(Ro(t));qo(this,e)})),this.g.attachEmptyPacketListener("detections",(t=>{qo(this,t)})),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};Wc.prototype.detectForVideo=Wc.prototype.F,Wc.prototype.detect=Wc.prototype.D,Wc.prototype.setOptions=Wc.prototype.o,Wc.createFromModelPath=async function(t,e){return Ya(Wc,t,{baseOptions:{modelAssetPath:e}})},Wc.createFromModelBuffer=function(t,e){return Ya(Wc,t,{baseOptions:{modelAssetBuffer:e}})},Wc.createFromOptions=function(t,e){return Ya(Wc,t,e)};var zc=class{constructor(t,e,n){this.landmarks=t,this.worldLandmarks=e,this.segmentationMasks=n}close(){this.segmentationMasks?.forEach((t=>{t.close()}))}};function Kc(t){t.landmarks=[],t.worldLandmarks=[],t.segmentationMasks=void 0}function Yc(t){try{const e=new zc(t.landmarks,t.worldLandmarks,t.segmentationMasks);if(!t.s)return e;t.s(e)}finally{Qo(t)}}zc.prototype.close=zc.prototype.close;var $c=class extends Qa{constructor(t,e){super(new Ka(t,e),"image_in","norm_rect",!1),this.landmarks=[],this.worldLandmarks=[],this.outputSegmentationMasks=!1,un(t=this.h=new ko,0,1,e=new Ps),this.v=new co,un(this.h,0,3,this.v),this.j=new ao,un(this.h,0,2,this.j),En(this.j,4,1),wn(this.j,2,.5),wn(this.v,2,.5),wn(this.h,4,.5)}get baseOptions(){return an(this.h,Ps,1)}set baseOptions(t){un(this.h,0,1,t)}o(t){return"numPoses"in t&&En(this.j,4,t.numPoses??1),"minPoseDetectionConfidence"in t&&wn(this.j,2,t.minPoseDetectionConfidence??.5),"minTrackingConfidence"in t&&wn(this.h,4,t.minTrackingConfidence??.5),"minPosePresenceConfidence"in t&&wn(this.v,2,t.minPosePresenceConfidence??.5),"outputSegmentationMasks"in t&&(this.outputSegmentationMasks=t.outputSegmentationMasks??!1),this.l(t)}D(t,e,n){const r="function"!=typeof e?e:{};return this.s="function"==typeof e?e:n,Kc(this),qa(this,t,r),Yc(this)}F(t,e,n,r){const i="function"!=typeof n?n:{};return this.s="function"==typeof n?n:r,Kc(this),Ja(this,t,i,e),Yc(this)}m(){var t=new es;Qi(t,"image_in"),Qi(t,"norm_rect"),ts(t,"normalized_landmarks"),ts(t,"world_landmarks"),ts(t,"segmentation_masks");const e=new Vi;Yn(e,xo,this.h);const n=new Yi;Wi(n,"mediapipe.tasks.vision.pose_landmarker.PoseLandmarkerGraph"),zi(n,"IMAGE:image_in"),zi(n,"NORM_RECT:norm_rect"),Ki(n,"NORM_LANDMARKS:normalized_landmarks"),Ki(n,"WORLD_LANDMARKS:world_landmarks"),n.o(e),Zi(t,n),Jo(this,t),this.g.attachProtoVectorListener("normalized_landmarks",((t,e)=>{this.landmarks=[];for(const e of t)t=gs(e),this.landmarks.push(Fo(t));qo(this,e)})),this.g.attachEmptyPacketListener("normalized_landmarks",(t=>{this.landmarks=[],qo(this,t)})),this.g.attachProtoVectorListener("world_landmarks",((t,e)=>{this.worldLandmarks=[];for(const e of t)t=ds(e),this.worldLandmarks.push(Io(t));qo(this,e)})),this.g.attachEmptyPacketListener("world_landmarks",(t=>{this.worldLandmarks=[],qo(this,t)})),this.outputSegmentationMasks&&(Ki(n,"SEGMENTATION_MASK:segmentation_masks"),Zo(this,"segmentation_masks"),this.g.da("segmentation_masks",((t,e)=>{this.segmentationMasks=t.map((t=>Za(this,t,!0,!this.s))),qo(this,e)})),this.g.attachEmptyPacketListener("segmentation_masks",(t=>{this.segmentationMasks=[],qo(this,t)}))),t=t.g(),this.setGraph(new Uint8Array(t),!0)}};$c.prototype.detectForVideo=$c.prototype.F,$c.prototype.detect=$c.prototype.D,$c.prototype.setOptions=$c.prototype.o,$c.createFromModelPath=function(t,e){return Ya($c,t,{baseOptions:{modelAssetPath:e}})},$c.createFromModelBuffer=function(t,e){return Ya($c,t,{baseOptions:{modelAssetBuffer:e}})},$c.createFromOptions=function(t,e){return Ya($c,t,e)},$c.POSE_CONNECTIONS=wc,exports.FaceDetector=tc,exports.FaceLandmarker=fc,exports.FaceStylizer=dc,exports.FilesetResolver=Do,exports.GestureRecognizer=_c,exports.HandLandmarker=Ec,exports.HolisticLandmarker=kc,exports.ImageClassifier=xc,exports.ImageEmbedder=Sc,exports.ImageSegmenter=Ic,exports.ImageSegmenterResult=Lc,exports.InteractiveSegmenter=Hc,exports.InteractiveSegmenterResult=Mc,exports.MPImage=Va,exports.MPMask=Ta,exports.ObjectDetector=Wc,exports.PoseLandmarker=$c,exports.VisionTaskRunner=Qa;\n//# sourceMappingURL=vision_bundle_cjs.js.map\n';
|
|
1109
1109
|
class CVSystem {
|
|
1110
1110
|
// MediaPipe Tasks Vision worker
|
|
@@ -1128,6 +1128,42 @@ class CVSystem {
|
|
|
1128
1128
|
};
|
|
1129
1129
|
// Processing state and performance tracking
|
|
1130
1130
|
processing = false;
|
|
1131
|
+
// Single-slot "latest pending" buffer. When a new frame arrives while
|
|
1132
|
+
// MediaPipe is still busy with the previous one, we keep the new bitmap here
|
|
1133
|
+
// (closing whatever was previously pending) and drain it from the
|
|
1134
|
+
// processFrame `finally` block via queueMicrotask. This guarantees that on
|
|
1135
|
+
// each MediaPipe completion we resume on the FRESHEST available frame
|
|
1136
|
+
// instead of whatever happens to land after `processing` flips back to
|
|
1137
|
+
// false — which used to leave us multi-frame stale at high resolution.
|
|
1138
|
+
//
|
|
1139
|
+
// Resource discipline (docs/14, rule 1 + rule 4):
|
|
1140
|
+
// - Bounded by construction: at most one entry, never a queue.
|
|
1141
|
+
// - Closed on every replace, in clearResults() (which covers
|
|
1142
|
+
// handleWorkerFailure and cleanup), and on synchronous error inside
|
|
1143
|
+
// the drain microtask. The pending.timestamp field is for diagnostics
|
|
1144
|
+
// only — the actual MediaPipe timestamp is re-derived inside
|
|
1145
|
+
// processFrame on the drain re-entry.
|
|
1146
|
+
pendingFrame = null;
|
|
1147
|
+
// Analysed-frame state — pairs the exact frame MediaPipe ran on with its
|
|
1148
|
+
// results so artists can do pixel-precise effects (face-mesh masks,
|
|
1149
|
+
// segmentation overlays). Surfaced via getAnalysedFrame() / getAnalysedFrameData().
|
|
1150
|
+
//
|
|
1151
|
+
// Lifecycle (docs/14, rule 4 + rule 6):
|
|
1152
|
+
// - analysedCanvas: lazy-allocated on first acceptAnalysedFrame call,
|
|
1153
|
+
// resized on dimension change, REUSED across results, RETAINED across
|
|
1154
|
+
// clearResults() (mirrors how MediaPipe models stay loaded across
|
|
1155
|
+
// reactivation), disposed only in cleanup().
|
|
1156
|
+
// - analysedFrameValid: separates "infrastructure exists" from "data is
|
|
1157
|
+
// valid". clearResults() flips this to false; the canvas is also
|
|
1158
|
+
// blanked via clearRect for defense in depth (so any internal poker at
|
|
1159
|
+
// the raw reference doesn't see stale post-disconnect imagery).
|
|
1160
|
+
// - analysedFrameData / Dirty: mirrors VideoSystem.frameDataDirty (line
|
|
1161
|
+
// 174-185 of VideoSystem.ts) — single getImageData per CV-result cycle.
|
|
1162
|
+
analysedCanvas = null;
|
|
1163
|
+
analysedCtx = null;
|
|
1164
|
+
analysedFrameValid = false;
|
|
1165
|
+
analysedFrameData = null;
|
|
1166
|
+
analysedFrameDataDirty = false;
|
|
1131
1167
|
cvFrameCounter = 0;
|
|
1132
1168
|
cvFrameRateMode = "full";
|
|
1133
1169
|
// Default: full scene rate
|
|
@@ -1149,6 +1185,19 @@ class CVSystem {
|
|
|
1149
1185
|
// requests under burst (replaces the prior anonymous-listener bridge that
|
|
1150
1186
|
// could resolve out of order).
|
|
1151
1187
|
nextRequestId = 1;
|
|
1188
|
+
// Set of postToCV request IDs whose one-shot listener is still alive. The
|
|
1189
|
+
// generic worker-message listener uses this to decide whether a bitmap-
|
|
1190
|
+
// bearing `result` message is "in flight" (one-shot will consume it) or
|
|
1191
|
+
// "orphaned" (one-shot already removed itself via the postToCV 5000ms
|
|
1192
|
+
// timeout — close the bitmap to prevent a GPU leak, docs/14 rule 1).
|
|
1193
|
+
//
|
|
1194
|
+
// Add: at the start of postToCV. Remove: in postToCV's cleanup() (which
|
|
1195
|
+
// runs on response, timeout, or error). The 500ms race-timeout in
|
|
1196
|
+
// processFrame does NOT remove the requestId — postToCV's listener is
|
|
1197
|
+
// still alive and will fire when cv-tasks responds; the late bitmap is
|
|
1198
|
+
// released by JS GC after msg.data goes out of scope (accepted tradeoff
|
|
1199
|
+
// documented in docs/14 Round 5).
|
|
1200
|
+
pendingRequestIds = /* @__PURE__ */ new Set();
|
|
1152
1201
|
constructor() {
|
|
1153
1202
|
this.debugLog("🔧 CVSystem initialized for MediaPipe Tasks Vision");
|
|
1154
1203
|
}
|
|
@@ -1204,6 +1253,14 @@ class CVSystem {
|
|
|
1204
1253
|
this.cvWorker.addEventListener("message", (evt) => {
|
|
1205
1254
|
const msg = evt.data;
|
|
1206
1255
|
this.debugLog(`📨 [CV Worker -> CVSystem] ${msg.type}`, msg.success ? msg.data : msg.error);
|
|
1256
|
+
const data = msg?.data;
|
|
1257
|
+
const reqId = msg?.requestId;
|
|
1258
|
+
if (msg?.type === "result" && data?.frame instanceof ImageBitmap && typeof reqId === "number" && !this.pendingRequestIds.has(reqId)) {
|
|
1259
|
+
try {
|
|
1260
|
+
data.frame.close();
|
|
1261
|
+
} catch {
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1207
1264
|
});
|
|
1208
1265
|
this.cvWorker.onerror = (err) => {
|
|
1209
1266
|
this.debugLog("❌ CV worker error event", err.message);
|
|
@@ -1241,6 +1298,7 @@ class CVSystem {
|
|
|
1241
1298
|
this.cvWorker.terminate();
|
|
1242
1299
|
this.cvWorker = null;
|
|
1243
1300
|
}
|
|
1301
|
+
this.pendingRequestIds.clear();
|
|
1244
1302
|
const featuresToRestore = new Set(this.activeFeatures);
|
|
1245
1303
|
this.activeFeatures.clear();
|
|
1246
1304
|
this.clearResults();
|
|
@@ -1284,12 +1342,14 @@ class CVSystem {
|
|
|
1284
1342
|
const requestId = this.nextRequestId++;
|
|
1285
1343
|
const worker = this.cvWorker;
|
|
1286
1344
|
let timer = null;
|
|
1345
|
+
this.pendingRequestIds.add(requestId);
|
|
1287
1346
|
const cleanup = () => {
|
|
1288
1347
|
if (timer !== null) {
|
|
1289
1348
|
clearTimeout(timer);
|
|
1290
1349
|
timer = null;
|
|
1291
1350
|
}
|
|
1292
1351
|
worker.removeEventListener("message", onMessage);
|
|
1352
|
+
this.pendingRequestIds.delete(requestId);
|
|
1293
1353
|
};
|
|
1294
1354
|
const onMessage = (ev) => {
|
|
1295
1355
|
const msg = ev.data;
|
|
@@ -1559,13 +1619,33 @@ class CVSystem {
|
|
|
1559
1619
|
}
|
|
1560
1620
|
}
|
|
1561
1621
|
/**
|
|
1562
|
-
* Process video frame with active CV features
|
|
1622
|
+
* Process video frame with active CV features.
|
|
1623
|
+
*
|
|
1624
|
+
* Frames arriving while MediaPipe is busy are NOT dropped: the latest one is
|
|
1625
|
+
* stashed in `pendingFrame` (replacing whatever was there before) and drained
|
|
1626
|
+
* from the `finally` block when the in-flight call completes. This keeps CV
|
|
1627
|
+
* results synced to the freshest frame available rather than whatever
|
|
1628
|
+
* happened to land after the previous round-trip resolved.
|
|
1563
1629
|
*/
|
|
1564
1630
|
async processFrame(bitmap) {
|
|
1565
|
-
if (this.
|
|
1631
|
+
if (this.activeFeatures.size === 0) {
|
|
1566
1632
|
bitmap.close();
|
|
1567
1633
|
return;
|
|
1568
1634
|
}
|
|
1635
|
+
if (this.processing) {
|
|
1636
|
+
if (this.pendingFrame) {
|
|
1637
|
+
try {
|
|
1638
|
+
this.pendingFrame.bitmap.close();
|
|
1639
|
+
} catch {
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
this.pendingFrame = {
|
|
1643
|
+
bitmap,
|
|
1644
|
+
timestamp: performance.now(),
|
|
1645
|
+
features: Array.from(this.activeFeatures)
|
|
1646
|
+
};
|
|
1647
|
+
return;
|
|
1648
|
+
}
|
|
1569
1649
|
this.cvFrameCounter++;
|
|
1570
1650
|
if (!this.shouldProcessFrame()) {
|
|
1571
1651
|
bitmap.close();
|
|
@@ -1588,6 +1668,10 @@ class CVSystem {
|
|
|
1588
1668
|
raceTimerId = setTimeout(() => reject(new Error("CV processing timeout")), 500);
|
|
1589
1669
|
});
|
|
1590
1670
|
const results = await Promise.race([processPromise, timeoutPromise]);
|
|
1671
|
+
const resultsAny = results;
|
|
1672
|
+
if (resultsAny.frame instanceof ImageBitmap) {
|
|
1673
|
+
this.acceptAnalysedFrame(resultsAny.frame);
|
|
1674
|
+
}
|
|
1591
1675
|
if ("faces" in results && (this.activeFeatures.has("faceDetection") || this.activeFeatures.has("faceMesh") || this.activeFeatures.has("emotionDetection"))) {
|
|
1592
1676
|
this.results.faces = results.faces;
|
|
1593
1677
|
this.debugLog(`📥 Received ${results.faces.length} face results`);
|
|
@@ -1614,8 +1698,126 @@ class CVSystem {
|
|
|
1614
1698
|
} finally {
|
|
1615
1699
|
if (raceTimerId !== null) clearTimeout(raceTimerId);
|
|
1616
1700
|
this.processing = false;
|
|
1701
|
+
if (this.pendingFrame && this.activeFeatures.size > 0) {
|
|
1702
|
+
queueMicrotask(() => this.drainPendingFrame());
|
|
1703
|
+
} else if (this.pendingFrame) {
|
|
1704
|
+
try {
|
|
1705
|
+
this.pendingFrame.bitmap.close();
|
|
1706
|
+
} catch {
|
|
1707
|
+
}
|
|
1708
|
+
this.pendingFrame = null;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
/**
|
|
1713
|
+
* Drain a pending frame after the in-flight processFrame has completed.
|
|
1714
|
+
*
|
|
1715
|
+
* Re-checks the feature set against `pending.features` because features may
|
|
1716
|
+
* have been disabled mid-flight. If the intersection is empty, the bitmap is
|
|
1717
|
+
* closed without re-entering processFrame.
|
|
1718
|
+
*
|
|
1719
|
+
* Resource discipline (docs/14, rule 1): the bitmap leaves this method
|
|
1720
|
+
* either via processFrame (which transfers it to cv-tasks or closes it on
|
|
1721
|
+
* early-return paths) or via .close() on the synchronous error / no-active-
|
|
1722
|
+
* features paths. No code path drops it.
|
|
1723
|
+
*/
|
|
1724
|
+
drainPendingFrame() {
|
|
1725
|
+
const pending = this.pendingFrame;
|
|
1726
|
+
this.pendingFrame = null;
|
|
1727
|
+
if (!pending) return;
|
|
1728
|
+
try {
|
|
1729
|
+
const stillWanted = pending.features.filter((f) => this.activeFeatures.has(f));
|
|
1730
|
+
if (stillWanted.length === 0) {
|
|
1731
|
+
pending.bitmap.close();
|
|
1732
|
+
return;
|
|
1733
|
+
}
|
|
1734
|
+
void this.processFrame(pending.bitmap);
|
|
1735
|
+
} catch (error) {
|
|
1736
|
+
try {
|
|
1737
|
+
pending.bitmap.close();
|
|
1738
|
+
} catch {
|
|
1739
|
+
}
|
|
1740
|
+
this.debugLog("⚠️ drainPendingFrame failed:", error);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
/**
|
|
1744
|
+
* Accept the bitmap that MediaPipe analysed and stage it as the new
|
|
1745
|
+
* `analysedFrame`. Lazy-allocates the scratch canvas on first call,
|
|
1746
|
+
* resizes on dimension change, draws the bitmap, then closes it (the
|
|
1747
|
+
* pixels are now in the canvas — keeping the bitmap alive would
|
|
1748
|
+
* double-cost GPU memory).
|
|
1749
|
+
*
|
|
1750
|
+
* Resource discipline (docs/14 rule 1): the bitmap is the sole obligation
|
|
1751
|
+
* passed in. Both the success path (drawImage then close in `finally`)
|
|
1752
|
+
* and the early-return paths (no `analysedCtx` after lazy-init failure)
|
|
1753
|
+
* close it. No drops.
|
|
1754
|
+
*
|
|
1755
|
+
* Called unconditionally on every successful CV inference, regardless of
|
|
1756
|
+
* which features are currently active — the contract is "this is the
|
|
1757
|
+
* frame MediaPipe last ran on". If features were disabled mid-flight and
|
|
1758
|
+
* the result fields aren't propagated to `this.results.*`, the artist
|
|
1759
|
+
* sees `[]`/`null` results paired with this frame, which is semantically
|
|
1760
|
+
* "no detection reported in this frame" — coherent.
|
|
1761
|
+
*/
|
|
1762
|
+
acceptAnalysedFrame(bitmap) {
|
|
1763
|
+
try {
|
|
1764
|
+
if (!this.analysedCanvas) {
|
|
1765
|
+
this.analysedCanvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
1766
|
+
this.analysedCtx = this.analysedCanvas.getContext("2d", { willReadFrequently: true });
|
|
1767
|
+
}
|
|
1768
|
+
if (!this.analysedCtx) {
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
if (this.analysedCanvas.width !== bitmap.width || this.analysedCanvas.height !== bitmap.height) {
|
|
1772
|
+
this.analysedCanvas.width = bitmap.width;
|
|
1773
|
+
this.analysedCanvas.height = bitmap.height;
|
|
1774
|
+
}
|
|
1775
|
+
this.analysedCtx.drawImage(bitmap, 0, 0);
|
|
1776
|
+
this.analysedFrameValid = true;
|
|
1777
|
+
this.analysedFrameDataDirty = true;
|
|
1778
|
+
} finally {
|
|
1779
|
+
try {
|
|
1780
|
+
bitmap.close();
|
|
1781
|
+
} catch {
|
|
1782
|
+
}
|
|
1617
1783
|
}
|
|
1618
1784
|
}
|
|
1785
|
+
/**
|
|
1786
|
+
* Public getter for the analysed-frame canvas. Returns the canvas only
|
|
1787
|
+
* when there's a valid CV result on it; returns null when CV hasn't
|
|
1788
|
+
* produced a result yet, when results have been cleared (disconnect /
|
|
1789
|
+
* worker failure), or when the canvas hasn't been allocated yet.
|
|
1790
|
+
*
|
|
1791
|
+
* The returned canvas is owned by CVSystem — the caller (artist scene
|
|
1792
|
+
* via `viji.video.cv.analysedFrame`, or renderer adapters) must treat it
|
|
1793
|
+
* as read-only: source for drawImage / texImage2D / p5.image only,
|
|
1794
|
+
* never a target.
|
|
1795
|
+
*/
|
|
1796
|
+
getAnalysedFrame() {
|
|
1797
|
+
return this.analysedFrameValid ? this.analysedCanvas : null;
|
|
1798
|
+
}
|
|
1799
|
+
/**
|
|
1800
|
+
* Public getter for the analysed frame's pixel data. Lazy + cached:
|
|
1801
|
+
* getImageData is invoked once per CV-result cycle (gated by
|
|
1802
|
+
* `analysedFrameDataDirty`), so multiple readers within a render share
|
|
1803
|
+
* a single allocation. Mirrors the `extractFrameDataIfNeeded` pattern
|
|
1804
|
+
* in VideoSystem.ts:174-185.
|
|
1805
|
+
*/
|
|
1806
|
+
getAnalysedFrameData() {
|
|
1807
|
+
if (!this.analysedFrameValid || !this.analysedCanvas || !this.analysedCtx) {
|
|
1808
|
+
return null;
|
|
1809
|
+
}
|
|
1810
|
+
if (this.analysedFrameDataDirty || !this.analysedFrameData) {
|
|
1811
|
+
this.analysedFrameData = this.analysedCtx.getImageData(
|
|
1812
|
+
0,
|
|
1813
|
+
0,
|
|
1814
|
+
this.analysedCanvas.width,
|
|
1815
|
+
this.analysedCanvas.height
|
|
1816
|
+
);
|
|
1817
|
+
this.analysedFrameDataDirty = false;
|
|
1818
|
+
}
|
|
1819
|
+
return this.analysedFrameData;
|
|
1820
|
+
}
|
|
1619
1821
|
/**
|
|
1620
1822
|
* Check if current frame should be processed based on CV frame rate mode
|
|
1621
1823
|
*/
|
|
@@ -1669,12 +1871,29 @@ class CVSystem {
|
|
|
1669
1871
|
* Called when the input source goes away (video disconnect, worker restart) so
|
|
1670
1872
|
* scenes do not see stale analysis data, while keeping WASM models loaded for
|
|
1671
1873
|
* fast reactivation.
|
|
1874
|
+
*
|
|
1875
|
+
* Also drains any pending bitmap so it doesn't leak across teardown — this
|
|
1876
|
+
* single point covers `handleWorkerFailure` (which clears the cache after
|
|
1877
|
+
* terminating the worker) and `cleanup` (full shutdown).
|
|
1672
1878
|
*/
|
|
1673
1879
|
clearResults() {
|
|
1674
1880
|
this.results.faces = [];
|
|
1675
1881
|
this.results.hands = [];
|
|
1676
1882
|
this.results.pose = null;
|
|
1677
1883
|
this.results.segmentation = null;
|
|
1884
|
+
if (this.pendingFrame) {
|
|
1885
|
+
try {
|
|
1886
|
+
this.pendingFrame.bitmap.close();
|
|
1887
|
+
} catch {
|
|
1888
|
+
}
|
|
1889
|
+
this.pendingFrame = null;
|
|
1890
|
+
}
|
|
1891
|
+
if (this.analysedFrameValid && this.analysedCtx && this.analysedCanvas) {
|
|
1892
|
+
this.analysedCtx.clearRect(0, 0, this.analysedCanvas.width, this.analysedCanvas.height);
|
|
1893
|
+
}
|
|
1894
|
+
this.analysedFrameValid = false;
|
|
1895
|
+
this.analysedFrameData = null;
|
|
1896
|
+
this.analysedFrameDataDirty = false;
|
|
1678
1897
|
}
|
|
1679
1898
|
/**
|
|
1680
1899
|
* Whether any CV feature is currently active. Used by callers to skip work
|
|
@@ -1826,6 +2045,9 @@ class CVSystem {
|
|
|
1826
2045
|
this.clearResults();
|
|
1827
2046
|
this.processing = false;
|
|
1828
2047
|
this.processingTimes = [];
|
|
2048
|
+
this.analysedCanvas = null;
|
|
2049
|
+
this.analysedCtx = null;
|
|
2050
|
+
this.pendingRequestIds.clear();
|
|
1829
2051
|
this.debugLog("✅ CVSystem cleanup complete");
|
|
1830
2052
|
}
|
|
1831
2053
|
}
|
|
@@ -1834,9 +2056,6 @@ class VideoSystem {
|
|
|
1834
2056
|
offscreenCanvas = null;
|
|
1835
2057
|
ctx = null;
|
|
1836
2058
|
gl = null;
|
|
1837
|
-
// CV processing helpers
|
|
1838
|
-
cvScratchCanvas = null;
|
|
1839
|
-
cvScratchContext = null;
|
|
1840
2059
|
// Debug logging control
|
|
1841
2060
|
debugMode = false;
|
|
1842
2061
|
// GPU-only mode flag (for shader compositor only - P5/Canvas need OffscreenCanvas)
|
|
@@ -1930,13 +2149,23 @@ class VideoSystem {
|
|
|
1930
2149
|
frameHeight: this.videoState.frameHeight,
|
|
1931
2150
|
frameRate: this.videoState.frameRate,
|
|
1932
2151
|
getFrameData: () => this.extractFrameDataIfNeeded(),
|
|
1933
|
-
// CV
|
|
1934
|
-
faces
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
//
|
|
1939
|
-
|
|
2152
|
+
// Unified CV surface: paired data outputs (analysedFrame +
|
|
2153
|
+
// faces/hands/pose/segmentation) alongside the verbs that activate
|
|
2154
|
+
// them. Built in one synchronous pass so `cvResults`, the analysed-
|
|
2155
|
+
// frame getters, and the control verbs all reflect the same CVSystem
|
|
2156
|
+
// state at the same instant. Per-host-frame Object.assign from
|
|
2157
|
+
// VijiWorkerRuntime (handleVideoFrameUpdate) locks the entire `cv`
|
|
2158
|
+
// sub-object atomically into `viji.video.cv` for the next render
|
|
2159
|
+
// tick.
|
|
2160
|
+
cv: {
|
|
2161
|
+
analysedFrame: this.cvSystem.getAnalysedFrame(),
|
|
2162
|
+
getAnalysedFrameData: () => this.cvSystem.getAnalysedFrameData(),
|
|
2163
|
+
faces: cvResults.faces,
|
|
2164
|
+
hands: cvResults.hands,
|
|
2165
|
+
pose: cvResults.pose,
|
|
2166
|
+
segmentation: cvResults.segmentation,
|
|
2167
|
+
...this.cvSystem.getControlInterface()
|
|
2168
|
+
}
|
|
1940
2169
|
};
|
|
1941
2170
|
}
|
|
1942
2171
|
/**
|
|
@@ -2000,7 +2229,22 @@ class VideoSystem {
|
|
|
2000
2229
|
}
|
|
2001
2230
|
}
|
|
2002
2231
|
/**
|
|
2003
|
-
*
|
|
2232
|
+
* Receive ImageBitmap frame and draw to the worker's OffscreenCanvas.
|
|
2233
|
+
*
|
|
2234
|
+
* After drawing, hand the SAME bitmap directly to CVSystem when CV features
|
|
2235
|
+
* are active — the bitmap is still valid (drawImage reads it, doesn't consume
|
|
2236
|
+
* it) and stays GPU-resident through the transfer to the cv-tasks worker.
|
|
2237
|
+
* This avoids the GPU→CPU readback (`getImageData`) and CPU→GPU re-upload
|
|
2238
|
+
* (`createImageBitmap(ImageData)`) that the previous CV path performed inside
|
|
2239
|
+
* `processCurrentFrame`. MediaPipe Tasks Vision accepts ImageBitmap inputs
|
|
2240
|
+
* directly — no canvas-side pixel access is required.
|
|
2241
|
+
*
|
|
2242
|
+
* Ownership:
|
|
2243
|
+
* - CV active → bitmap transferred onward into cvSystem.processFrame, which
|
|
2244
|
+
* either transfers it to cv-tasks (postToCV with [bitmap])
|
|
2245
|
+
* or closes it on every early-return path.
|
|
2246
|
+
* - CV inactive → bitmap closed locally after drawImage.
|
|
2247
|
+
* - Exception → bitmap closed in the catch block.
|
|
2004
2248
|
*/
|
|
2005
2249
|
handleFrameUpdate(data) {
|
|
2006
2250
|
if (!this.offscreenCanvas || !this.ctx) {
|
|
@@ -2020,21 +2264,30 @@ class VideoSystem {
|
|
|
2020
2264
|
this.ctx.drawImage(data.imageBitmap, 0, 0, this.offscreenCanvas.width, this.offscreenCanvas.height);
|
|
2021
2265
|
this.frameDataDirty = true;
|
|
2022
2266
|
this.processCurrentFrame(data.timestamp);
|
|
2023
|
-
|
|
2267
|
+
if (this.cvSystem.hasActiveFeatures()) {
|
|
2268
|
+
this.cvSystem.processFrame(data.imageBitmap);
|
|
2269
|
+
} else {
|
|
2270
|
+
data.imageBitmap.close();
|
|
2271
|
+
}
|
|
2024
2272
|
this.frameCount++;
|
|
2025
2273
|
} catch (error) {
|
|
2026
2274
|
console.error("🔴 Error processing video frame (worker-side):", error);
|
|
2275
|
+
try {
|
|
2276
|
+
data.imageBitmap.close();
|
|
2277
|
+
} catch {
|
|
2278
|
+
}
|
|
2027
2279
|
}
|
|
2028
2280
|
}
|
|
2029
2281
|
/**
|
|
2030
|
-
*
|
|
2282
|
+
* Update frame-rate accounting and emit the first-frame debug log.
|
|
2031
2283
|
*
|
|
2032
|
-
*
|
|
2033
|
-
*
|
|
2034
|
-
*
|
|
2035
|
-
*
|
|
2284
|
+
* CV input is dispatched directly from `handleFrameUpdate` / `handleDirectFrame`
|
|
2285
|
+
* (the same bitmap that was drawn to the canvas is forwarded to CVSystem),
|
|
2286
|
+
* so this method no longer touches CV. Scenes that need CPU pixel access read
|
|
2287
|
+
* via `viji.video.getFrameData()` which goes through `extractFrameDataIfNeeded`
|
|
2288
|
+
* — that path stays available.
|
|
2036
2289
|
*/
|
|
2037
|
-
|
|
2290
|
+
processCurrentFrame(timestamp) {
|
|
2038
2291
|
if (!this.offscreenCanvas || !this.ctx) {
|
|
2039
2292
|
return;
|
|
2040
2293
|
}
|
|
@@ -2046,30 +2299,6 @@ class VideoSystem {
|
|
|
2046
2299
|
this.debugLog("✅ Full GPU access available for custom effects and CV analysis");
|
|
2047
2300
|
this.hasLoggedFirstFrame = true;
|
|
2048
2301
|
}
|
|
2049
|
-
if (this.cvSystem.hasActiveFeatures()) {
|
|
2050
|
-
const frameData = this.extractFrameDataIfNeeded();
|
|
2051
|
-
if (frameData) {
|
|
2052
|
-
try {
|
|
2053
|
-
const bitmap = await createImageBitmap(frameData);
|
|
2054
|
-
this.cvSystem.processFrame(bitmap);
|
|
2055
|
-
} catch (bitmapError) {
|
|
2056
|
-
this.debugLog("⚠️ createImageBitmap failed – falling back to reusable CV canvas:", bitmapError);
|
|
2057
|
-
if (!this.cvScratchCanvas || !this.cvScratchContext || this.cvScratchCanvas.width !== frameData.width || this.cvScratchCanvas.height !== frameData.height) {
|
|
2058
|
-
this.cvScratchCanvas = new OffscreenCanvas(
|
|
2059
|
-
frameData.width,
|
|
2060
|
-
frameData.height
|
|
2061
|
-
);
|
|
2062
|
-
this.cvScratchContext = this.cvScratchCanvas.getContext("2d");
|
|
2063
|
-
if (!this.cvScratchContext) {
|
|
2064
|
-
throw new Error("Failed to get 2D context for CV fallback canvas");
|
|
2065
|
-
}
|
|
2066
|
-
}
|
|
2067
|
-
this.cvScratchContext.putImageData(frameData, 0, 0);
|
|
2068
|
-
const fallbackBitmap = this.cvScratchCanvas.transferToImageBitmap();
|
|
2069
|
-
this.cvSystem.processFrame(fallbackBitmap);
|
|
2070
|
-
}
|
|
2071
|
-
}
|
|
2072
|
-
}
|
|
2073
2302
|
this.lastFrameTime = timestamp;
|
|
2074
2303
|
} catch (error) {
|
|
2075
2304
|
console.error("Error processing video frame (worker-side):", error);
|
|
@@ -2133,8 +2362,6 @@ class VideoSystem {
|
|
|
2133
2362
|
this.videoState.frameRate = 0;
|
|
2134
2363
|
this.videoState.frameData = null;
|
|
2135
2364
|
this.frameDataDirty = false;
|
|
2136
|
-
this.cvScratchCanvas = null;
|
|
2137
|
-
this.cvScratchContext = null;
|
|
2138
2365
|
this.cvSystem.clearResults();
|
|
2139
2366
|
this.hasLoggedFirstFrame = false;
|
|
2140
2367
|
this.frameCount = 0;
|
|
@@ -2521,6 +2748,15 @@ class P5WorkerAdapter {
|
|
|
2521
2748
|
height: bitmap.height
|
|
2522
2749
|
};
|
|
2523
2750
|
}
|
|
2751
|
+
if (vijiAPI.video?.cv?.analysedFrame instanceof OffscreenCanvas) {
|
|
2752
|
+
const canvas = vijiAPI.video.cv.analysedFrame;
|
|
2753
|
+
vijiAPI.video.cv.analysedFrame = {
|
|
2754
|
+
canvas,
|
|
2755
|
+
elt: canvas,
|
|
2756
|
+
width: canvas.width,
|
|
2757
|
+
height: canvas.height
|
|
2758
|
+
};
|
|
2759
|
+
}
|
|
2524
2760
|
if (Array.isArray(vijiAPI.videoStreams)) {
|
|
2525
2761
|
for (const stream of vijiAPI.videoStreams) {
|
|
2526
2762
|
if (stream?.currentFrame instanceof OffscreenCanvas) {
|
|
@@ -2893,6 +3129,16 @@ class ShaderWorkerAdapter {
|
|
|
2893
3129
|
audioFFTTexture = null;
|
|
2894
3130
|
audioWaveformTexture = null;
|
|
2895
3131
|
videoTexture = null;
|
|
3132
|
+
// Analysed-frame texture: bound to u_videoAnalysed; uploaded from
|
|
3133
|
+
// viji.video.cv.analysedFrame (the OffscreenCanvas owned by CVSystem). Allocated
|
|
3134
|
+
// lazily on first non-null frame; never closed by this adapter (CVSystem
|
|
3135
|
+
// owns the underlying canvas).
|
|
3136
|
+
analysedFrameTexture = null;
|
|
3137
|
+
// 1×1 black fallback bound to u_videoAnalysed before the first CV result
|
|
3138
|
+
// arrives. u_videoAnalysedAvailable is set to false when this is bound, so
|
|
3139
|
+
// shaders can branch — but if a shader reads u_videoAnalysed unconditionally
|
|
3140
|
+
// it gets safe-zero pixels rather than sampling uninitialized memory.
|
|
3141
|
+
analysedFrameFallbackTexture = null;
|
|
2896
3142
|
segmentationTexture = null;
|
|
2897
3143
|
keyboardTexture = null;
|
|
2898
3144
|
// Multi-stream textures
|
|
@@ -3186,6 +3432,8 @@ uniform sampler2D u_audioWaveform; // Time-domain waveform (fftSize samples, -1
|
|
|
3186
3432
|
uniform sampler2D u_video; // Current video frame as texture
|
|
3187
3433
|
uniform vec2 u_videoResolution; // Video frame width and height in pixels
|
|
3188
3434
|
uniform float u_videoFrameRate; // Video frame rate in frames per second
|
|
3435
|
+
uniform sampler2D u_videoAnalysed; // The exact frame MediaPipe analysed; pair with u_face*/u_hand*/u_pose* uniforms for pixel-precise CV-driven effects (face mesh masks, segmentation overlays). Shares u_videoResolution.
|
|
3436
|
+
uniform bool u_videoAnalysedAvailable; // True after the first CV result lands; before that, u_videoAnalysed samples a 1x1 black fallback. Use to gate effects that require valid analysed pixels.
|
|
3189
3437
|
|
|
3190
3438
|
// Multi-Stream Compositor Support (using individual uniforms due to WebGL 1.0 limitations)
|
|
3191
3439
|
uniform int u_videoStreamCount; // Number of available compositor input streams (0-8)
|
|
@@ -3562,6 +3810,7 @@ ${error}`);
|
|
|
3562
3810
|
this.textureUnits.set("u_audioFFT", this.nextTextureUnit++);
|
|
3563
3811
|
this.textureUnits.set("u_audioWaveform", this.nextTextureUnit++);
|
|
3564
3812
|
this.textureUnits.set("u_video", this.nextTextureUnit++);
|
|
3813
|
+
this.textureUnits.set("u_videoAnalysed", this.nextTextureUnit++);
|
|
3565
3814
|
this.textureUnits.set("u_segmentationMask", this.nextTextureUnit++);
|
|
3566
3815
|
this.textureUnits.set("u_keyboard", this.nextTextureUnit++);
|
|
3567
3816
|
for (let i = 0; i < ShaderWorkerAdapter.MAX_VIDEO_STREAMS; i++) {
|
|
@@ -3739,6 +3988,13 @@ ${error}`);
|
|
|
3739
3988
|
this.setUniform("u_videoResolution", "vec2", [0, 0]);
|
|
3740
3989
|
this.setUniform("u_videoFrameRate", "float", 0);
|
|
3741
3990
|
}
|
|
3991
|
+
if (video.cv?.analysedFrame instanceof OffscreenCanvas) {
|
|
3992
|
+
this.updateAnalysedFrameTexture(video.cv.analysedFrame);
|
|
3993
|
+
this.setUniform("u_videoAnalysedAvailable", "bool", true);
|
|
3994
|
+
} else {
|
|
3995
|
+
this.bindAnalysedFrameFallback();
|
|
3996
|
+
this.setUniform("u_videoAnalysedAvailable", "bool", false);
|
|
3997
|
+
}
|
|
3742
3998
|
const videoStreams = viji.videoStreams || [];
|
|
3743
3999
|
const videoStreamCount = Math.min(videoStreams.length, ShaderWorkerAdapter.MAX_VIDEO_STREAMS);
|
|
3744
4000
|
this.setUniform("u_videoStreamCount", "int", videoStreamCount);
|
|
@@ -3805,7 +4061,7 @@ ${error}`);
|
|
|
3805
4061
|
this.setUniform(`${prefix}Flatness`, "float", 0);
|
|
3806
4062
|
}
|
|
3807
4063
|
}
|
|
3808
|
-
const faces = video.faces || [];
|
|
4064
|
+
const faces = video.cv?.faces || [];
|
|
3809
4065
|
this.setUniform("u_faceCount", "int", faces.length);
|
|
3810
4066
|
if (faces.length > 0) {
|
|
3811
4067
|
const face = faces[0];
|
|
@@ -3888,7 +4144,7 @@ ${error}`);
|
|
|
3888
4144
|
this.setUniform("u_face0Disgusted", "float", 0);
|
|
3889
4145
|
this.setUniform("u_face0Fearful", "float", 0);
|
|
3890
4146
|
}
|
|
3891
|
-
const hands = video.hands || [];
|
|
4147
|
+
const hands = video.cv?.hands || [];
|
|
3892
4148
|
this.setUniform("u_handCount", "int", hands.length);
|
|
3893
4149
|
const leftHand = hands.find((h) => h.handedness === "left");
|
|
3894
4150
|
const rightHand = hands.find((h) => h.handedness === "right");
|
|
@@ -3944,7 +4200,7 @@ ${error}`);
|
|
|
3944
4200
|
this.setUniform("u_rightHandPointing", "float", 0);
|
|
3945
4201
|
this.setUniform("u_rightHandILoveYou", "float", 0);
|
|
3946
4202
|
}
|
|
3947
|
-
const pose = video.pose;
|
|
4203
|
+
const pose = video.cv?.pose ?? null;
|
|
3948
4204
|
this.setUniform("u_poseDetected", "bool", pose !== null);
|
|
3949
4205
|
if (pose && pose.landmarks) {
|
|
3950
4206
|
const lm = pose.landmarks;
|
|
@@ -3978,7 +4234,7 @@ ${error}`);
|
|
|
3978
4234
|
this.setUniform("u_leftAnklePosition", "vec2", [0, 0]);
|
|
3979
4235
|
this.setUniform("u_rightAnklePosition", "vec2", [0, 0]);
|
|
3980
4236
|
}
|
|
3981
|
-
const segmentation = video.segmentation;
|
|
4237
|
+
const segmentation = video.cv?.segmentation ?? null;
|
|
3982
4238
|
if (segmentation) {
|
|
3983
4239
|
this.updateSegmentationTexture(segmentation.mask, segmentation.width, segmentation.height);
|
|
3984
4240
|
this.setUniform("u_segmentationRes", "vec2", [segmentation.width, segmentation.height]);
|
|
@@ -4330,6 +4586,71 @@ ${error}`);
|
|
|
4330
4586
|
videoFrame.close();
|
|
4331
4587
|
}
|
|
4332
4588
|
}
|
|
4589
|
+
/**
|
|
4590
|
+
* Upload viji.video.cv.analysedFrame as the u_videoAnalysed texture. Mirrors
|
|
4591
|
+
* updateVideoTexture (same Y-flip and filter settings — same camera
|
|
4592
|
+
* source, same coordinate convention) but does NOT close the source: the
|
|
4593
|
+
* analysed canvas is owned by CVSystem and reused across frames.
|
|
4594
|
+
*
|
|
4595
|
+
* Type is OffscreenCanvas only (never ImageBitmap) — CVSystem materialises
|
|
4596
|
+
* the analysed frame onto a scratch canvas before exposing it.
|
|
4597
|
+
*/
|
|
4598
|
+
updateAnalysedFrameTexture(analysedFrame) {
|
|
4599
|
+
const gl = this.gl;
|
|
4600
|
+
const unit = this.textureUnits.get("u_videoAnalysed");
|
|
4601
|
+
if (!this.analysedFrameTexture) {
|
|
4602
|
+
this.analysedFrameTexture = gl.createTexture();
|
|
4603
|
+
}
|
|
4604
|
+
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
4605
|
+
gl.bindTexture(gl.TEXTURE_2D, this.analysedFrameTexture);
|
|
4606
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
4607
|
+
gl.texImage2D(
|
|
4608
|
+
gl.TEXTURE_2D,
|
|
4609
|
+
0,
|
|
4610
|
+
gl.RGBA,
|
|
4611
|
+
gl.RGBA,
|
|
4612
|
+
gl.UNSIGNED_BYTE,
|
|
4613
|
+
analysedFrame
|
|
4614
|
+
);
|
|
4615
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
4616
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
4617
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
4618
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
4619
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
4620
|
+
const location = this.uniformLocations.get("u_videoAnalysed");
|
|
4621
|
+
if (location) {
|
|
4622
|
+
gl.uniform1i(location, unit);
|
|
4623
|
+
}
|
|
4624
|
+
}
|
|
4625
|
+
/**
|
|
4626
|
+
* Bind a 1×1 black fallback to u_videoAnalysed when analysedFrame is null
|
|
4627
|
+
* (CV not enabled, or first result hasn't landed yet). Pairs with
|
|
4628
|
+
* u_videoAnalysedAvailable=false so shaders can branch; the fallback is
|
|
4629
|
+
* just safety so an unconditional sample doesn't read uninitialized GPU
|
|
4630
|
+
* memory.
|
|
4631
|
+
*/
|
|
4632
|
+
bindAnalysedFrameFallback() {
|
|
4633
|
+
const gl = this.gl;
|
|
4634
|
+
const unit = this.textureUnits.get("u_videoAnalysed");
|
|
4635
|
+
if (!this.analysedFrameFallbackTexture) {
|
|
4636
|
+
this.analysedFrameFallbackTexture = gl.createTexture();
|
|
4637
|
+
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
4638
|
+
gl.bindTexture(gl.TEXTURE_2D, this.analysedFrameFallbackTexture);
|
|
4639
|
+
const blackPixel = new Uint8Array([0, 0, 0, 255]);
|
|
4640
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, blackPixel);
|
|
4641
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
4642
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
4643
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
4644
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
4645
|
+
} else {
|
|
4646
|
+
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
4647
|
+
gl.bindTexture(gl.TEXTURE_2D, this.analysedFrameFallbackTexture);
|
|
4648
|
+
}
|
|
4649
|
+
const location = this.uniformLocations.get("u_videoAnalysed");
|
|
4650
|
+
if (location) {
|
|
4651
|
+
gl.uniform1i(location, unit);
|
|
4652
|
+
}
|
|
4653
|
+
}
|
|
4333
4654
|
/**
|
|
4334
4655
|
* Update compositor video stream texture at specified index
|
|
4335
4656
|
* Supports both OffscreenCanvas and ImageBitmap for zero-copy pipeline
|
|
@@ -4538,6 +4859,8 @@ ${error}`);
|
|
|
4538
4859
|
if (this.audioFFTTexture) gl.deleteTexture(this.audioFFTTexture);
|
|
4539
4860
|
if (this.audioWaveformTexture) gl.deleteTexture(this.audioWaveformTexture);
|
|
4540
4861
|
if (this.videoTexture) gl.deleteTexture(this.videoTexture);
|
|
4862
|
+
if (this.analysedFrameTexture) gl.deleteTexture(this.analysedFrameTexture);
|
|
4863
|
+
if (this.analysedFrameFallbackTexture) gl.deleteTexture(this.analysedFrameFallbackTexture);
|
|
4541
4864
|
if (this.segmentationTexture) gl.deleteTexture(this.segmentationTexture);
|
|
4542
4865
|
for (const texture of this.videoStreamTextures) {
|
|
4543
4866
|
if (texture) gl.deleteTexture(texture);
|
|
@@ -4967,6 +5290,16 @@ class VijiWorkerRuntime {
|
|
|
4967
5290
|
rendererType = "native";
|
|
4968
5291
|
_isHeadless = false;
|
|
4969
5292
|
_displayScale = 1;
|
|
5293
|
+
/**
|
|
5294
|
+
* Worker-side end of the direct host↔worker MessageChannel. Installed by
|
|
5295
|
+
* `handleInit` BEFORE `init-response` is posted, so by the time the host
|
|
5296
|
+
* sees `viji-ready` and switches to port mode the worker is already
|
|
5297
|
+
* listening. All outbound messages from the runtime's `postMessage`
|
|
5298
|
+
* helper prefer this port; pre-init early-error paths in
|
|
5299
|
+
* `viji.worker.ts` continue to use `self.postMessage` (the iframe relay
|
|
5300
|
+
* always picks them up).
|
|
5301
|
+
*/
|
|
5302
|
+
controlPort = null;
|
|
4970
5303
|
// Pending capture requests (queue to handle multiple simultaneous requests)
|
|
4971
5304
|
pendingCaptures = [];
|
|
4972
5305
|
/**
|
|
@@ -5070,7 +5403,11 @@ class VijiWorkerRuntime {
|
|
|
5070
5403
|
anySmoothed: 0,
|
|
5071
5404
|
triggers: { any: false, kick: false, snare: false, hat: false },
|
|
5072
5405
|
events: [],
|
|
5073
|
-
bpm:
|
|
5406
|
+
// `bpm: 0` is the documented "no signal" sentinel — set when no audio
|
|
5407
|
+
// is connected. Non-zero values flow only from the host's actual
|
|
5408
|
+
// detection pipeline. Artist scenes that need a fallback default
|
|
5409
|
+
// should write `audio.beat.bpm || 120` (or whatever default fits).
|
|
5410
|
+
bpm: 0,
|
|
5074
5411
|
confidence: 0,
|
|
5075
5412
|
isLocked: false
|
|
5076
5413
|
},
|
|
@@ -5086,11 +5423,19 @@ class VijiWorkerRuntime {
|
|
|
5086
5423
|
frameHeight: 0,
|
|
5087
5424
|
frameRate: 0,
|
|
5088
5425
|
getFrameData: () => null,
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5426
|
+
// Unified CV surface: data + verbs together. Replaced wholesale by
|
|
5427
|
+
// Object.assign with VideoSystem.getVideoAPI() once a stream
|
|
5428
|
+
// connects. Defaults below match the empty/no-op contract for a
|
|
5429
|
+
// stream with no CV running yet.
|
|
5093
5430
|
cv: {
|
|
5431
|
+
// Data
|
|
5432
|
+
analysedFrame: null,
|
|
5433
|
+
getAnalysedFrameData: () => null,
|
|
5434
|
+
faces: [],
|
|
5435
|
+
hands: [],
|
|
5436
|
+
pose: null,
|
|
5437
|
+
segmentation: null,
|
|
5438
|
+
// Verbs
|
|
5094
5439
|
enableFaceDetection: async () => {
|
|
5095
5440
|
},
|
|
5096
5441
|
disableFaceDetection: async () => {
|
|
@@ -5358,98 +5703,108 @@ class VijiWorkerRuntime {
|
|
|
5358
5703
|
}
|
|
5359
5704
|
setupMessageHandling() {
|
|
5360
5705
|
self.onmessage = (event) => {
|
|
5361
|
-
|
|
5362
|
-
switch (message.type) {
|
|
5363
|
-
case "init":
|
|
5364
|
-
this.handleInit(message).catch((e) => console.error("[Viji] handleInit failed:", e));
|
|
5365
|
-
break;
|
|
5366
|
-
case "frame-rate-update":
|
|
5367
|
-
this.handleFrameRateUpdate(message);
|
|
5368
|
-
break;
|
|
5369
|
-
case "refresh-rate-update":
|
|
5370
|
-
this.handleRefreshRateUpdate(message);
|
|
5371
|
-
break;
|
|
5372
|
-
case "cv-frame-rate-update":
|
|
5373
|
-
this.handleCVFrameRateUpdate(message);
|
|
5374
|
-
break;
|
|
5375
|
-
case "resolution-update":
|
|
5376
|
-
this.handleResolutionUpdate(message);
|
|
5377
|
-
break;
|
|
5378
|
-
case "set-scene-code":
|
|
5379
|
-
this.handleSetSceneCode(message);
|
|
5380
|
-
break;
|
|
5381
|
-
case "debug-mode":
|
|
5382
|
-
this.setDebugMode(message.data.enabled);
|
|
5383
|
-
break;
|
|
5384
|
-
case "parameter-update":
|
|
5385
|
-
this.handleParameterUpdate(message);
|
|
5386
|
-
break;
|
|
5387
|
-
case "parameter-batch-update":
|
|
5388
|
-
this.handleParameterBatchUpdate(message);
|
|
5389
|
-
break;
|
|
5390
|
-
case "stream-update":
|
|
5391
|
-
this.handleStreamUpdate(message);
|
|
5392
|
-
break;
|
|
5393
|
-
case "audio-analysis-update":
|
|
5394
|
-
this.handleAudioAnalysisUpdate(message);
|
|
5395
|
-
break;
|
|
5396
|
-
case "audio-stream-setup":
|
|
5397
|
-
this.handleAudioStreamSetup(message);
|
|
5398
|
-
break;
|
|
5399
|
-
case "video-canvas-setup":
|
|
5400
|
-
this.handleVideoCanvasSetup(message);
|
|
5401
|
-
break;
|
|
5402
|
-
case "video-frame-update":
|
|
5403
|
-
this.handleVideoFrameUpdate(message);
|
|
5404
|
-
break;
|
|
5405
|
-
case "video-config-update":
|
|
5406
|
-
this.handleVideoConfigUpdate(message);
|
|
5407
|
-
break;
|
|
5408
|
-
case "video-streams-prepare":
|
|
5409
|
-
this.handleVideoStreamsPrepare(message);
|
|
5410
|
-
break;
|
|
5411
|
-
case "video-frame-direct":
|
|
5412
|
-
this.handleVideoFrameDirect(message);
|
|
5413
|
-
break;
|
|
5414
|
-
case "enable-auto-capture":
|
|
5415
|
-
this.autoCaptureEnabled = message.data.enabled;
|
|
5416
|
-
if (message.data.flipY !== void 0) {
|
|
5417
|
-
this.autoCaptureFormat.flipY = message.data.flipY;
|
|
5418
|
-
this.debugLog(`[AutoCapture] ${message.data.enabled ? "ENABLED" : "DISABLED"} with flipY=${message.data.flipY}`);
|
|
5419
|
-
} else {
|
|
5420
|
-
this.debugLog(`[AutoCapture] ${message.data.enabled ? "ENABLED" : "DISABLED"}`);
|
|
5421
|
-
}
|
|
5422
|
-
break;
|
|
5423
|
-
case "mouse-update":
|
|
5424
|
-
this.handleMouseUpdate(message);
|
|
5425
|
-
break;
|
|
5426
|
-
case "keyboard-update":
|
|
5427
|
-
this.handleKeyboardUpdate(message);
|
|
5428
|
-
break;
|
|
5429
|
-
case "touch-update":
|
|
5430
|
-
this.handleTouchUpdate(message);
|
|
5431
|
-
break;
|
|
5432
|
-
case "interaction-enabled":
|
|
5433
|
-
this.handleInteractionEnabled(message);
|
|
5434
|
-
break;
|
|
5435
|
-
case "device-state-update":
|
|
5436
|
-
this.handleDeviceStateUpdate(message);
|
|
5437
|
-
break;
|
|
5438
|
-
case "performance-update":
|
|
5439
|
-
this.handlePerformanceUpdate(message);
|
|
5440
|
-
break;
|
|
5441
|
-
case "capture-frame":
|
|
5442
|
-
this.handleCaptureFrame(message);
|
|
5443
|
-
break;
|
|
5444
|
-
case "sc-update":
|
|
5445
|
-
update(message.data.t);
|
|
5446
|
-
break;
|
|
5447
|
-
case "rh-update":
|
|
5448
|
-
setRenderHint(message.data.h);
|
|
5449
|
-
break;
|
|
5450
|
-
}
|
|
5706
|
+
this.dispatchMessage(event.data);
|
|
5451
5707
|
};
|
|
5452
5708
|
}
|
|
5709
|
+
/**
|
|
5710
|
+
* Single dispatch helper for all incoming host-to-worker messages, shared
|
|
5711
|
+
* between the `self.onmessage` path (bootstrap window + early errors) and
|
|
5712
|
+
* the `controlPort.onmessage` path (steady state, post-`viji-ready`).
|
|
5713
|
+
*
|
|
5714
|
+
* Re-entrancy is fine: the switch is synchronous and only mutates `this.*`.
|
|
5715
|
+
* Ordering within either source is preserved by the receive queue.
|
|
5716
|
+
*/
|
|
5717
|
+
dispatchMessage(message) {
|
|
5718
|
+
switch (message.type) {
|
|
5719
|
+
case "init":
|
|
5720
|
+
this.handleInit(message).catch((e) => console.error("[Viji] handleInit failed:", e));
|
|
5721
|
+
break;
|
|
5722
|
+
case "frame-rate-update":
|
|
5723
|
+
this.handleFrameRateUpdate(message);
|
|
5724
|
+
break;
|
|
5725
|
+
case "refresh-rate-update":
|
|
5726
|
+
this.handleRefreshRateUpdate(message);
|
|
5727
|
+
break;
|
|
5728
|
+
case "cv-frame-rate-update":
|
|
5729
|
+
this.handleCVFrameRateUpdate(message);
|
|
5730
|
+
break;
|
|
5731
|
+
case "resolution-update":
|
|
5732
|
+
this.handleResolutionUpdate(message);
|
|
5733
|
+
break;
|
|
5734
|
+
case "set-scene-code":
|
|
5735
|
+
this.handleSetSceneCode(message);
|
|
5736
|
+
break;
|
|
5737
|
+
case "debug-mode":
|
|
5738
|
+
this.setDebugMode(message.data.enabled);
|
|
5739
|
+
break;
|
|
5740
|
+
case "parameter-update":
|
|
5741
|
+
this.handleParameterUpdate(message);
|
|
5742
|
+
break;
|
|
5743
|
+
case "parameter-batch-update":
|
|
5744
|
+
this.handleParameterBatchUpdate(message);
|
|
5745
|
+
break;
|
|
5746
|
+
case "stream-update":
|
|
5747
|
+
this.handleStreamUpdate(message);
|
|
5748
|
+
break;
|
|
5749
|
+
case "audio-analysis-update":
|
|
5750
|
+
this.handleAudioAnalysisUpdate(message);
|
|
5751
|
+
break;
|
|
5752
|
+
case "audio-stream-setup":
|
|
5753
|
+
this.handleAudioStreamSetup(message);
|
|
5754
|
+
break;
|
|
5755
|
+
case "video-canvas-setup":
|
|
5756
|
+
this.handleVideoCanvasSetup(message);
|
|
5757
|
+
break;
|
|
5758
|
+
case "video-frame-update":
|
|
5759
|
+
this.handleVideoFrameUpdate(message);
|
|
5760
|
+
break;
|
|
5761
|
+
case "video-config-update":
|
|
5762
|
+
this.handleVideoConfigUpdate(message);
|
|
5763
|
+
break;
|
|
5764
|
+
case "video-streams-prepare":
|
|
5765
|
+
this.handleVideoStreamsPrepare(message);
|
|
5766
|
+
break;
|
|
5767
|
+
case "video-frame-direct":
|
|
5768
|
+
this.handleVideoFrameDirect(message);
|
|
5769
|
+
break;
|
|
5770
|
+
case "enable-auto-capture":
|
|
5771
|
+
this.autoCaptureEnabled = message.data.enabled;
|
|
5772
|
+
if (message.data.flipY !== void 0) {
|
|
5773
|
+
this.autoCaptureFormat.flipY = message.data.flipY;
|
|
5774
|
+
this.debugLog(`[AutoCapture] ${message.data.enabled ? "ENABLED" : "DISABLED"} with flipY=${message.data.flipY}`);
|
|
5775
|
+
} else {
|
|
5776
|
+
this.debugLog(`[AutoCapture] ${message.data.enabled ? "ENABLED" : "DISABLED"}`);
|
|
5777
|
+
}
|
|
5778
|
+
break;
|
|
5779
|
+
case "mouse-update":
|
|
5780
|
+
this.handleMouseUpdate(message);
|
|
5781
|
+
break;
|
|
5782
|
+
case "keyboard-update":
|
|
5783
|
+
this.handleKeyboardUpdate(message);
|
|
5784
|
+
break;
|
|
5785
|
+
case "touch-update":
|
|
5786
|
+
this.handleTouchUpdate(message);
|
|
5787
|
+
break;
|
|
5788
|
+
case "interaction-enabled":
|
|
5789
|
+
this.handleInteractionEnabled(message);
|
|
5790
|
+
break;
|
|
5791
|
+
case "device-state-update":
|
|
5792
|
+
this.handleDeviceStateUpdate(message);
|
|
5793
|
+
break;
|
|
5794
|
+
case "performance-update":
|
|
5795
|
+
this.handlePerformanceUpdate(message);
|
|
5796
|
+
break;
|
|
5797
|
+
case "capture-frame":
|
|
5798
|
+
this.handleCaptureFrame(message);
|
|
5799
|
+
break;
|
|
5800
|
+
case "sc-update":
|
|
5801
|
+
update(message.data.t);
|
|
5802
|
+
break;
|
|
5803
|
+
case "rh-update":
|
|
5804
|
+
setRenderHint(message.data.h);
|
|
5805
|
+
break;
|
|
5806
|
+
}
|
|
5807
|
+
}
|
|
5453
5808
|
async handleInit(message) {
|
|
5454
5809
|
try {
|
|
5455
5810
|
this.canvas = message.data.canvas;
|
|
@@ -5484,9 +5839,18 @@ class VijiWorkerRuntime {
|
|
|
5484
5839
|
nosimdBinary: URL.createObjectURL(new Blob([f.nosimdBinary], { type: "application/wasm" }))
|
|
5485
5840
|
};
|
|
5486
5841
|
}
|
|
5842
|
+
if (message.data.controlPort) {
|
|
5843
|
+
this.controlPort = message.data.controlPort;
|
|
5844
|
+
this.controlPort.onmessage = (evt) => {
|
|
5845
|
+
this.dispatchMessage(evt.data);
|
|
5846
|
+
};
|
|
5847
|
+
}
|
|
5487
5848
|
this.startRenderLoop();
|
|
5488
|
-
|
|
5489
|
-
|
|
5849
|
+
self.postMessage({
|
|
5850
|
+
type: "init-response",
|
|
5851
|
+
id: message.id,
|
|
5852
|
+
timestamp: Date.now(),
|
|
5853
|
+
data: { id: message.id }
|
|
5490
5854
|
});
|
|
5491
5855
|
} catch (error) {
|
|
5492
5856
|
this.postMessage("error", {
|
|
@@ -5740,7 +6104,7 @@ class VijiWorkerRuntime {
|
|
|
5740
6104
|
audio.beat.triggers.hat = false;
|
|
5741
6105
|
audio.beat.triggers.any = false;
|
|
5742
6106
|
audio.beat.events.length = 0;
|
|
5743
|
-
audio.beat.bpm =
|
|
6107
|
+
audio.beat.bpm = 0;
|
|
5744
6108
|
audio.beat.confidence = 0;
|
|
5745
6109
|
audio.beat.isLocked = false;
|
|
5746
6110
|
audio.spectral.brightness = 0;
|
|
@@ -5902,12 +6266,7 @@ class VijiWorkerRuntime {
|
|
|
5902
6266
|
const format = message.data.format || "blob";
|
|
5903
6267
|
if (format === "bitmap") {
|
|
5904
6268
|
const bitmap = this.canvas.transferToImageBitmap();
|
|
5905
|
-
|
|
5906
|
-
type: "capture-frame-result",
|
|
5907
|
-
id: message.id,
|
|
5908
|
-
timestamp: Date.now(),
|
|
5909
|
-
data: { bitmap }
|
|
5910
|
-
}, [bitmap]);
|
|
6269
|
+
this.postMessage("capture-frame-result", { id: message.id, bitmap }, [bitmap]);
|
|
5911
6270
|
return;
|
|
5912
6271
|
}
|
|
5913
6272
|
const mimeType = message.data.type || "image/jpeg";
|
|
@@ -5966,12 +6325,7 @@ class VijiWorkerRuntime {
|
|
|
5966
6325
|
if (!tctx) throw new Error("Failed to get 2D context");
|
|
5967
6326
|
tctx.drawImage(sourceCanvas, sx, sy, sWidth, sHeight, 0, 0, targetWidth, targetHeight);
|
|
5968
6327
|
const blob = await temp.convertToBlob({ type: mimeType });
|
|
5969
|
-
|
|
5970
|
-
type: "capture-frame-result",
|
|
5971
|
-
id: message.id,
|
|
5972
|
-
timestamp: Date.now(),
|
|
5973
|
-
data: { blob }
|
|
5974
|
-
});
|
|
6328
|
+
this.postMessage("capture-frame-result", { id: message.id, blob });
|
|
5975
6329
|
} catch (error) {
|
|
5976
6330
|
this.postMessage("error", {
|
|
5977
6331
|
id: message.id,
|
|
@@ -6046,11 +6400,11 @@ class VijiWorkerRuntime {
|
|
|
6046
6400
|
if (ctx) {
|
|
6047
6401
|
const options = this.autoCaptureFormat.flipY ? { imageOrientation: "flipY" } : {};
|
|
6048
6402
|
createImageBitmap(this.canvas, options).then((bitmap) => {
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
timestamp:
|
|
6052
|
-
|
|
6053
|
-
|
|
6403
|
+
this.postMessage(
|
|
6404
|
+
"auto-capture-result",
|
|
6405
|
+
{ bitmap, timestamp: performance.now() },
|
|
6406
|
+
[bitmap]
|
|
6407
|
+
);
|
|
6054
6408
|
}).catch((err) => {
|
|
6055
6409
|
console.warn("[AutoCapture] ImageBitmap creation failed:", err);
|
|
6056
6410
|
});
|
|
@@ -6073,13 +6427,28 @@ class VijiWorkerRuntime {
|
|
|
6073
6427
|
this.resetAudioFrameEvents();
|
|
6074
6428
|
requestAnimationFrame(() => this.renderFrame());
|
|
6075
6429
|
}
|
|
6076
|
-
|
|
6077
|
-
|
|
6430
|
+
/**
|
|
6431
|
+
* Outbound message helper. Prefers the direct host↔worker port when wired
|
|
6432
|
+
* (after `handleInit` has installed `controlPort`); otherwise falls back
|
|
6433
|
+
* to `self.postMessage` so messages sent before init-response — and any
|
|
6434
|
+
* legacy callers — still reach the host through the iframe relay.
|
|
6435
|
+
*
|
|
6436
|
+
* Optional `transfer` arg lets callers ship transferables (ImageBitmap,
|
|
6437
|
+
* ArrayBuffer, OffscreenCanvas, …) without bypassing the helper. Both
|
|
6438
|
+
* routing paths honour it; an empty / undefined transfer list is a no-op.
|
|
6439
|
+
*/
|
|
6440
|
+
postMessage(type, data, transfer) {
|
|
6441
|
+
const envelope = {
|
|
6078
6442
|
type,
|
|
6079
6443
|
id: data?.id || `${type}_${Date.now()}`,
|
|
6080
6444
|
timestamp: Date.now(),
|
|
6081
6445
|
data
|
|
6082
|
-
}
|
|
6446
|
+
};
|
|
6447
|
+
if (this.controlPort) {
|
|
6448
|
+
this.controlPort.postMessage(envelope, transfer ?? []);
|
|
6449
|
+
} else {
|
|
6450
|
+
self.postMessage(envelope, transfer ?? []);
|
|
6451
|
+
}
|
|
6083
6452
|
}
|
|
6084
6453
|
// Phase 7: Interaction Message Handlers (delegated to InteractionSystem)
|
|
6085
6454
|
handleMouseUpdate(message) {
|
|
@@ -27548,4 +27917,4 @@ async function setSceneCode(sceneCode) {
|
|
|
27548
27917
|
}
|
|
27549
27918
|
}
|
|
27550
27919
|
self.setSceneCode = setSceneCode;
|
|
27551
|
-
//# sourceMappingURL=viji.worker-
|
|
27920
|
+
//# sourceMappingURL=viji.worker-DwYMDyfQ.js.map
|