@blueharford/scrypted-spatial-awareness 0.5.5 → 0.5.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.
package/out/plugin.zip CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blueharford/scrypted-spatial-awareness",
3
- "version": "0.5.5",
3
+ "version": "0.5.7",
4
4
  "description": "Cross-camera object tracking for Scrypted NVR with spatial awareness",
5
5
  "author": "Joshua Seidel <blueharford>",
6
6
  "license": "Apache-2.0",
@@ -84,31 +84,58 @@ export interface ImageData {
84
84
  */
85
85
  export async function mediaObjectToBase64(mediaObject: MediaObject): Promise<ImageData | null> {
86
86
  try {
87
- // Convert MediaObject to Buffer using mediaManager
88
- const buffer = await mediaManager.convertMediaObjectToBuffer(mediaObject, ScryptedMimeTypes.Image);
87
+ console.log(`[Image] Converting MediaObject, mimeType=${mediaObject?.mimeType}`);
88
+
89
+ // First convert to JPEG to ensure consistent format
90
+ const jpegMediaObject = await mediaManager.convertMediaObject(mediaObject, 'image/jpeg') as MediaObject;
91
+ console.log(`[Image] Converted to JPEG MediaObject`);
92
+
93
+ // Get the buffer from the converted media object
94
+ const buffer = await mediaManager.convertMediaObjectToBuffer(jpegMediaObject, 'image/jpeg');
95
+
96
+ // Check if we got an actual Buffer (not a proxy)
97
+ const isRealBuffer = Buffer.isBuffer(buffer);
98
+ const bufferLength = isRealBuffer ? buffer.length : 0;
99
+
100
+ console.log(`[Image] Buffer: isBuffer=${isRealBuffer}, length=${bufferLength}`);
101
+
102
+ if (!isRealBuffer || bufferLength === 0) {
103
+ console.warn('[Image] Did not receive a valid Buffer');
104
+
105
+ // Try alternate approach: get raw data using any type
106
+ try {
107
+ const anyMedia = mediaObject as any;
108
+ if (typeof anyMedia.getData === 'function') {
109
+ const data = await anyMedia.getData();
110
+ if (data && Buffer.isBuffer(data)) {
111
+ console.log(`[Image] Got data from getData(): ${data.length} bytes`);
112
+ if (data.length > 1000) {
113
+ const base64 = data.toString('base64');
114
+ return { base64, mediaType: 'image/jpeg' };
115
+ }
116
+ }
117
+ }
118
+ } catch (dataErr) {
119
+ console.warn('[Image] getData() failed:', dataErr);
120
+ }
89
121
 
90
- if (!buffer || buffer.length === 0) {
91
- console.warn('Failed to convert MediaObject: empty buffer');
92
122
  return null;
93
123
  }
94
124
 
95
- // Convert buffer to base64 (raw, no data URL prefix)
96
- const base64 = buffer.toString('base64');
97
-
98
- // Validate base64 - check it's not empty and looks valid
99
- if (!base64 || base64.length < 100) {
100
- console.warn(`Invalid base64: length=${base64?.length || 0}`);
125
+ // Check if buffer is too small to be a valid image (< 1KB is suspicious)
126
+ if (bufferLength < 1000) {
127
+ console.warn(`[Image] Buffer too small: ${bufferLength} bytes`);
101
128
  return null;
102
129
  }
103
130
 
104
- // Determine MIME type - default to JPEG for camera images
105
- const mediaType = mediaObject.mimeType?.split(';')[0] || 'image/jpeg';
131
+ // Convert buffer to base64 (raw, no data URL prefix)
132
+ const base64 = buffer.toString('base64');
106
133
 
107
- console.log(`[Image] Converted to base64: ${base64.length} chars, type=${mediaType}`);
134
+ console.log(`[Image] Converted to base64: ${base64.length} chars`);
108
135
 
109
- return { base64, mediaType };
136
+ return { base64, mediaType: 'image/jpeg' };
110
137
  } catch (e) {
111
- console.warn('Failed to convert MediaObject to base64:', e);
138
+ console.warn('[Image] Failed to convert MediaObject to base64:', e);
112
139
  return null;
113
140
  }
114
141
  }
@@ -213,11 +213,27 @@ export class TopologyDiscoveryEngine {
213
213
  try {
214
214
  const camera = systemManager.getDeviceById<Camera>(cameraId);
215
215
  if (!camera?.interfaces?.includes(ScryptedInterface.Camera)) {
216
+ this.console.warn(`[Discovery] Camera ${cameraId} doesn't have Camera interface`);
216
217
  return null;
217
218
  }
218
219
 
220
+ this.console.log(`[Discovery] Taking snapshot from camera: ${camera.name || cameraId}`);
219
221
  const mediaObject = await camera.takePicture();
220
- return mediaObjectToBase64(mediaObject);
222
+
223
+ if (!mediaObject) {
224
+ this.console.warn(`[Discovery] takePicture() returned null for ${camera.name}`);
225
+ return null;
226
+ }
227
+
228
+ this.console.log(`[Discovery] MediaObject received: mimeType=${mediaObject.mimeType}`);
229
+
230
+ const imageData = await mediaObjectToBase64(mediaObject);
231
+
232
+ if (!imageData) {
233
+ this.console.warn(`[Discovery] Failed to convert MediaObject to base64 for ${camera.name}`);
234
+ }
235
+
236
+ return imageData;
221
237
  } catch (e) {
222
238
  this.console.warn(`[Discovery] Failed to get snapshot from camera ${cameraId}:`, e);
223
239
  return null;