@arfuhad/react-native-smart-camera 0.1.2 → 0.1.5
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/CHANGELOG.md +75 -3
- package/README.md +259 -206
- package/android/build.gradle +14 -39
- package/android/src/main/java/com/smartcamera/FaceDetectorFrameProcessorPlugin.kt +324 -0
- package/android/src/main/java/com/smartcamera/SmartCameraPackage.kt +28 -0
- package/build/detection/blinkProcessor.js +2 -1
- package/build/detection/blinkProcessor.js.map +1 -1
- package/build/detection/faceDetector.d.ts +4 -4
- package/build/detection/faceDetector.d.ts.map +1 -1
- package/build/detection/faceDetector.js +31 -11
- package/build/detection/faceDetector.js.map +1 -1
- package/build/detection/index.d.ts +1 -1
- package/build/detection/index.d.ts.map +1 -1
- package/build/detection/index.js +1 -1
- package/build/detection/index.js.map +1 -1
- package/build/detection/staticImageDetector.d.ts +11 -11
- package/build/detection/staticImageDetector.d.ts.map +1 -1
- package/build/detection/staticImageDetector.js +19 -23
- package/build/detection/staticImageDetector.js.map +1 -1
- package/build/hooks/index.d.ts +6 -0
- package/build/hooks/index.d.ts.map +1 -1
- package/build/hooks/index.js +8 -0
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/useBlinkDetection.d.ts +27 -16
- package/build/hooks/useBlinkDetection.d.ts.map +1 -1
- package/build/hooks/useBlinkDetection.js +63 -37
- package/build/hooks/useBlinkDetection.js.map +1 -1
- package/build/hooks/useFaceDetection.js +3 -2
- package/build/hooks/useFaceDetection.js.map +1 -1
- package/build/hooks/useFaceDetector.d.ts +123 -0
- package/build/hooks/useFaceDetector.d.ts.map +1 -0
- package/build/hooks/useFaceDetector.js +133 -0
- package/build/hooks/useFaceDetector.js.map +1 -0
- package/build/hooks/useSmartCamera.js.map +1 -1
- package/build/hooks/useSmartCameraWebRTC.d.ts +3 -5
- package/build/hooks/useSmartCameraWebRTC.d.ts.map +1 -1
- package/build/hooks/useSmartCameraWebRTC.js +19 -87
- package/build/hooks/useSmartCameraWebRTC.js.map +1 -1
- package/build/hooks/useWebRTC.d.ts +88 -0
- package/build/hooks/useWebRTC.d.ts.map +1 -0
- package/build/hooks/useWebRTC.js +394 -0
- package/build/hooks/useWebRTC.js.map +1 -0
- package/build/hooks/useWebRTCWithDetection.d.ts +89 -0
- package/build/hooks/useWebRTCWithDetection.d.ts.map +1 -0
- package/build/hooks/useWebRTCWithDetection.js +131 -0
- package/build/hooks/useWebRTCWithDetection.js.map +1 -0
- package/build/index.d.ts +24 -10
- package/build/index.d.ts.map +1 -1
- package/build/index.js +38 -13
- package/build/index.js.map +1 -1
- package/build/types.d.ts +28 -12
- package/build/types.d.ts.map +1 -1
- package/build/types.js.map +1 -1
- package/build/utils/index.js.map +1 -1
- package/build/webrtc/WebRTCBridge.d.ts +3 -0
- package/build/webrtc/WebRTCBridge.d.ts.map +1 -1
- package/build/webrtc/WebRTCBridge.js +12 -15
- package/build/webrtc/WebRTCBridge.js.map +1 -1
- package/build/webrtc/WebRTCManager.d.ts +148 -0
- package/build/webrtc/WebRTCManager.d.ts.map +1 -0
- package/build/webrtc/WebRTCManager.js +383 -0
- package/build/webrtc/WebRTCManager.js.map +1 -0
- package/build/webrtc/index.d.ts +3 -1
- package/build/webrtc/index.d.ts.map +1 -1
- package/build/webrtc/index.js +5 -0
- package/build/webrtc/index.js.map +1 -1
- package/build/webrtc/types.d.ts +212 -4
- package/build/webrtc/types.d.ts.map +1 -1
- package/build/webrtc/types.js +34 -1
- package/build/webrtc/types.js.map +1 -1
- package/ios/FaceDetectorFrameProcessorPlugin.m +11 -0
- package/ios/FaceDetectorFrameProcessorPlugin.swift +304 -0
- package/package.json +11 -11
- package/react-native-smart-camera.podspec +32 -0
- package/src/detection/blinkProcessor.ts +127 -0
- package/src/detection/faceDetector.ts +78 -0
- package/src/detection/index.ts +3 -0
- package/src/detection/staticImageDetector.ts +53 -0
- package/src/hooks/index.ts +26 -0
- package/src/hooks/useBlinkDetection.ts +127 -0
- package/src/hooks/useFaceDetection.ts +105 -0
- package/src/hooks/useFaceDetector.ts +191 -0
- package/src/hooks/useSmartCamera.ts +83 -0
- package/src/hooks/useSmartCameraWebRTC.ts +120 -0
- package/src/hooks/useWebRTC.ts +453 -0
- package/src/hooks/useWebRTCWithDetection.ts +181 -0
- package/src/index.ts +170 -0
- package/src/types.ts +636 -0
- package/src/utils/index.ts +355 -0
- package/src/webrtc/WebRTCBridge.ts +127 -0
- package/src/webrtc/WebRTCManager.ts +453 -0
- package/src/webrtc/index.ts +50 -0
- package/src/webrtc/types.ts +361 -0
- package/android/build/.transforms/e0a0b120a9ccc3a8de4f5784bc36b161/results.bin +0 -1
- package/android/build/.transforms/e0a0b120a9ccc3a8de4f5784bc36b161/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/generated/source/buildConfig/debug/expo/modules/smartcamera/BuildConfig.java +0 -10
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/AndroidManifest.xml +0 -7
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/output-metadata.json +0 -18
- package/android/build/intermediates/aar_metadata/debug/aar-metadata.properties +0 -6
- package/android/build/intermediates/annotation_processor_list/debug/annotationProcessors.json +0 -1
- package/android/build/intermediates/compile_library_classes_jar/debug/classes.jar +0 -0
- package/android/build/intermediates/compile_r_class_jar/debug/R.jar +0 -0
- package/android/build/intermediates/compile_symbol_list/debug/R.txt +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -1
- package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
- package/android/build/intermediates/java_res/debug/out/META-INF/arfuhad-react-native-smart-camera_debug.kotlin_module +0 -0
- package/android/build/intermediates/javac/debug/classes/expo/modules/smartcamera/BuildConfig.class +0 -0
- package/android/build/intermediates/local_only_symbol_list/debug/R-def.txt +0 -2
- package/android/build/intermediates/manifest_merge_blame_file/debug/manifest-merger-blame-debug-report.txt +0 -7
- package/android/build/intermediates/merged_manifest/debug/AndroidManifest.xml +0 -7
- package/android/build/intermediates/navigation_json/debug/navigation.json +0 -1
- package/android/build/intermediates/runtime_library_classes_jar/debug/classes.jar +0 -0
- package/android/build/intermediates/symbol_list_with_package_name/debug/package-aware-r.txt +0 -1
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +0 -2
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -16
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/build/tmp/kotlin-classes/debug/META-INF/arfuhad-react-native-smart-camera_debug.kotlin_module +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/DetectedFace.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/FaceBounds.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/FaceContoursData.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/FaceDetectionOptions.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/FaceLandmarksData.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/ImageLoader$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/ImageLoader$loadImage$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/ImageLoader.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/MLKitFaceDetector$detectFaces$2$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/MLKitFaceDetector$detectFaces$2$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/MLKitFaceDetector.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/MLKitFaceDetectorKt$sam$com_google_android_gms_tasks_OnSuccessListener$0.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/MLKitFaceDetectorKt.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/PointData.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$1$1$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$1$3$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$1$4$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$AsyncFunction$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$AsyncFunction$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$AsyncFunction$3.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$AsyncFunctionWithPromise$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$AsyncFunctionWithPromise$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$AsyncFunctionWithPromise$3.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$AsyncFunctionWithPromise$4.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$Function$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$Function$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$Function$3.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$Function$4.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$FunctionWithoutArgs$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$FunctionWithoutArgs$2.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$OnActivityEntersBackground$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$OnActivityEntersForeground$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule$definition$lambda$10$$inlined$OnDestroy$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraModule.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/SmartCameraView.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/WebRTCFrameBridge$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/smartcamera/WebRTCFrameBridge.class +0 -0
- package/android/src/main/java/expo/modules/smartcamera/ImageLoader.kt +0 -106
- package/android/src/main/java/expo/modules/smartcamera/MLKitFaceDetector.kt +0 -273
- package/android/src/main/java/expo/modules/smartcamera/SmartCameraModule.kt +0 -205
- package/android/src/main/java/expo/modules/smartcamera/SmartCameraView.kt +0 -153
- package/android/src/main/java/expo/modules/smartcamera/WebRTCFrameBridge.kt +0 -184
- package/build/SmartCamera.d.ts +0 -17
- package/build/SmartCamera.d.ts.map +0 -1
- package/build/SmartCamera.js +0 -270
- package/build/SmartCamera.js.map +0 -1
- package/build/SmartCameraModule.d.ts +0 -112
- package/build/SmartCameraModule.d.ts.map +0 -1
- package/build/SmartCameraModule.js +0 -121
- package/build/SmartCameraModule.js.map +0 -1
- package/build/SmartCameraView.d.ts +0 -8
- package/build/SmartCameraView.d.ts.map +0 -1
- package/build/SmartCameraView.js +0 -7
- package/build/SmartCameraView.js.map +0 -1
- package/expo-module.config.json +0 -9
- package/ios/MLKitFaceDetector.swift +0 -310
- package/ios/SmartCamera.podspec +0 -33
- package/ios/SmartCameraModule.swift +0 -225
- package/ios/SmartCameraView.swift +0 -146
- package/ios/WebRTCFrameBridge.swift +0 -150
package/build/webrtc/types.js
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WebRTC-related types for the SmartCamera module
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
// =============================================================================
|
|
5
|
+
// Default Configurations
|
|
6
|
+
// =============================================================================
|
|
7
|
+
/**
|
|
8
|
+
* Default ICE servers (Google STUN servers)
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_ICE_SERVERS = [
|
|
11
|
+
{ urls: 'stun:stun.l.google.com:19302' },
|
|
12
|
+
{ urls: 'stun:stun1.l.google.com:19302' },
|
|
13
|
+
];
|
|
14
|
+
/**
|
|
15
|
+
* Default peer connection configuration
|
|
16
|
+
*/
|
|
17
|
+
export const DEFAULT_PEER_CONNECTION_CONFIG = {
|
|
18
|
+
iceServers: DEFAULT_ICE_SERVERS,
|
|
19
|
+
iceTransportPolicy: 'all',
|
|
20
|
+
bundlePolicy: 'balanced',
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Default media constraints
|
|
24
|
+
*/
|
|
25
|
+
export const DEFAULT_MEDIA_CONSTRAINTS = {
|
|
26
|
+
video: {
|
|
27
|
+
width: { ideal: 1280 },
|
|
28
|
+
height: { ideal: 720 },
|
|
29
|
+
frameRate: { ideal: 30 },
|
|
30
|
+
facingMode: 'user',
|
|
31
|
+
},
|
|
32
|
+
audio: {
|
|
33
|
+
echoCancellation: true,
|
|
34
|
+
noiseSuppression: true,
|
|
35
|
+
autoGainControl: true,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
5
38
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/webrtc/types.ts"],"names":[],"mappings":"AAAA;;GAEG
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/webrtc/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAkUH,gFAAgF;AAChF,yBAAyB;AACzB,gFAAgF;AAEhF;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAgB;IAC9C,EAAE,IAAI,EAAE,8BAA8B,EAAE;IACxC,EAAE,IAAI,EAAE,+BAA+B,EAAE;CAC1C,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAyB;IAClE,UAAU,EAAE,mBAAmB;IAC/B,kBAAkB,EAAE,KAAK;IACzB,YAAY,EAAE,UAAU;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAqB;IACzD,KAAK,EAAE;QACL,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;QACtB,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;QACtB,SAAS,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;QACxB,UAAU,EAAE,MAAM;KACnB;IACD,KAAK,EAAE;QACL,gBAAgB,EAAE,IAAI;QACtB,gBAAgB,EAAE,IAAI;QACtB,eAAe,EAAE,IAAI;KACtB;CACF,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#import <VisionCamera/FrameProcessorPlugin.h>
|
|
2
|
+
#import <VisionCamera/FrameProcessorPluginRegistry.h>
|
|
3
|
+
|
|
4
|
+
#if __has_include("react_native_smart_camera-Swift.h")
|
|
5
|
+
#import "react_native_smart_camera-Swift.h"
|
|
6
|
+
#else
|
|
7
|
+
#import <react_native_smart_camera/react_native_smart_camera-Swift.h>
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
// Register the frame processor plugin
|
|
11
|
+
VISION_EXPORT_FRAME_PROCESSOR(FaceDetectorFrameProcessorPlugin, detectFaces)
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import VisionCamera
|
|
3
|
+
import MLKitFaceDetection
|
|
4
|
+
import MLKitVision
|
|
5
|
+
|
|
6
|
+
@objc(FaceDetectorFrameProcessorPlugin)
|
|
7
|
+
public class FaceDetectorFrameProcessorPlugin: FrameProcessorPlugin {
|
|
8
|
+
|
|
9
|
+
private var faceDetector: FaceDetector?
|
|
10
|
+
private var currentOptions: FaceDetectorOptions?
|
|
11
|
+
|
|
12
|
+
// Auto mode options (stored separately as they don't affect detector)
|
|
13
|
+
private var autoMode: Bool = false
|
|
14
|
+
private var windowWidth: CGFloat = 1.0
|
|
15
|
+
private var windowHeight: CGFloat = 1.0
|
|
16
|
+
private var cameraFacing: String = "front"
|
|
17
|
+
|
|
18
|
+
public override init(proxy: VisionCameraProxyHolder, options: [AnyHashable: Any]! = [:]) {
|
|
19
|
+
super.init(proxy: proxy, options: options)
|
|
20
|
+
print("[FaceDetectorPlugin] Initialized")
|
|
21
|
+
updateDetectorOptions(options as? [String: Any] ?? [:])
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private func updateDetectorOptions(_ options: [String: Any]) {
|
|
25
|
+
let performanceMode = options["performanceMode"] as? String ?? "fast"
|
|
26
|
+
let landmarkMode = options["landmarkMode"] as? String ?? "none"
|
|
27
|
+
let contourMode = options["contourMode"] as? String ?? "none"
|
|
28
|
+
let classificationMode = options["classificationMode"] as? String ?? "none"
|
|
29
|
+
let minFaceSize = options["minFaceSize"] as? CGFloat ?? 0.15
|
|
30
|
+
let trackingEnabled = options["trackingEnabled"] as? Bool ?? false
|
|
31
|
+
|
|
32
|
+
// Update auto mode options
|
|
33
|
+
autoMode = options["autoMode"] as? Bool ?? false
|
|
34
|
+
windowWidth = options["windowWidth"] as? CGFloat ?? 1.0
|
|
35
|
+
windowHeight = options["windowHeight"] as? CGFloat ?? 1.0
|
|
36
|
+
cameraFacing = options["cameraFacing"] as? String ?? "front"
|
|
37
|
+
|
|
38
|
+
let newOptions = FaceDetectorOptions()
|
|
39
|
+
|
|
40
|
+
switch performanceMode {
|
|
41
|
+
case "accurate":
|
|
42
|
+
newOptions.performanceMode = .accurate
|
|
43
|
+
default:
|
|
44
|
+
newOptions.performanceMode = .fast
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
switch landmarkMode {
|
|
48
|
+
case "all":
|
|
49
|
+
newOptions.landmarkMode = .all
|
|
50
|
+
default:
|
|
51
|
+
newOptions.landmarkMode = .none
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
switch contourMode {
|
|
55
|
+
case "all":
|
|
56
|
+
newOptions.contourMode = .all
|
|
57
|
+
default:
|
|
58
|
+
newOptions.contourMode = .none
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
switch classificationMode {
|
|
62
|
+
case "all":
|
|
63
|
+
newOptions.classificationMode = .all
|
|
64
|
+
default:
|
|
65
|
+
newOptions.classificationMode = .none
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
newOptions.minFaceSize = minFaceSize
|
|
69
|
+
newOptions.isTrackingEnabled = trackingEnabled
|
|
70
|
+
|
|
71
|
+
faceDetector = FaceDetector.faceDetector(options: newOptions)
|
|
72
|
+
currentOptions = newOptions
|
|
73
|
+
print("[FaceDetectorPlugin] Detector updated with new options")
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public override func callback(_ frame: Frame, withArguments arguments: [AnyHashable: Any]?) -> Any? {
|
|
77
|
+
if let args = arguments as? [String: Any], !args.isEmpty {
|
|
78
|
+
updateDetectorOptions(args)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
guard let detector = faceDetector else {
|
|
82
|
+
print("[FaceDetectorPlugin] Detector not initialized")
|
|
83
|
+
return []
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
guard let pixelBuffer = CMSampleBufferGetImageBuffer(frame.buffer) else {
|
|
87
|
+
print("[FaceDetectorPlugin] Could not get pixel buffer")
|
|
88
|
+
return []
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let image = VisionImage(buffer: frame.buffer)
|
|
92
|
+
image.orientation = getImageOrientation(frame.orientation)
|
|
93
|
+
|
|
94
|
+
let frameWidth = CVPixelBufferGetWidth(pixelBuffer)
|
|
95
|
+
let frameHeight = CVPixelBufferGetHeight(pixelBuffer)
|
|
96
|
+
|
|
97
|
+
var detectedFaces: [Face] = []
|
|
98
|
+
let semaphore = DispatchSemaphore(value: 0)
|
|
99
|
+
|
|
100
|
+
detector.process(image) { faces, error in
|
|
101
|
+
if let error = error {
|
|
102
|
+
print("[FaceDetectorPlugin] Detection error: \(error.localizedDescription)")
|
|
103
|
+
} else if let faces = faces {
|
|
104
|
+
detectedFaces = faces
|
|
105
|
+
}
|
|
106
|
+
semaphore.signal()
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
_ = semaphore.wait(timeout: .now() + 0.1)
|
|
110
|
+
|
|
111
|
+
return detectedFaces.map { face in
|
|
112
|
+
faceToDict(
|
|
113
|
+
face,
|
|
114
|
+
frameWidth: frameWidth,
|
|
115
|
+
frameHeight: frameHeight,
|
|
116
|
+
autoMode: autoMode,
|
|
117
|
+
windowWidth: windowWidth,
|
|
118
|
+
windowHeight: windowHeight,
|
|
119
|
+
cameraFacing: cameraFacing
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private func getImageOrientation(_ orientation: Orientation) -> UIImage.Orientation {
|
|
125
|
+
switch orientation {
|
|
126
|
+
case .portrait:
|
|
127
|
+
return .right
|
|
128
|
+
case .portraitUpsideDown:
|
|
129
|
+
return .left
|
|
130
|
+
case .landscapeLeft:
|
|
131
|
+
return .up
|
|
132
|
+
case .landscapeRight:
|
|
133
|
+
return .down
|
|
134
|
+
@unknown default:
|
|
135
|
+
return .right
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private func faceToDict(
|
|
140
|
+
_ face: Face,
|
|
141
|
+
frameWidth: Int,
|
|
142
|
+
frameHeight: Int,
|
|
143
|
+
autoMode: Bool,
|
|
144
|
+
windowWidth: CGFloat,
|
|
145
|
+
windowHeight: CGFloat,
|
|
146
|
+
cameraFacing: String
|
|
147
|
+
) -> [String: Any] {
|
|
148
|
+
var result: [String: Any] = [:]
|
|
149
|
+
|
|
150
|
+
// Calculate scale factors for autoMode
|
|
151
|
+
let scaleX = autoMode ? windowWidth / CGFloat(frameWidth) : 1.0 / CGFloat(frameWidth)
|
|
152
|
+
let scaleY = autoMode ? windowHeight / CGFloat(frameHeight) : 1.0 / CGFloat(frameHeight)
|
|
153
|
+
let mirrorX = autoMode && cameraFacing == "front"
|
|
154
|
+
|
|
155
|
+
// Bounding box
|
|
156
|
+
let bounds = face.frame
|
|
157
|
+
let x: CGFloat
|
|
158
|
+
if mirrorX {
|
|
159
|
+
x = windowWidth - ((bounds.origin.x + bounds.width) * scaleX)
|
|
160
|
+
} else {
|
|
161
|
+
x = bounds.origin.x * scaleX
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
result["bounds"] = [
|
|
165
|
+
"x": x,
|
|
166
|
+
"y": bounds.origin.y * scaleY,
|
|
167
|
+
"width": bounds.width * scaleX,
|
|
168
|
+
"height": bounds.height * scaleY
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
// Angles
|
|
172
|
+
result["rollAngle"] = face.headEulerAngleZ
|
|
173
|
+
result["pitchAngle"] = face.headEulerAngleX
|
|
174
|
+
result["yawAngle"] = face.headEulerAngleY
|
|
175
|
+
|
|
176
|
+
// Classification probabilities
|
|
177
|
+
if face.hasSmilingProbability {
|
|
178
|
+
result["smilingProbability"] = face.smilingProbability
|
|
179
|
+
}
|
|
180
|
+
if face.hasLeftEyeOpenProbability {
|
|
181
|
+
result["leftEyeOpenProbability"] = face.leftEyeOpenProbability
|
|
182
|
+
}
|
|
183
|
+
if face.hasRightEyeOpenProbability {
|
|
184
|
+
result["rightEyeOpenProbability"] = face.rightEyeOpenProbability
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Tracking ID
|
|
188
|
+
if face.hasTrackingID {
|
|
189
|
+
result["trackingId"] = face.trackingID
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Landmarks
|
|
193
|
+
var landmarks: [String: Any] = [:]
|
|
194
|
+
|
|
195
|
+
if let leftEye = face.landmark(ofType: .leftEye) {
|
|
196
|
+
landmarks["leftEye"] = pointToDict(leftEye.position, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth)
|
|
197
|
+
}
|
|
198
|
+
if let rightEye = face.landmark(ofType: .rightEye) {
|
|
199
|
+
landmarks["rightEye"] = pointToDict(rightEye.position, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth)
|
|
200
|
+
}
|
|
201
|
+
if let noseBase = face.landmark(ofType: .noseBase) {
|
|
202
|
+
landmarks["noseBase"] = pointToDict(noseBase.position, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth)
|
|
203
|
+
}
|
|
204
|
+
if let leftCheek = face.landmark(ofType: .leftCheek) {
|
|
205
|
+
landmarks["leftCheek"] = pointToDict(leftCheek.position, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth)
|
|
206
|
+
}
|
|
207
|
+
if let rightCheek = face.landmark(ofType: .rightCheek) {
|
|
208
|
+
landmarks["rightCheek"] = pointToDict(rightCheek.position, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth)
|
|
209
|
+
}
|
|
210
|
+
if let mouthLeft = face.landmark(ofType: .mouthLeft) {
|
|
211
|
+
landmarks["mouthLeft"] = pointToDict(mouthLeft.position, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth)
|
|
212
|
+
}
|
|
213
|
+
if let mouthRight = face.landmark(ofType: .mouthRight) {
|
|
214
|
+
landmarks["mouthRight"] = pointToDict(mouthRight.position, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth)
|
|
215
|
+
}
|
|
216
|
+
if let mouthBottom = face.landmark(ofType: .mouthBottom) {
|
|
217
|
+
landmarks["mouthBottom"] = pointToDict(mouthBottom.position, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth)
|
|
218
|
+
}
|
|
219
|
+
if let leftEar = face.landmark(ofType: .leftEar) {
|
|
220
|
+
landmarks["leftEar"] = pointToDict(leftEar.position, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth)
|
|
221
|
+
}
|
|
222
|
+
if let rightEar = face.landmark(ofType: .rightEar) {
|
|
223
|
+
landmarks["rightEar"] = pointToDict(rightEar.position, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if !landmarks.isEmpty {
|
|
227
|
+
result["landmarks"] = landmarks
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// All contours (like reference package)
|
|
231
|
+
var contours: [String: Any] = [:]
|
|
232
|
+
|
|
233
|
+
if let contour = face.contour(ofType: .face) {
|
|
234
|
+
contours["face"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
235
|
+
}
|
|
236
|
+
if let contour = face.contour(ofType: .leftEyebrowTop) {
|
|
237
|
+
contours["leftEyebrowTop"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
238
|
+
}
|
|
239
|
+
if let contour = face.contour(ofType: .leftEyebrowBottom) {
|
|
240
|
+
contours["leftEyebrowBottom"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
241
|
+
}
|
|
242
|
+
if let contour = face.contour(ofType: .rightEyebrowTop) {
|
|
243
|
+
contours["rightEyebrowTop"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
244
|
+
}
|
|
245
|
+
if let contour = face.contour(ofType: .rightEyebrowBottom) {
|
|
246
|
+
contours["rightEyebrowBottom"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
247
|
+
}
|
|
248
|
+
if let contour = face.contour(ofType: .leftEye) {
|
|
249
|
+
contours["leftEye"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
250
|
+
}
|
|
251
|
+
if let contour = face.contour(ofType: .rightEye) {
|
|
252
|
+
contours["rightEye"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
253
|
+
}
|
|
254
|
+
if let contour = face.contour(ofType: .upperLipTop) {
|
|
255
|
+
contours["upperLipTop"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
256
|
+
}
|
|
257
|
+
if let contour = face.contour(ofType: .upperLipBottom) {
|
|
258
|
+
contours["upperLipBottom"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
259
|
+
}
|
|
260
|
+
if let contour = face.contour(ofType: .lowerLipTop) {
|
|
261
|
+
contours["lowerLipTop"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
262
|
+
}
|
|
263
|
+
if let contour = face.contour(ofType: .lowerLipBottom) {
|
|
264
|
+
contours["lowerLipBottom"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
265
|
+
}
|
|
266
|
+
if let contour = face.contour(ofType: .noseBridge) {
|
|
267
|
+
contours["noseBridge"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
268
|
+
}
|
|
269
|
+
if let contour = face.contour(ofType: .noseBottom) {
|
|
270
|
+
contours["noseBottom"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
271
|
+
}
|
|
272
|
+
if let contour = face.contour(ofType: .leftCheek) {
|
|
273
|
+
contours["leftCheek"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
274
|
+
}
|
|
275
|
+
if let contour = face.contour(ofType: .rightCheek) {
|
|
276
|
+
contours["rightCheek"] = contour.points.map { pointToDict($0, scaleX: scaleX, scaleY: scaleY, mirrorX: mirrorX, windowWidth: windowWidth) }
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if !contours.isEmpty {
|
|
280
|
+
result["contours"] = contours
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return result
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private func pointToDict(
|
|
287
|
+
_ point: VisionPoint,
|
|
288
|
+
scaleX: CGFloat,
|
|
289
|
+
scaleY: CGFloat,
|
|
290
|
+
mirrorX: Bool,
|
|
291
|
+
windowWidth: CGFloat
|
|
292
|
+
) -> [String: CGFloat] {
|
|
293
|
+
let x: CGFloat
|
|
294
|
+
if mirrorX {
|
|
295
|
+
x = windowWidth - (point.x * scaleX)
|
|
296
|
+
} else {
|
|
297
|
+
x = point.x * scaleX
|
|
298
|
+
}
|
|
299
|
+
return [
|
|
300
|
+
"x": x,
|
|
301
|
+
"y": point.y * scaleY
|
|
302
|
+
]
|
|
303
|
+
}
|
|
304
|
+
}
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arfuhad/react-native-smart-camera",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "VisionCamera frame processor plugin for face detection, blink detection, and WebRTC streaming",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
7
|
+
"react-native": "src/index.ts",
|
|
8
|
+
"source": "src/index.ts",
|
|
7
9
|
"scripts": {
|
|
8
|
-
"build": "
|
|
10
|
+
"build": "tsc --project tsconfig.build.json",
|
|
9
11
|
"build:plugin": "tsc --project plugin/tsconfig.json",
|
|
10
|
-
"clean": "
|
|
11
|
-
"lint": "
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"prepublishOnly": "expo-module prepublishOnly",
|
|
15
|
-
"expo-module": "expo-module"
|
|
12
|
+
"clean": "rm -rf build plugin/build",
|
|
13
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
14
|
+
"prepare": "npm run build && npm run build:plugin",
|
|
15
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
16
16
|
},
|
|
17
17
|
"keywords": [
|
|
18
18
|
"react-native",
|
|
@@ -23,16 +23,16 @@
|
|
|
23
23
|
"webrtc",
|
|
24
24
|
"vision-camera",
|
|
25
25
|
"ml-kit",
|
|
26
|
-
"expo-module",
|
|
27
26
|
"frame-processor"
|
|
28
27
|
],
|
|
29
28
|
"files": [
|
|
29
|
+
"src",
|
|
30
30
|
"build",
|
|
31
31
|
"ios",
|
|
32
32
|
"android",
|
|
33
33
|
"plugin/build",
|
|
34
34
|
"app.plugin.js",
|
|
35
|
-
"
|
|
35
|
+
"react-native-smart-camera.podspec",
|
|
36
36
|
"README.md",
|
|
37
37
|
"ARCHITECTURE.md",
|
|
38
38
|
"CHANGELOG.md"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'react-native-smart-camera'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.description = package['description']
|
|
10
|
+
s.license = package['license']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.homepage = package['homepage']
|
|
13
|
+
s.platforms = { :ios => '13.4' }
|
|
14
|
+
s.swift_version = '5.4'
|
|
15
|
+
s.source = { git: package['repository']['url'], tag: "v#{s.version}" }
|
|
16
|
+
s.static_framework = true
|
|
17
|
+
|
|
18
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
19
|
+
|
|
20
|
+
# React Native dependency
|
|
21
|
+
s.dependency 'React-Core'
|
|
22
|
+
|
|
23
|
+
# VisionCamera for frame processor API
|
|
24
|
+
s.dependency 'VisionCamera'
|
|
25
|
+
|
|
26
|
+
# Google ML Kit Face Detection
|
|
27
|
+
s.dependency 'GoogleMLKit/FaceDetection', '~> 5.0.0'
|
|
28
|
+
|
|
29
|
+
# Exclude test files
|
|
30
|
+
s.exclude_files = "ios/Tests/**/*"
|
|
31
|
+
end
|
|
32
|
+
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { Face, BlinkEvent } from '../types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Threshold for considering an eye as closed
|
|
5
|
+
*/
|
|
6
|
+
const EYE_CLOSED_THRESHOLD = 0.4;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Threshold for considering an eye as open
|
|
10
|
+
*/
|
|
11
|
+
const EYE_OPEN_THRESHOLD = 0.6;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* State for tracking blink across frames
|
|
15
|
+
*/
|
|
16
|
+
interface BlinkState {
|
|
17
|
+
wasEyesClosed: boolean;
|
|
18
|
+
lastBlinkTimestamp: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Global blink state per face tracking ID
|
|
22
|
+
const blinkStates = new Map<number, BlinkState>();
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Process faces to detect blinks
|
|
26
|
+
*
|
|
27
|
+
* @param faces - Array of detected faces
|
|
28
|
+
* @param lastBlinkTimestamp - Timestamp of the last detected blink
|
|
29
|
+
* @param debounceMs - Minimum time between blinks in milliseconds
|
|
30
|
+
* @returns BlinkEvent if a blink was detected, null otherwise
|
|
31
|
+
*/
|
|
32
|
+
export function processBlinkFromFaces(
|
|
33
|
+
faces: Face[],
|
|
34
|
+
lastBlinkTimestamp: number,
|
|
35
|
+
debounceMs: number = 300
|
|
36
|
+
): BlinkEvent | null {
|
|
37
|
+
'worklet';
|
|
38
|
+
|
|
39
|
+
if (faces.length === 0) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Use the first face (most prominent)
|
|
44
|
+
const face = faces[0];
|
|
45
|
+
|
|
46
|
+
// Ensure we have eye classification data
|
|
47
|
+
if (
|
|
48
|
+
face.leftEyeOpenProbability === undefined ||
|
|
49
|
+
face.rightEyeOpenProbability === undefined
|
|
50
|
+
) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const leftEyeOpen = face.leftEyeOpenProbability;
|
|
55
|
+
const rightEyeOpen = face.rightEyeOpenProbability;
|
|
56
|
+
const now = Date.now();
|
|
57
|
+
|
|
58
|
+
// Get or create blink state for this face
|
|
59
|
+
const faceId = face.trackingId ?? 0;
|
|
60
|
+
let state = blinkStates.get(faceId);
|
|
61
|
+
|
|
62
|
+
if (!state) {
|
|
63
|
+
state = {
|
|
64
|
+
wasEyesClosed: false,
|
|
65
|
+
lastBlinkTimestamp: 0,
|
|
66
|
+
};
|
|
67
|
+
blinkStates.set(faceId, state);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Check if eyes are currently closed
|
|
71
|
+
const eyesClosed = leftEyeOpen < EYE_CLOSED_THRESHOLD && rightEyeOpen < EYE_CLOSED_THRESHOLD;
|
|
72
|
+
|
|
73
|
+
// Check if eyes are currently open
|
|
74
|
+
const eyesOpen = leftEyeOpen > EYE_OPEN_THRESHOLD && rightEyeOpen > EYE_OPEN_THRESHOLD;
|
|
75
|
+
|
|
76
|
+
// Detect blink: transition from closed to open
|
|
77
|
+
const isBlink = state.wasEyesClosed && eyesOpen && (now - state.lastBlinkTimestamp) > debounceMs;
|
|
78
|
+
|
|
79
|
+
// Update state
|
|
80
|
+
if (eyesClosed) {
|
|
81
|
+
state.wasEyesClosed = true;
|
|
82
|
+
} else if (eyesOpen) {
|
|
83
|
+
state.wasEyesClosed = false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (isBlink) {
|
|
87
|
+
state.lastBlinkTimestamp = now;
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
timestamp: now,
|
|
91
|
+
leftEyeOpen,
|
|
92
|
+
rightEyeOpen,
|
|
93
|
+
isBlink: true,
|
|
94
|
+
faceId: face.trackingId,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Reset blink state for all faces
|
|
103
|
+
*/
|
|
104
|
+
export function resetBlinkStates(): void {
|
|
105
|
+
blinkStates.clear();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get current eye state without blink detection
|
|
110
|
+
* Useful for real-time eye tracking UI
|
|
111
|
+
*/
|
|
112
|
+
export function getEyeState(face: Face): { leftOpen: number; rightOpen: number } | null {
|
|
113
|
+
'worklet';
|
|
114
|
+
|
|
115
|
+
if (
|
|
116
|
+
face.leftEyeOpenProbability === undefined ||
|
|
117
|
+
face.rightEyeOpenProbability === undefined
|
|
118
|
+
) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
leftOpen: face.leftEyeOpenProbability,
|
|
124
|
+
rightOpen: face.rightEyeOpenProbability,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { VisionCameraProxy, type Frame } from 'react-native-vision-camera';
|
|
2
|
+
import type { Face, FrameProcessorOptions } from '../types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Initialize the face detector frame processor plugin
|
|
6
|
+
* This registers the native plugin with VisionCamera
|
|
7
|
+
*/
|
|
8
|
+
const plugin = VisionCameraProxy.initFrameProcessorPlugin('detectFaces', {});
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Default face detection options
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_OPTIONS: FrameProcessorOptions = {
|
|
14
|
+
performanceMode: 'fast',
|
|
15
|
+
landmarkMode: 'none',
|
|
16
|
+
contourMode: 'none',
|
|
17
|
+
classificationMode: 'none',
|
|
18
|
+
minFaceSize: 0.15,
|
|
19
|
+
trackingEnabled: false,
|
|
20
|
+
cameraFacing: 'front',
|
|
21
|
+
autoMode: false,
|
|
22
|
+
windowWidth: 1.0,
|
|
23
|
+
windowHeight: 1.0,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Detect faces in a camera frame
|
|
28
|
+
*
|
|
29
|
+
* @param frame - The camera frame from VisionCamera
|
|
30
|
+
* @param options - Face detection options
|
|
31
|
+
* @returns Array of detected faces
|
|
32
|
+
*/
|
|
33
|
+
export function detectFaces(frame: Frame, options?: Partial<FrameProcessorOptions>): Face[] {
|
|
34
|
+
'worklet';
|
|
35
|
+
|
|
36
|
+
if (plugin == null) {
|
|
37
|
+
// Plugin not available - return empty array
|
|
38
|
+
// This can happen if the native module is not properly linked
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const mergedOptions: FrameProcessorOptions = {
|
|
43
|
+
...DEFAULT_OPTIONS,
|
|
44
|
+
...options,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
// Convert options to a format compatible with VisionCamera plugin API
|
|
49
|
+
const pluginOptions: Record<string, string | number | boolean | undefined> = {
|
|
50
|
+
performanceMode: mergedOptions.performanceMode,
|
|
51
|
+
landmarkMode: mergedOptions.landmarkMode,
|
|
52
|
+
contourMode: mergedOptions.contourMode,
|
|
53
|
+
classificationMode: mergedOptions.classificationMode,
|
|
54
|
+
minFaceSize: mergedOptions.minFaceSize,
|
|
55
|
+
trackingEnabled: mergedOptions.trackingEnabled,
|
|
56
|
+
cameraFacing: mergedOptions.cameraFacing,
|
|
57
|
+
autoMode: mergedOptions.autoMode,
|
|
58
|
+
windowWidth: mergedOptions.windowWidth,
|
|
59
|
+
windowHeight: mergedOptions.windowHeight,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const result = plugin.call(frame, pluginOptions) as Face[] | null | undefined;
|
|
63
|
+
return result ?? [];
|
|
64
|
+
} catch (error) {
|
|
65
|
+
// Return empty array on error in worklet context
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Check if the face detector plugin is available
|
|
72
|
+
* @returns true if the plugin is registered and available
|
|
73
|
+
*/
|
|
74
|
+
export function isFaceDetectorAvailable(): boolean {
|
|
75
|
+
return plugin != null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|