@monitordog/detector
v1.0.16
Published
Lean browser SDK for MonitorDog local ONNX detection.
Readme
MonitorDog Detector SDK v2
MonitorDog 로컬 ONNX 감지를 위한 경량 브라우저 SDK입니다.
import { MonitorDogDetector } from "@monitordog/detector";
const detector = await MonitorDogDetector.init({
apiBaseUrl: "https://dev-api.monitor.dog/v1",
// "auto"는 데스크톱 640, 모바일/태블릿 416으로 시작합니다.
modelInputSize: "auto",
sessionTokenEndpoint: "/api/monitordog/sdk-session",
onDetect: (result) => {
console.log(result.personCount, result.phoneCount);
for (const pose of result.poseTracking?.detections ?? []) {
console.log(pose.x, pose.y, pose.width, pose.height);
console.log(pose.landmarks);
}
},
});
await detector.login({ email: "[email protected]" });
await detector.start();personDetected와 personCount는 YOLO 얼굴 결과와 MediaPipe 사용자 추적 상태를 합친 값입니다. 얼굴이 감지되면 얼굴 수를 사용하고, 얼굴이 없더라도 Pose 상태가 TRACKING 또는 MISSING이면 사용자 1명으로 반환합니다. 모델별 상세 결과는 faceDetections와 poseTracking에서 확인합니다.
poseTracking.detections의 bounding box와 landmark x, y는 원본 비디오 기준 픽셀 좌표입니다. 각 landmark에는 MediaPipe의 0~1 normalizedX, normalizedY, depth z, visibility도 함께 포함됩니다. Pose가 없는 프레임에는 detections가 빈 배열이며, pose tracking이 비활성화된 경우에도 빈 배열이 반환됩니다.
Camera errors
웹캠 시작 오류는 MonitorDogSdkError로 전달됩니다. CAMERA_IN_USE는 다른 애플리케이션이나 브라우저 탭이 카메라를 사용 중일 가능성이 있음을 의미합니다. 원본 브라우저 오류는 cause에서 확인할 수 있습니다.
import { MonitorDogSdkError } from "@monitordog/detector";
onError: (error) => {
if (error instanceof MonitorDogSdkError) {
console.error(error.code, error.message, error.cause);
}
}카메라 오류 코드는 CAMERA_PERMISSION_DENIED, CAMERA_NOT_FOUND, CAMERA_IN_USE, CAMERA_CONSTRAINT_FAILED, CAMERA_REQUEST_TIMEOUT, CAMERA_UNSUPPORTED, CAMERA_READ_FAILED입니다.
SDK session and MPA restore
login({ email })은 사용자가 실제로 고객사 서비스에 로그인한 시점에 호출합니다. 이 호출은 SDK 세션 토큰을 발급받고 MonitorDog에 login activity event를 남깁니다.
MPA 페이지 이동, 새로고침, 새 탭 복원처럼 이미 고객사 로그인 세션이 유지되는 상황에서는 login()을 인자 없이 호출합니다. 이 호출은 restore token source로 account/policy를 다시 로드해 SDK를 authenticated 상태로 만들지만 login activity event는 보내지 않습니다.
const detector = await MonitorDogDetector.init({
apiBaseUrl: "https://dev-api.monitor.dog/v1",
sessionTokenEndpoint: "/api/monitordog/sdk-session",
onDetect: (result) => {
console.log(result.personCount, result.phoneCount);
},
});
// 첫 사용자 로그인 시점
await detector.login({ email });
// MPA 페이지 이동/새로고침 후 SDK 세션 복원
await detector.login();
await detector.start();고객사 서버는 자체 HttpOnly 로그인 쿠키로 사용자를 식별하고, 서버에서 Partner API Key로 MonitorDog /v1/sdk/sessions를 호출한 뒤 짧은 SDK token만 브라우저에 반환해야 합니다. Partner API Key는 브라우저 저장소, JS bundle, HTML, localStorage/sessionStorage에 넣지 않습니다.
sessionTokenEndpoint는 고객사 token broker URL을 그대로 사용하며 apiBaseUrl에 붙이지 않습니다. login({ email })에서는 POST로 { email } JSON body를 보내고, login() 복원에서는 같은 endpoint를 POST body 없이 호출합니다. 두 호출 모두 credentials: "include"를 사용하므로 고객사 서버는 자체 HttpOnly 로그인 쿠키로 사용자를 식별할 수 있습니다.
직접 제어가 필요하면 sessionTokenProvider를 사용할 수 있습니다. MPA 복원만 별도 콜백으로 제어해야 하는 특수한 경우에는 restoreSessionTokenProvider를 추가할 수 있습니다. provider와 endpoint를 모두 설정한 경우 provider가 우선합니다.
/auth/v2와 /v1/auth/cookie는 MonitorDog 일반 웹 로그인 쿠키 흐름용 API입니다. 고객사 MPA에서 SDK 로그인 유지를 위해 직접 호출하는 API가 아니며, SDK 연동에서는 고객사 서버의 token broker와 /v1/sdk/sessions server-to-server 호출을 사용합니다.
이 패키지는 입력 크기 320, 416, 640용 암호화된 detector ONNX 자산을 포함합니다. 브라우저에서는 onnxruntime-web WebAssembly를 로컬로 사용하고, /auth/sdk-asset-key에서는 패키지 자산 복호화에 필요한 DEK만 요청합니다.
Runtime assets
이 패키지는 브라우저 런타임에 필요한 암호화 모델, ORT wasm 파일, MediaPipe pose tracking runtime을 dist/assets/sdk, dist/assets/ort, dist/assets/mediapipe에 포함합니다.
Vite, Webpack 5, Rspack, Next.js client bundle처럼 ESM asset 처리를 지원하는 일반 JS 번들러 앱은 별도 SDK plugin이나 copy script 없이 평소처럼 빌드하면 됩니다. SDK package에는 detector model 3개, ORT 2개, MediaPipe pose model과 wasm runtime 6개가 함께 포함됩니다.
npm install @monitordog/detector
npm run build앱 코드에서는 runtimeAssetBaseUrl을 지정하지 않습니다.
await MonitorDogDetector.init({
apiBaseUrl: "https://dev-api.monitor.dog/v1",
sessionTokenProvider,
onDetect,
});JSP/WAR 또는 번들러 없는 static deploy
npm install이나 monitordog-copy-assets를 실행하기 어려운 JSP/WAR/static 서버 고객은 릴리스 산출물인 monitordog-detector-static-{version}-{environment}.zip을 사용합니다. 압축을 풀어 나온 monitordog/ 폴더를 정적 리소스 경로에 통째로 배치합니다.
/vendor/monitordog/
monitordog-detector.umd.js
assets/
inference-worker-*.js
sdk/detector-320.onnx.enc
sdk/detector-416.onnx.enc
sdk/detector-640.onnx.enc
ort/ort-wasm-simd-threaded.mjs
ort/ort-wasm-simd-threaded.wasm
mediapipe/pose_landmarker_lite.task
mediapipe/vision_wasm_internal.js
mediapipe/vision_wasm_internal.wasm
mediapipe/vision_wasm_module_internal.js
mediapipe/vision_wasm_module_internal.wasm
mediapipe/vision_wasm_nosimd_internal.js
mediapipe/vision_wasm_nosimd_internal.wasm
manifest.json
example.html
README.md
LICENSEHTML/JSP에서는 UMD script 하나를 로드합니다. monitordog-detector.umd.js와 assets/가 같은 monitordog/ 폴더 안에 있으면 runtimeAssetBaseUrl을 지정하지 않습니다.
<script src="/vendor/monitordog/monitordog-detector.umd.js"></script>
<script>
const { MonitorDogDetector } = window.MonitorDogDetector;
(async () => {
const detector = await MonitorDogDetector.init({
apiBaseUrl: "https://api.monitor.dog/v1",
modelInputSize: "auto",
sessionTokenEndpoint: "/api/monitordog/sdk-session",
onDetect: (result) => {
console.log(result.personCount, result.phoneCount);
},
});
await detector.login({ email: "[email protected]" });
await detector.start();
})();
</script>서버 MIME mapping은 아래처럼 지정합니다.
.js:application/javascript.mjs:application/javascript.wasm:application/wasm.enc:application/octet-stream.task:application/octet-stream
npm 기반 static asset 직접 합치기
npm package를 설치하고 앱 build/packaging 단계에서 SDK runtime asset을 직접 합치고 싶은 고객은 선택적으로 SDK CLI를 사용합니다.
{
"scripts": {
"build": "vite build",
"copy:md-sdk-assets": "monitordog-copy-assets src/main/webapp/assets/dist/assets",
"package:war": "npm run build && npm run copy:md-sdk-assets && mvn -q -DskipTests clean package"
}
}monitordog-copy-assets <target-dir>에서 <target-dir>은 브라우저에 노출되는 sdk/, ort/, mediapipe/의 parent directory입니다. 실행 시 <target-dir>/sdk, <target-dir>/ort, <target-dir>/mediapipe만 교체하고 target root는 삭제하지 않습니다.
Custom static path 또는 CDN
앱이 detector UMD script와 sdk/, ort/, mediapipe/ runtime asset을 서로 다른 경로로 배포해야 하는 경우에만 SDK 초기화 시 runtimeAssetBaseUrl을 지정합니다. 이 값은 브라우저에 노출되는 sdk/, ort/, mediapipe/의 parent URL입니다.
{
"scripts": {
"copy:md-sdk-assets": "monitordog-copy-assets public/monitordog-sdk"
}
}await MonitorDogDetector.init({
apiBaseUrl: "https://dev-api.monitor.dog/v1",
runtimeAssetBaseUrl: "/monitordog-sdk",
sessionTokenProvider,
});이 경우 SDK는 다음 경로를 사용합니다.
- detector model:
/monitordog-sdk/sdk/detector-640.onnx.enc - ORT wasm runtime:
/monitordog-sdk/ort/ort-wasm-simd-threaded.mjs,/monitordog-sdk/ort/ort-wasm-simd-threaded.wasm - MediaPipe pose model/runtime:
/monitordog-sdk/mediapipe/pose_landmarker_lite.task,/monitordog-sdk/mediapipe/vision_wasm_*_internal.{js,wasm}
.onnx.enc만 복사하면 onnxruntime-web 또는 MediaPipe wasm 파일을 찾지 못할 수 있으므로 sdk/, ort/, mediapipe/를 모두 배포해야 합니다. MediaPipe runtime은 실행 환경에 따라 SIMD, module, nosimd loader 중 하나를 선택하므로 package와 static zip에는 6개 wasm loader/binary 파일을 모두 포함합니다. runtimeAssetBaseUrl은 모델 선택이나 /auth/sdk-asset-key 계약을 바꾸지 않고, 브라우저가 runtime byte를 fetch하는 위치만 바꿉니다.
worker JS 파일(assets/inference-worker-*.js)은 UMD script 기준의 sibling assets/ 경로에서 로드됩니다. 기본 static zip 구조를 유지하지 않고 asset을 분리할 때는 worker 파일도 UMD script 기준 경로에서 접근 가능해야 합니다.
Model input size
modelInputSize는 초기 모델 크기 선택 옵션입니다. 기본값 "auto"는 데스크톱에서 640, 모바일/태블릿에서 416으로 시작하며, 320, 416, 640을 직접 지정할 수 있습니다. 메모리 부족이 발생하면 기존과 동일하게 640 -> 416 -> 320 순서로 fallback합니다. 이 옵션은 runtime asset 404를 해결하는 옵션이 아니며, asset 경로 문제는 runtimeAssetBaseUrl로 처리합니다.
