scrypted-detection-trainer 0.1.13 → 0.1.14

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": "scrypted-detection-trainer",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Collect and label detections to fine-tune the Scrypted NVR object detection model.",
5
5
  "keywords": [
6
6
  "scrypted-plugin"
package/src/main.ts CHANGED
@@ -292,11 +292,11 @@ class DetectionTrainer extends ScryptedDeviceBase implements Settings, HttpReque
292
292
  const path = url.pathname.replace(request.rootPath, '');
293
293
 
294
294
  // Serve browse event image via getVideoClipThumbnail
295
- if (path === '/api/browse-img') {
296
- const params = new URL(request.url, 'http://localhost').searchParams;
297
- const cameraId = params.get('cameraId')?.replace(/[^a-zA-Z0-9_\-]/g, '');
298
- const thumbnailId = params.get('thumbnailId')?.replace(/[^a-zA-Z0-9_\-:.]/g, '');
299
- if (!cameraId || !thumbnailId) return response.send('Missing params', { code: 400 });
295
+ if (path === '/api/browse-img' && request.body) {
296
+ const rawBody = request.body as any;
297
+ const body = JSON.parse(typeof rawBody === 'string' ? rawBody : Buffer.isBuffer(rawBody) ? rawBody.toString() : String(rawBody));
298
+ const { cameraId, thumbnailId } = body;
299
+ if (!cameraId || thumbnailId === undefined) return response.send('Missing params', { code: 400 });
300
300
  try {
301
301
  const cam = systemManager.getDeviceById(cameraId) as any;
302
302
  const mo = await cam.getVideoClipThumbnail(thumbnailId);
@@ -359,9 +359,10 @@ class DetectionTrainer extends ScryptedDeviceBase implements Settings, HttpReque
359
359
  const startTime = endTime - hours * 3600 * 1000;
360
360
  const clips = await cam.getVideoClips({ startTime, endTime });
361
361
 
362
+ const limit = parseInt(params.get('limit') || '100');
362
363
  const events = (clips || [])
363
364
  .filter((c: any) => c.detectionClasses?.length && c.thumbnailId)
364
- .slice(0, 100)
365
+ .slice(0, limit)
365
366
  .map((c: any) => ({
366
367
  clipId: c.id,
367
368
  thumbnailId: c.thumbnailId,
@@ -641,6 +642,12 @@ class DetectionTrainer extends ScryptedDeviceBase implements Settings, HttpReque
641
642
  <option value="24" selected>Last 24 hours</option>
642
643
  <option value="72">Last 3 days</option>
643
644
  </select>
645
+ <select id="browse-limit" style="padding:8px 12px;background:#222;border:1px solid #444;color:#fff;border-radius:6px;font-size:13px;">
646
+ <option value="50">50 events</option>
647
+ <option value="100" selected>100 events</option>
648
+ <option value="250">250 events</option>
649
+ <option value="500">500 events</option>
650
+ </select>
644
651
  <button class="export-btn" onclick="loadBrowse()" style="padding:8px 16px;">Load Events</button>
645
652
  <span id="browse-status" style="font-size:13px;color:#888;"></span>
646
653
  </div>
@@ -860,6 +867,7 @@ let browseEvents = [];
860
867
  async function loadBrowse() {
861
868
  const cameraId = document.getElementById('browse-camera').value;
862
869
  const hours = document.getElementById('browse-hours').value;
870
+ const limit = document.getElementById('browse-limit').value;
863
871
  const status = document.getElementById('browse-status');
864
872
  const list = document.getElementById('browse-list');
865
873
 
@@ -870,7 +878,7 @@ async function loadBrowse() {
870
878
  browseEvents = [];
871
879
 
872
880
  try {
873
- const res = await fetch(BASE + '/api/browse?cameraId=' + cameraId + '&hours=' + hours);
881
+ const res = await fetch(BASE + '/api/browse?cameraId=' + cameraId + '&hours=' + hours + '&limit=' + limit);
874
882
  const events = await res.json();
875
883
 
876
884
  if (events.error) { status.textContent = 'Error: ' + events.error; return; }
@@ -930,7 +938,11 @@ async function loadBrowse() {
930
938
  }
931
939
 
932
940
  function loadBrowseImage(i, ev) {
933
- fetch(BASE + '/api/browse-img?cameraId=' + ev.cameraId + '&thumbnailId=' + encodeURIComponent(ev.thumbnailId))
941
+ fetch(BASE + '/api/browse-img', {
942
+ method: 'POST',
943
+ headers: { 'Content-Type': 'application/json' },
944
+ body: JSON.stringify({ cameraId: ev.cameraId, thumbnailId: ev.thumbnailId }),
945
+ })
934
946
  .then(r => r.ok ? r.blob() : null)
935
947
  .then(blob => {
936
948
  if (!blob) return;