/// import { FaceDetector } from "@mediapipe/tasks-vision"; import type { CanvasFaceBox } from "./canvas-emotion"; type DetectFaceRequest = { id: number; image: ImageBitmap; }; type DetectFaceResponse = { id: number; faces?: CanvasFaceBox[]; imageWidth?: number; imageHeight?: number; error?: string; }; let detectorPromise: Promise | null = null; const workerGlobal = self as typeof self & { importScripts: (...urls: string[]) => void; import?: (url: string) => Promise; }; // MediaPipe 会在模块 Worker 中从 importScripts 失败分支转向 self.import。 // 这里显式标记为运行时 URL,避免 Vite 将 public loader 当作源码模块转换。 workerGlobal.importScripts = () => { throw new TypeError("module worker uses dynamic import"); }; workerGlobal.import = async (url: string) => { const response = await fetch(url.replace(/\?import(?:&.*)?$/, "")); if (!response.ok) throw new Error(`MediaPipe loader 加载失败:${response.status}`); const blobUrl = URL.createObjectURL(new Blob([await response.text()], { type: "text/javascript" })); try { return await import(/* @vite-ignore */ blobUrl); } finally { URL.revokeObjectURL(blobUrl); } }; function getDetector() { if (!detectorPromise) { detectorPromise = FaceDetector.createFromOptions( { wasmLoaderPath: "/mediapipe/wasm/vision_wasm_module_internal.js", wasmBinaryPath: "/mediapipe/wasm/vision_wasm_module_internal.wasm", }, { baseOptions: { modelAssetPath: "/canvas/models/blaze-face-full-range-sparse.tflite" }, runningMode: "IMAGE", minDetectionConfidence: 0.25, minSuppressionThreshold: 0.3, }, ); } return detectorPromise; } self.onmessage = async (event: MessageEvent) => { const { id, image } = event.data; const response: DetectFaceResponse = { id, imageWidth: image.width, imageHeight: image.height }; try { const detector = await getDetector(); response.faces = detector.detect(image).detections.flatMap((detection, index) => { const box = detection.boundingBox; if (!box) return []; return [{ id: `face-${id}-${index}`, x: box.originX, y: box.originY, width: box.width, height: box.height, confidence: detection.categories[0]?.score, source: "detected" as const, }]; }); } catch (error) { response.error = error instanceof Error ? error.message : "人脸识别失败"; } finally { image.close(); } self.postMessage(response); }; export {};