diff --git a/src/components/PoseDetector.tsx b/src/components/PoseDetector.tsx index 85e9e9b..c87f54d 100644 --- a/src/components/PoseDetector.tsx +++ b/src/components/PoseDetector.tsx @@ -4,6 +4,9 @@ import type { pose } from "@/utils/detector" import { detectSlope, detectTextNeck } from "@/utils/detector" import { drawPose } from "@/utils/drawer" import usePushNotification from "@/hooks/usePushNotification" +import { worker } from "@/utils/worker" + +declare let ml5: any const PoseDetector: React.FC = () => { const [isScriptLoaded, setIsScriptLoaded] = useState(false) @@ -13,6 +16,7 @@ const PoseDetector: React.FC = () => { const [isModelLoaded, setIsModelLoaded] = useState(false) const [mode, setMode] = useState("snapshot") + const modelRef = useRef(null) const snapRef = useRef(null) const resultRef = useRef(null) const textNeckStartTime = useRef(null) @@ -23,25 +27,43 @@ const PoseDetector: React.FC = () => { const requestApi = (delay: number): Promise => new Promise((resolve) => setTimeout(resolve, delay)) + const setup = async (): Promise => { + ml5.bodyPose( + "MoveNet", + { + modelType: "SINGLEPOSE_THUNDER", + }, + setupCallback + ) + } + + const setupCallback = async (bodypose: any, error: Error): Promise => { + if (error) { + console.log("bodypose 모델 불러오기를 실패했습니다.") + return + } + await initializeBackend() + setIsModelLoaded(true) + modelRef.current = bodypose + worker.postMessage({ type: "init", data: {} }) + } + const getScript = (): void => { - console.log("getScript") const script = document.createElement("script") script.src = "https://unpkg.com/ml5@1/dist/ml5.min.js" - script.onload = (): void => { setIsScriptLoaded(true) + setup() } - script.onerror = (): void => { setIsScriptError(true) } - document.body.appendChild(script) } // webgl설정 const initializeBackend = async (): Promise => { - await window.ml5.setBackend("webgl") + await ml5.setBackend("webgl") } const detect = (results: pose[]): void => { @@ -73,19 +95,16 @@ const PoseDetector: React.FC = () => { } } - // pose detecting 시작 const detectStart = async (video: HTMLVideoElement): Promise => { - const detector = window.ml5.bodyPose("MoveNet", { - modelType: "SINGLEPOSE_THUNDER", - }) - await detector.loadModel() - await initializeBackend() - setIsModelLoaded(true) - detector.detectStart(video, detect) + worker.onmessage = ({ data }: any) => { + if (modelRef.current) { + modelRef.current.detect(video, detect) + } + } } const getInitSnap = (): void => { - if (isModelLoaded) snapRef.current = resultRef.current + if (modelRef && modelRef.current) snapRef.current = resultRef.current } useEffect(() => { diff --git a/src/utils/index.ts b/src/utils/index.ts index 212c377..dd86d45 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,3 +1,4 @@ -export * from "./calculator"; -export * from "./detector"; -export * from "./drawer"; +export * from "./calculator" +export * from "./detector" +export * from "./drawer" +export * from "./worker" diff --git a/src/utils/worker.ts b/src/utils/worker.ts new file mode 100644 index 0000000..f81ac78 --- /dev/null +++ b/src/utils/worker.ts @@ -0,0 +1,4 @@ +// eslint-disable-next-line import/extensions +import Worker from "../workers/worker.ts?worker" + +export const worker = new Worker() diff --git a/src/workers/worker.ts b/src/workers/worker.ts new file mode 100644 index 0000000..fbb0ae5 --- /dev/null +++ b/src/workers/worker.ts @@ -0,0 +1,14 @@ +interface e { + type: string + data: any +} + +self.onmessage = (e) => { + const { type, data } = e.data + switch (type) { + case "init": + setInterval(() => { + postMessage("do it") + }, 100) + } +} diff --git a/tsconfig.json b/tsconfig.json index db86abc..2829cc7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,7 @@ "outDir": "./dist", "target": "ES2020", "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], + "lib": ["ES2020", "DOM", "DOM.Iterable", "WebWorker"], "module": "ESNext", "skipLibCheck": true,