react-native-vision-camera-spoof-detector 1.0.28 → 1.1.7

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.

Potentially problematic release.


This version of react-native-vision-camera-spoof-detector might be problematic. Click here for more details.

Files changed (67) hide show
  1. package/.npmignore +16 -99
  2. package/README.md +5 -4
  3. package/android/CMakeLists.txt +29 -0
  4. package/android/build.gradle +26 -12
  5. package/android/fix-prefab.gradle +4 -0
  6. package/android/src/main/AndroidManifest.xml +1 -1
  7. package/android/src/main/cpp/CMakeLists.txt +18 -86
  8. package/android/src/main/cpp/FaceAntiSpoofJSI.cpp +80 -6
  9. package/android/src/main/cpp/cpp-adapter.cpp +9 -0
  10. package/android/src/main/java/com/faceantispoof/FaceAntiSpoofModule.kt +108 -103
  11. package/android/src/main/java/com/faceantispoof/FaceAntiSpoofPackage.kt +12 -27
  12. package/android/src/main/java/com/faceantispoof/FaceAntiSpoofingAdvanced.kt +58 -1
  13. package/android/src/main/java/com/margelo/nitro/camera/spoofdetector/HybridSpoofDetectorFactory.kt +15 -0
  14. package/android/src/main/java/com/margelo/nitro/camera/spoofdetector/HybridSpoofDetectorOutput.kt +107 -0
  15. package/index.d.ts +14 -1
  16. package/index.js +26 -57
  17. package/nitro.json +20 -0
  18. package/nitrogen/generated/.gitattributes +1 -0
  19. package/nitrogen/generated/android/VisionCameraSpoofDetector+autolinking.cmake +81 -0
  20. package/nitrogen/generated/android/VisionCameraSpoofDetector+autolinking.gradle +27 -0
  21. package/nitrogen/generated/android/VisionCameraSpoofDetectorOnLoad.cpp +58 -0
  22. package/nitrogen/generated/android/VisionCameraSpoofDetectorOnLoad.hpp +34 -0
  23. package/nitrogen/generated/android/c++/JAntiSpoofingResult.hpp +77 -0
  24. package/nitrogen/generated/android/c++/JFunc_void_AntiSpoofingResult.hpp +78 -0
  25. package/nitrogen/generated/android/c++/JFunc_void_std__exception_ptr.hpp +76 -0
  26. package/nitrogen/generated/android/c++/JHybridSpoofDetectorFactorySpec.cpp +75 -0
  27. package/nitrogen/generated/android/c++/JHybridSpoofDetectorFactorySpec.hpp +63 -0
  28. package/nitrogen/generated/android/c++/JSize.hpp +61 -0
  29. package/nitrogen/generated/android/c++/JSpoofDetectorOutputOptions.hpp +91 -0
  30. package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/AntiSpoofingResult.kt +76 -0
  31. package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/Func_void_AntiSpoofingResult.kt +78 -0
  32. package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/Func_void_std__exception_ptr.kt +78 -0
  33. package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/HybridSpoofDetectorFactorySpec.kt +57 -0
  34. package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/Size.kt +56 -0
  35. package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/SpoofDetectorOutputOptions.kt +65 -0
  36. package/nitrogen/generated/android/kotlin/com/margelo/nitro/camera/spoofdetector/VisionCameraSpoofDetectorOnLoad.kt +35 -0
  37. package/nitrogen/generated/shared/c++/AntiSpoofingResult.hpp +103 -0
  38. package/nitrogen/generated/shared/c++/HybridSpoofDetectorFactorySpec.cpp +21 -0
  39. package/nitrogen/generated/shared/c++/HybridSpoofDetectorFactorySpec.hpp +67 -0
  40. package/nitrogen/generated/shared/c++/Size.hpp +87 -0
  41. package/nitrogen/generated/shared/c++/SpoofDetectorOutputOptions.hpp +98 -0
  42. package/package.json +12 -13
  43. package/react-native-vision-camera-spoof-detector.podspec +4 -4
  44. package/src/specs/SpoofDetectorFactory.nitro.ts +23 -0
  45. package/.gitattributes +0 -2
  46. package/CONTRIBUTING.md +0 -280
  47. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  48. package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
  49. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  50. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  51. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  52. package/android/.gradle/8.9/gc.properties +0 -0
  53. package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
  54. package/android/.gradle/9.2.0/checksums/md5-checksums.bin +0 -0
  55. package/android/.gradle/9.2.0/checksums/sha1-checksums.bin +0 -0
  56. package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
  57. package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
  58. package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
  59. package/android/.gradle/9.2.0/gc.properties +0 -0
  60. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  61. package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
  62. package/android/.gradle/vcs-1/gc.properties +0 -0
  63. package/android/build/reports/problems/problems-report.html +0 -659
  64. package/android/src/main/assets/spoof_model_scale_2_7.tflite +0 -0
  65. package/android/src/main/assets/spoof_model_scale_4_0.tflite +0 -0
  66. package/android/src/main/java/com/faceantispoof/FaceAntiSpoofFrameProcessor.kt +0 -198
  67. /package/{android/src/main → lib}/assets/FaceAntiSpoofing.tflite +0 -0
@@ -1,198 +0,0 @@
1
- package com.faceantispoof
2
-
3
- import com.mrousavy.camera.frameprocessors.Frame
4
- import com.mrousavy.camera.frameprocessors.FrameProcessorPlugin
5
- import android.util.Log
6
- import java.util.concurrent.Executors
7
- import java.util.concurrent.ConcurrentHashMap
8
- import java.util.concurrent.atomic.AtomicReference
9
-
10
- /**
11
- * Frame processor that performs face anti-spoofing detection directly on YUV frames
12
- * without creating intermediate Bitmaps. Uses ByteBuffer and FloatArray for efficient processing.
13
- *
14
- * IMPORTANT: All heavy processing is offloaded to a dedicated background thread (not the VisionCamera callback thread)
15
- * to prevent frame drop issues and ensure smooth camera preview.
16
- */
17
- class FaceAntiSpoofFrameProcessor : FrameProcessorPlugin() {
18
-
19
- private var faceAntiSpoofing: FaceAntiSpoofingAdvanced? = null
20
- private var isInitialized = false
21
-
22
- // Single-threaded executor for offloading processing tasks
23
- private val processingExecutor = Executors.newSingleThreadExecutor { runnable ->
24
- Thread(runnable, "FaceAntiSpoofProcessor").apply { isDaemon = true }
25
- }
26
-
27
- // Store the latest result to avoid race conditions
28
- private val latestResult: AtomicReference<Map<String, Any?>> = AtomicReference(
29
- mapOf(
30
- "error" to "Not initialized",
31
- "isLive" to false,
32
- "label" to "Not Initialized"
33
- )
34
- )
35
-
36
- // Track if processing is in flight to prevent queue overflow
37
- private val isProcessing = AtomicReference(false)
38
-
39
- fun initialize(assets: android.content.res.AssetManager) {
40
- try {
41
- faceAntiSpoofing = FaceAntiSpoofingAdvanced(assets)
42
- isInitialized = true
43
- Log.i("FaceAntiSpoof", "Initialized successfully")
44
- } catch (e: Exception) {
45
- Log.e("FaceAntiSpoof", "Initialization failed: ${e.message}", e)
46
- isInitialized = false
47
- }
48
- }
49
-
50
- override fun callback(frame: Frame, params: Map<String, Any?>?): Any? {
51
- // Return immediately without blocking the VisionCamera thread
52
- // The callback should return quickly to avoid frame drops
53
-
54
- if (!isInitialized) {
55
- return latestResult.get()
56
- }
57
-
58
- // Only process if the previous frame has finished processing
59
- // This prevents accumulating a queue of frames to process
60
- if (!isProcessing.compareAndSet(false, true)) {
61
- // Processing already in flight, return the latest result
62
- return latestResult.get()
63
- }
64
-
65
- // CRITICAL: Copy frame data BEFORE submitting to background thread
66
- // The frame reference becomes invalid after the callback returns
67
- val nv21: ByteArray
68
- val width: Int
69
- val height: Int
70
-
71
- try {
72
- // Extract YUV data immediately while the frame is still valid
73
- val image = frame.getImage() ?: throw Exception("Frame image is null")
74
- val planes = image.planes
75
-
76
- if (planes == null) {
77
- throw Exception("Frame planes are null")
78
- }
79
-
80
- if (planes.size < 3) {
81
- throw Exception("Invalid frame planes: expected 3, got ${planes.size}")
82
- }
83
-
84
- val yBuffer = planes[0]?.buffer ?: throw Exception("Y buffer is null")
85
- val uBuffer = planes[1]?.buffer ?: throw Exception("U buffer is null")
86
- val vBuffer = planes[2]?.buffer ?: throw Exception("V buffer is null")
87
-
88
- // Ensure buffers are accessible
89
- if (!yBuffer.isDirect && !yBuffer.hasArray()) {
90
- throw Exception("Y buffer is not accessible")
91
- }
92
- if (!uBuffer.isDirect && !uBuffer.hasArray()) {
93
- throw Exception("U buffer is not accessible")
94
- }
95
- if (!vBuffer.isDirect && !vBuffer.hasArray()) {
96
- throw Exception("V buffer is not accessible")
97
- }
98
-
99
- yBuffer.rewind()
100
- uBuffer.rewind()
101
- vBuffer.rewind()
102
-
103
- val ySize = yBuffer.remaining()
104
- val uSize = uBuffer.remaining()
105
- val vSize = vBuffer.remaining()
106
-
107
- if (ySize <= 0 || uSize <= 0 || vSize <= 0) {
108
- throw Exception("Invalid buffer sizes: Y=$ySize, U=$uSize, V=$vSize")
109
- }
110
-
111
- nv21 = ByteArray(ySize + uSize + vSize)
112
-
113
- try {
114
- yBuffer.get(nv21, 0, ySize)
115
- vBuffer.get(nv21, ySize, vSize)
116
- uBuffer.get(nv21, ySize + vSize, uSize)
117
- } catch (e: Exception) {
118
- throw Exception("Error copying YUV buffers: ${e.message}", e)
119
- }
120
-
121
- width = frame.getWidth()
122
- height = frame.getHeight()
123
-
124
- if (width <= 0 || height <= 0) {
125
- throw Exception("Invalid frame dimensions: width=$width, height=$height")
126
- }
127
- } catch (e: Exception) {
128
- Log.e("FaceAntiSpoof", "Error extracting frame data: ${e.message}", e)
129
- val errorMap = mapOf(
130
- "error" to e.message,
131
- "isLive" to false,
132
- "label" to "Error: ${e.message}"
133
- )
134
- latestResult.set(errorMap)
135
- isProcessing.set(false)
136
- return latestResult.get()
137
- }
138
-
139
- // Submit the heavy processing to the background thread executor
140
- // Now using the copied nv21 data, not the frame reference
141
- processingExecutor.submit {
142
- try {
143
- val faceAntispoof = faceAntiSpoofing ?: throw Exception("FaceAntiSpoofing not initialized")
144
-
145
- // Process copied NV21 data directly (no Bitmap conversion)
146
- val result = faceAntispoof.advancedAntiSpoofing(nv21, width, height)
147
-
148
- val resultMap = mapOf(
149
- "neuralNetworkScore" to result.neuralNetworkScore.toDouble(),
150
- "laplacianScore" to result.laplacianScore,
151
- "combinedScore" to result.combinedScore.toDouble(),
152
- "confidence" to result.confidence.toDouble()
153
- )
154
-
155
- // Update the latest result for the next callback
156
- latestResult.set(resultMap)
157
- } catch (e: Exception) {
158
- Log.e("FaceAntiSpoof", "Processing error: ${e.message}", e)
159
- val errorMap = mapOf(
160
- "error" to e.message,
161
- "isLive" to false,
162
- "label" to "Error: ${e.message}"
163
- )
164
- latestResult.set(errorMap)
165
- } finally {
166
- // Mark processing as complete for the next frame
167
- isProcessing.set(false)
168
- }
169
- }
170
-
171
- // Return the latest result immediately without waiting
172
- return latestResult.get()
173
- }
174
-
175
- /**
176
- * Cleanup resources when the frame processor is no longer needed
177
- * This should be called when the camera is closed or the app is destroyed
178
- */
179
- fun cleanup() {
180
- try {
181
- // Shutdown the executor and wait for any running tasks to complete
182
- processingExecutor.shutdown()
183
- if (!processingExecutor.awaitTermination(5, java.util.concurrent.TimeUnit.SECONDS)) {
184
- Log.w("FaceAntiSpoof", "Executor did not terminate in time, forcing shutdown")
185
- processingExecutor.shutdownNow()
186
- }
187
-
188
- // Clean up the face anti-spoofing model
189
- faceAntiSpoofing?.close()
190
- faceAntiSpoofing = null
191
- isInitialized = false
192
-
193
- Log.i("FaceAntiSpoof", "Cleanup completed successfully")
194
- } catch (e: Exception) {
195
- Log.e("FaceAntiSpoof", "Error during cleanup: ${e.message}", e)
196
- }
197
- }
198
- }