@arfuhad/react-native-smart-camera 0.1.1 → 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.
Files changed (116) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +259 -206
  3. package/android/build.gradle +15 -33
  4. package/android/src/main/java/com/smartcamera/FaceDetectorFrameProcessorPlugin.kt +324 -0
  5. package/android/src/main/java/com/smartcamera/SmartCameraPackage.kt +28 -0
  6. package/build/detection/blinkProcessor.js +2 -1
  7. package/build/detection/blinkProcessor.js.map +1 -1
  8. package/build/detection/faceDetector.d.ts +4 -4
  9. package/build/detection/faceDetector.d.ts.map +1 -1
  10. package/build/detection/faceDetector.js +31 -11
  11. package/build/detection/faceDetector.js.map +1 -1
  12. package/build/detection/index.d.ts +1 -1
  13. package/build/detection/index.d.ts.map +1 -1
  14. package/build/detection/index.js +1 -1
  15. package/build/detection/index.js.map +1 -1
  16. package/build/detection/staticImageDetector.d.ts +11 -11
  17. package/build/detection/staticImageDetector.d.ts.map +1 -1
  18. package/build/detection/staticImageDetector.js +19 -23
  19. package/build/detection/staticImageDetector.js.map +1 -1
  20. package/build/hooks/index.d.ts +6 -0
  21. package/build/hooks/index.d.ts.map +1 -1
  22. package/build/hooks/index.js +8 -0
  23. package/build/hooks/index.js.map +1 -1
  24. package/build/hooks/useBlinkDetection.d.ts +27 -16
  25. package/build/hooks/useBlinkDetection.d.ts.map +1 -1
  26. package/build/hooks/useBlinkDetection.js +63 -37
  27. package/build/hooks/useBlinkDetection.js.map +1 -1
  28. package/build/hooks/useFaceDetection.js +3 -2
  29. package/build/hooks/useFaceDetection.js.map +1 -1
  30. package/build/hooks/useFaceDetector.d.ts +123 -0
  31. package/build/hooks/useFaceDetector.d.ts.map +1 -0
  32. package/build/hooks/useFaceDetector.js +133 -0
  33. package/build/hooks/useFaceDetector.js.map +1 -0
  34. package/build/hooks/useSmartCamera.js.map +1 -1
  35. package/build/hooks/useSmartCameraWebRTC.d.ts +3 -5
  36. package/build/hooks/useSmartCameraWebRTC.d.ts.map +1 -1
  37. package/build/hooks/useSmartCameraWebRTC.js +19 -87
  38. package/build/hooks/useSmartCameraWebRTC.js.map +1 -1
  39. package/build/hooks/useWebRTC.d.ts +88 -0
  40. package/build/hooks/useWebRTC.d.ts.map +1 -0
  41. package/build/hooks/useWebRTC.js +394 -0
  42. package/build/hooks/useWebRTC.js.map +1 -0
  43. package/build/hooks/useWebRTCWithDetection.d.ts +89 -0
  44. package/build/hooks/useWebRTCWithDetection.d.ts.map +1 -0
  45. package/build/hooks/useWebRTCWithDetection.js +131 -0
  46. package/build/hooks/useWebRTCWithDetection.js.map +1 -0
  47. package/build/index.d.ts +24 -10
  48. package/build/index.d.ts.map +1 -1
  49. package/build/index.js +38 -13
  50. package/build/index.js.map +1 -1
  51. package/build/types.d.ts +28 -12
  52. package/build/types.d.ts.map +1 -1
  53. package/build/types.js.map +1 -1
  54. package/build/utils/index.js.map +1 -1
  55. package/build/webrtc/WebRTCBridge.d.ts +3 -0
  56. package/build/webrtc/WebRTCBridge.d.ts.map +1 -1
  57. package/build/webrtc/WebRTCBridge.js +12 -15
  58. package/build/webrtc/WebRTCBridge.js.map +1 -1
  59. package/build/webrtc/WebRTCManager.d.ts +148 -0
  60. package/build/webrtc/WebRTCManager.d.ts.map +1 -0
  61. package/build/webrtc/WebRTCManager.js +383 -0
  62. package/build/webrtc/WebRTCManager.js.map +1 -0
  63. package/build/webrtc/index.d.ts +3 -1
  64. package/build/webrtc/index.d.ts.map +1 -1
  65. package/build/webrtc/index.js +5 -0
  66. package/build/webrtc/index.js.map +1 -1
  67. package/build/webrtc/types.d.ts +212 -4
  68. package/build/webrtc/types.d.ts.map +1 -1
  69. package/build/webrtc/types.js +34 -1
  70. package/build/webrtc/types.js.map +1 -1
  71. package/ios/FaceDetectorFrameProcessorPlugin.m +11 -0
  72. package/ios/FaceDetectorFrameProcessorPlugin.swift +304 -0
  73. package/package.json +13 -12
  74. package/react-native-smart-camera.podspec +32 -0
  75. package/src/detection/blinkProcessor.ts +127 -0
  76. package/src/detection/faceDetector.ts +78 -0
  77. package/src/detection/index.ts +3 -0
  78. package/src/detection/staticImageDetector.ts +53 -0
  79. package/src/hooks/index.ts +26 -0
  80. package/src/hooks/useBlinkDetection.ts +127 -0
  81. package/src/hooks/useFaceDetection.ts +105 -0
  82. package/src/hooks/useFaceDetector.ts +191 -0
  83. package/src/hooks/useSmartCamera.ts +83 -0
  84. package/src/hooks/useSmartCameraWebRTC.ts +120 -0
  85. package/src/hooks/useWebRTC.ts +453 -0
  86. package/src/hooks/useWebRTCWithDetection.ts +181 -0
  87. package/src/index.ts +170 -0
  88. package/src/types.ts +636 -0
  89. package/src/utils/index.ts +355 -0
  90. package/src/webrtc/WebRTCBridge.ts +127 -0
  91. package/src/webrtc/WebRTCManager.ts +453 -0
  92. package/src/webrtc/index.ts +50 -0
  93. package/src/webrtc/types.ts +361 -0
  94. package/android/src/main/java/expo/modules/smartcamera/ImageLoader.kt +0 -106
  95. package/android/src/main/java/expo/modules/smartcamera/MLKitFaceDetector.kt +0 -273
  96. package/android/src/main/java/expo/modules/smartcamera/SmartCameraModule.kt +0 -205
  97. package/android/src/main/java/expo/modules/smartcamera/SmartCameraView.kt +0 -153
  98. package/android/src/main/java/expo/modules/smartcamera/WebRTCFrameBridge.kt +0 -184
  99. package/build/SmartCamera.d.ts +0 -17
  100. package/build/SmartCamera.d.ts.map +0 -1
  101. package/build/SmartCamera.js +0 -270
  102. package/build/SmartCamera.js.map +0 -1
  103. package/build/SmartCameraModule.d.ts +0 -112
  104. package/build/SmartCameraModule.d.ts.map +0 -1
  105. package/build/SmartCameraModule.js +0 -121
  106. package/build/SmartCameraModule.js.map +0 -1
  107. package/build/SmartCameraView.d.ts +0 -8
  108. package/build/SmartCameraView.d.ts.map +0 -1
  109. package/build/SmartCameraView.js +0 -7
  110. package/build/SmartCameraView.js.map +0 -1
  111. package/expo-module.config.json +0 -9
  112. package/ios/MLKitFaceDetector.swift +0 -310
  113. package/ios/SmartCamera.podspec +0 -33
  114. package/ios/SmartCameraModule.swift +0 -225
  115. package/ios/SmartCameraView.swift +0 -146
  116. package/ios/WebRTCFrameBridge.swift +0 -150
@@ -0,0 +1,361 @@
1
+ /**
2
+ * WebRTC-related types for the SmartCamera module
3
+ */
4
+
5
+ // =============================================================================
6
+ // Core WebRTC Types
7
+ // =============================================================================
8
+
9
+ /**
10
+ * ICE server configuration for STUN/TURN servers
11
+ */
12
+ export interface ICEServer {
13
+ /** STUN/TURN server URLs */
14
+ urls: string | string[];
15
+ /** Username for TURN authentication */
16
+ username?: string;
17
+ /** Credential for TURN authentication */
18
+ credential?: string;
19
+ }
20
+
21
+ /**
22
+ * Peer connection configuration
23
+ */
24
+ export interface PeerConnectionConfig {
25
+ /** ICE servers (STUN/TURN) */
26
+ iceServers?: ICEServer[];
27
+ /** ICE transport policy */
28
+ iceTransportPolicy?: 'all' | 'relay';
29
+ /** Bundle policy */
30
+ bundlePolicy?: 'balanced' | 'max-bundle' | 'max-compat';
31
+ /** RTCP mux policy */
32
+ rtcpMuxPolicy?: 'require';
33
+ }
34
+
35
+ /**
36
+ * Video constraints for getUserMedia
37
+ */
38
+ export interface VideoConstraints {
39
+ /** Frame width in pixels */
40
+ width?: number | { min?: number; ideal?: number; max?: number };
41
+ /** Frame height in pixels */
42
+ height?: number | { min?: number; ideal?: number; max?: number };
43
+ /** Target frame rate */
44
+ frameRate?: number | { min?: number; ideal?: number; max?: number };
45
+ /** Camera facing mode */
46
+ facingMode?: 'user' | 'environment';
47
+ }
48
+
49
+ /**
50
+ * Audio constraints for getUserMedia
51
+ */
52
+ export interface AudioConstraints {
53
+ /** Enable echo cancellation */
54
+ echoCancellation?: boolean;
55
+ /** Enable noise suppression */
56
+ noiseSuppression?: boolean;
57
+ /** Enable auto gain control */
58
+ autoGainControl?: boolean;
59
+ }
60
+
61
+ /**
62
+ * Media stream constraints
63
+ */
64
+ export interface MediaConstraints {
65
+ /** Video constraints (false to disable video) */
66
+ video?: boolean | VideoConstraints;
67
+ /** Audio constraints (false to disable audio) */
68
+ audio?: boolean | AudioConstraints;
69
+ }
70
+
71
+ // =============================================================================
72
+ // Call State Types
73
+ // =============================================================================
74
+
75
+ /**
76
+ * WebRTC call state
77
+ */
78
+ export type CallState =
79
+ | 'idle' // No active call
80
+ | 'connecting' // Call is being established
81
+ | 'connected' // Call is active
82
+ | 'reconnecting'// Connection lost, attempting to reconnect
83
+ | 'disconnected'// Call ended or failed
84
+ | 'failed'; // Call failed to establish
85
+
86
+ /**
87
+ * WebRTC connection state (maps to RTCPeerConnectionState)
88
+ */
89
+ export type WebRTCConnectionState =
90
+ | 'new'
91
+ | 'connecting'
92
+ | 'connected'
93
+ | 'disconnected'
94
+ | 'failed'
95
+ | 'closed';
96
+
97
+ /**
98
+ * ICE connection state
99
+ */
100
+ export type ICEConnectionState =
101
+ | 'new'
102
+ | 'checking'
103
+ | 'connected'
104
+ | 'completed'
105
+ | 'failed'
106
+ | 'disconnected'
107
+ | 'closed';
108
+
109
+ /**
110
+ * ICE gathering state
111
+ */
112
+ export type ICEGatheringState = 'new' | 'gathering' | 'complete';
113
+
114
+ /**
115
+ * Signaling state
116
+ */
117
+ export type SignalingState =
118
+ | 'stable'
119
+ | 'have-local-offer'
120
+ | 'have-remote-offer'
121
+ | 'have-local-pranswer'
122
+ | 'have-remote-pranswer'
123
+ | 'closed';
124
+
125
+ // =============================================================================
126
+ // Stream and Track Types
127
+ // =============================================================================
128
+
129
+ /**
130
+ * Video frame format for WebRTC
131
+ */
132
+ export type VideoFrameFormat = 'I420' | 'NV12' | 'NV21' | 'BGRA';
133
+
134
+ /**
135
+ * Configuration for the WebRTC video source
136
+ */
137
+ export interface WebRTCVideoSourceConfig {
138
+ /** Frame width in pixels */
139
+ width: number;
140
+ /** Frame height in pixels */
141
+ height: number;
142
+ /** Target frame rate */
143
+ frameRate: number;
144
+ /** Video frame format. Default: 'I420' */
145
+ format?: VideoFrameFormat;
146
+ }
147
+
148
+ /**
149
+ * WebRTC stream statistics
150
+ */
151
+ export interface WebRTCStreamStats {
152
+ /** Current frame rate */
153
+ frameRate: number;
154
+ /** Frames sent */
155
+ framesSent: number;
156
+ /** Frames dropped */
157
+ framesDropped: number;
158
+ /** Bytes sent */
159
+ bytesSent: number;
160
+ /** Current bitrate in bps */
161
+ bitrate: number;
162
+ /** Round-trip time in ms */
163
+ rtt?: number;
164
+ /** Packets lost */
165
+ packetsLost?: number;
166
+ /** Jitter in ms */
167
+ jitter?: number;
168
+ }
169
+
170
+ /**
171
+ * WebRTC stream quality settings
172
+ */
173
+ export interface WebRTCQualitySettings {
174
+ /** Maximum bitrate in bps */
175
+ maxBitrate?: number;
176
+ /** Minimum bitrate in bps */
177
+ minBitrate?: number;
178
+ /** Target frame rate */
179
+ targetFrameRate?: number;
180
+ /** Resolution scale (0.0 - 1.0) */
181
+ resolutionScale?: number;
182
+ }
183
+
184
+ // =============================================================================
185
+ // Event Types
186
+ // =============================================================================
187
+
188
+ /**
189
+ * Event emitted when WebRTC stream state changes
190
+ */
191
+ export interface WebRTCStreamEvent {
192
+ type: 'started' | 'stopped' | 'error' | 'stats';
193
+ timestamp: number;
194
+ error?: Error;
195
+ stats?: WebRTCStreamStats;
196
+ }
197
+
198
+ /**
199
+ * ICE candidate event data
200
+ */
201
+ export interface ICECandidateEvent {
202
+ /** The ICE candidate */
203
+ candidate: RTCIceCandidate | null;
204
+ /** SDP mid */
205
+ sdpMid?: string | null;
206
+ /** SDP m-line index */
207
+ sdpMLineIndex?: number | null;
208
+ }
209
+
210
+ /**
211
+ * Session description for signaling
212
+ */
213
+ export interface SessionDescription {
214
+ /** Type of description (offer/answer) */
215
+ type: 'offer' | 'answer';
216
+ /** SDP string */
217
+ sdp: string;
218
+ }
219
+
220
+ // =============================================================================
221
+ // Hook Options and Results
222
+ // =============================================================================
223
+
224
+ /**
225
+ * Options for useWebRTC hook
226
+ */
227
+ export interface UseWebRTCOptions {
228
+ /** Peer connection configuration */
229
+ config?: PeerConnectionConfig;
230
+ /** Media constraints for local stream */
231
+ mediaConstraints?: MediaConstraints;
232
+ /** Initial camera facing mode */
233
+ initialCamera?: 'front' | 'back';
234
+ /** Auto-start local stream when hook mounts */
235
+ autoStartLocalStream?: boolean;
236
+ /** Callback when call state changes */
237
+ onCallStateChange?: (state: CallState) => void;
238
+ /** Callback when connection state changes */
239
+ onConnectionStateChange?: (state: WebRTCConnectionState) => void;
240
+ /** Callback when ICE connection state changes */
241
+ onIceConnectionStateChange?: (state: ICEConnectionState) => void;
242
+ /** Callback when remote stream is received */
243
+ onRemoteStream?: (stream: MediaStream) => void;
244
+ /** Callback when remote stream is removed */
245
+ onRemoteStreamRemoved?: () => void;
246
+ /** Callback when an error occurs */
247
+ onError?: (error: Error) => void;
248
+ }
249
+
250
+ /**
251
+ * Result type for useWebRTC hook
252
+ */
253
+ export interface UseWebRTCResult {
254
+ // Streams
255
+ /** Local media stream (camera + microphone) */
256
+ localStream: MediaStream | null;
257
+ /** Remote media stream from peer */
258
+ remoteStream: MediaStream | null;
259
+
260
+ // State
261
+ /** Current call state */
262
+ callState: CallState;
263
+ /** Whether local audio is enabled */
264
+ isAudioEnabled: boolean;
265
+ /** Whether local video is enabled */
266
+ isVideoEnabled: boolean;
267
+ /** Current camera facing mode */
268
+ currentCamera: 'front' | 'back';
269
+ /** Peer connection instance */
270
+ peerConnection: RTCPeerConnection | null;
271
+
272
+ // Local stream controls
273
+ /** Start local camera/microphone stream */
274
+ startLocalStream: () => Promise<void>;
275
+ /** Stop local stream */
276
+ stopLocalStream: () => void;
277
+ /** Switch between front and back camera */
278
+ switchCamera: () => Promise<void>;
279
+ /** Toggle local audio on/off */
280
+ toggleAudio: () => void;
281
+ /** Toggle local video on/off */
282
+ toggleVideo: () => void;
283
+
284
+ // Peer connection management
285
+ /** Create a new peer connection */
286
+ createPeerConnection: (config?: PeerConnectionConfig) => RTCPeerConnection;
287
+ /** Close the peer connection */
288
+ closePeerConnection: () => void;
289
+
290
+ // Signaling helpers (user integrates with their signaling server)
291
+ /** Create an SDP offer */
292
+ createOffer: () => Promise<SessionDescription>;
293
+ /** Create an SDP answer */
294
+ createAnswer: () => Promise<SessionDescription>;
295
+ /** Set the remote SDP description */
296
+ setRemoteDescription: (description: SessionDescription) => Promise<void>;
297
+ /** Add an ICE candidate from remote peer */
298
+ addIceCandidate: (candidate: RTCIceCandidate) => Promise<void>;
299
+ /** Register callback for ICE candidates to send to remote peer */
300
+ onIceCandidate: (callback: (candidate: ICECandidateEvent) => void) => void;
301
+
302
+ // Cleanup
303
+ /** Clean up all resources */
304
+ cleanup: () => void;
305
+ }
306
+
307
+ /**
308
+ * Options for useWebRTCWithDetection hook
309
+ */
310
+ export interface UseWebRTCWithDetectionOptions extends UseWebRTCOptions {
311
+ /** Face detection options */
312
+ faceDetection?: {
313
+ enabled?: boolean;
314
+ performanceMode?: 'fast' | 'accurate';
315
+ landmarkMode?: 'none' | 'all';
316
+ classificationMode?: 'none' | 'all';
317
+ };
318
+ /** Eye tracking options */
319
+ eyeTracking?: {
320
+ enabled?: boolean;
321
+ eyeClosedThreshold?: number;
322
+ };
323
+ }
324
+
325
+ // =============================================================================
326
+ // Default Configurations
327
+ // =============================================================================
328
+
329
+ /**
330
+ * Default ICE servers (Google STUN servers)
331
+ */
332
+ export const DEFAULT_ICE_SERVERS: ICEServer[] = [
333
+ { urls: 'stun:stun.l.google.com:19302' },
334
+ { urls: 'stun:stun1.l.google.com:19302' },
335
+ ];
336
+
337
+ /**
338
+ * Default peer connection configuration
339
+ */
340
+ export const DEFAULT_PEER_CONNECTION_CONFIG: PeerConnectionConfig = {
341
+ iceServers: DEFAULT_ICE_SERVERS,
342
+ iceTransportPolicy: 'all',
343
+ bundlePolicy: 'balanced',
344
+ };
345
+
346
+ /**
347
+ * Default media constraints
348
+ */
349
+ export const DEFAULT_MEDIA_CONSTRAINTS: MediaConstraints = {
350
+ video: {
351
+ width: { ideal: 1280 },
352
+ height: { ideal: 720 },
353
+ frameRate: { ideal: 30 },
354
+ facingMode: 'user',
355
+ },
356
+ audio: {
357
+ echoCancellation: true,
358
+ noiseSuppression: true,
359
+ autoGainControl: true,
360
+ },
361
+ };
@@ -1,106 +0,0 @@
1
- package expo.modules.smartcamera
2
-
3
- import android.graphics.Bitmap
4
- import android.graphics.BitmapFactory
5
- import android.net.Uri
6
- import android.util.Base64
7
- import android.util.Log
8
- import kotlinx.coroutines.Dispatchers
9
- import kotlinx.coroutines.withContext
10
- import java.io.File
11
- import java.net.URL
12
-
13
- /**
14
- * Utility class for loading images from various sources
15
- */
16
- class ImageLoader {
17
- companion object {
18
- private const val TAG = "ImageLoader"
19
- }
20
-
21
- /**
22
- * Load an image from various sources (suspending function for async loading)
23
- *
24
- * @param source Image source - can be String URI, Map with "uri" key, or resource ID
25
- * @return Bitmap
26
- * @throws IllegalArgumentException if the source is invalid
27
- */
28
- suspend fun loadImage(source: Any): Bitmap = withContext(Dispatchers.IO) {
29
- when (source) {
30
- is String -> loadFromString(source)
31
- is Map<*, *> -> {
32
- val uri = source["uri"] as? String
33
- val base64 = source["base64"] as? String
34
-
35
- when {
36
- uri != null -> loadFromString(uri)
37
- base64 != null -> loadFromBase64(base64)
38
- else -> throw IllegalArgumentException("Invalid image source map - must contain 'uri' or 'base64'")
39
- }
40
- }
41
- is Number -> throw IllegalArgumentException("Loading from resource ID not supported. Use a URI instead.")
42
- else -> throw IllegalArgumentException("Unsupported image source type: ${source::class.java.simpleName}")
43
- }
44
- }
45
-
46
- private fun loadFromString(source: String): Bitmap {
47
- return when {
48
- source.startsWith("data:image") -> {
49
- // Base64 data URI
50
- val base64Data = source.substringAfter("base64,")
51
- loadFromBase64(base64Data)
52
- }
53
- source.startsWith("http://") || source.startsWith("https://") -> {
54
- loadFromUrl(source)
55
- }
56
- source.startsWith("file://") -> {
57
- loadFromFile(source.removePrefix("file://"))
58
- }
59
- else -> {
60
- // Try as file path
61
- loadFromFile(source)
62
- }
63
- }
64
- }
65
-
66
- private fun loadFromBase64(base64: String): Bitmap {
67
- return try {
68
- val decodedBytes = Base64.decode(base64, Base64.DEFAULT)
69
- BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.size)
70
- ?: throw IllegalStateException("Failed to decode base64 image data")
71
- } catch (e: Exception) {
72
- Log.e(TAG, "Failed to decode base64 image", e)
73
- throw IllegalArgumentException("Failed to decode base64 image: ${e.message}", e)
74
- }
75
- }
76
-
77
- private fun loadFromUrl(url: String): Bitmap {
78
- return try {
79
- val connection = URL(url).openConnection()
80
- connection.connectTimeout = 10000
81
- connection.readTimeout = 30000
82
- connection.doInput = true
83
- connection.connect()
84
- val inputStream = connection.getInputStream()
85
- BitmapFactory.decodeStream(inputStream)
86
- ?: throw IllegalStateException("Failed to decode image from URL")
87
- } catch (e: Exception) {
88
- Log.e(TAG, "Failed to load image from URL: $url", e)
89
- throw IllegalArgumentException("Failed to load image from URL: ${e.message}", e)
90
- }
91
- }
92
-
93
- private fun loadFromFile(path: String): Bitmap {
94
- return try {
95
- val file = File(path)
96
- if (!file.exists()) {
97
- throw IllegalArgumentException("File not found: $path")
98
- }
99
- BitmapFactory.decodeFile(path)
100
- ?: throw IllegalStateException("Failed to decode image from file")
101
- } catch (e: Exception) {
102
- Log.e(TAG, "Failed to load image from file: $path", e)
103
- throw IllegalArgumentException("Failed to load image from file: ${e.message}", e)
104
- }
105
- }
106
- }