scrypted-detection-trainer 0.1.8 → 0.1.9

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/dist/plugin.zip CHANGED
Binary file
@@ -1549,8 +1549,13 @@ var __importStar = (this && this.__importStar) || (function () {
1549
1549
  return result;
1550
1550
  };
1551
1551
  })();
1552
+ var __importDefault = (this && this.__importDefault) || function (mod) {
1553
+ return (mod && mod.__esModule) ? mod : { "default": mod };
1554
+ };
1552
1555
  Object.defineProperty(exports, "__esModule", ({ value: true }));
1553
1556
  const sdk_1 = __importStar(__webpack_require__(/*! @scrypted/sdk */ "./node_modules/@scrypted/sdk/dist/src/index.js"));
1557
+ const fs_1 = __importDefault(__webpack_require__(/*! fs */ "fs"));
1558
+ const path_1 = __importDefault(__webpack_require__(/*! path */ "path"));
1554
1559
  const { systemManager, deviceManager, mediaManager } = sdk_1.default;
1555
1560
  // ─── Constants ────────────────────────────────────────────────────────────────
1556
1561
  const LABELS = ['person', 'animal', 'face', 'vehicle', 'plate', 'package', 'discard'];
@@ -1571,10 +1576,14 @@ class DetectionTrainer extends sdk_1.ScryptedDeviceBase {
1571
1576
  this.lastCapture = new Map();
1572
1577
  // Map<captureId, CaptureRecord>
1573
1578
  this.captures = new Map();
1574
- // Map<captureId, jpegBuffer>
1575
- this.images = new Map();
1576
1579
  // Active event listeners
1577
1580
  this.listeners = [];
1581
+ // Use a stable directory inside the plugin's volume
1582
+ this.imgDir = path_1.default.join(process.env.SCRYPTED_PLUGIN_VOLUME || '/tmp', 'detection-trainer-images');
1583
+ try {
1584
+ fs_1.default.mkdirSync(this.imgDir, { recursive: true });
1585
+ }
1586
+ catch { }
1578
1587
  this.loadState();
1579
1588
  this.registerListeners();
1580
1589
  }
@@ -1592,25 +1601,48 @@ class DetectionTrainer extends sdk_1.ScryptedDeviceBase {
1592
1601
  catch (e) {
1593
1602
  this.console.warn('Could not load captures from storage:', e);
1594
1603
  }
1595
- // images are stored as individual items
1604
+ // Clean up any old base64 image entries from previous versions
1596
1605
  for (const [id] of this.captures) {
1597
- const raw = this.storage.getItem(`img:${id}`);
1598
- if (raw)
1599
- this.images.set(id, Buffer.from(raw, 'base64'));
1606
+ try {
1607
+ this.storage.removeItem(`img:${id}`);
1608
+ }
1609
+ catch { }
1600
1610
  }
1601
1611
  }
1602
1612
  saveCaptures() {
1603
- this.storage.setItem('captures', JSON.stringify([...this.captures.values()]));
1613
+ try {
1614
+ this.storage.setItem('captures', JSON.stringify([...this.captures.values()]));
1615
+ }
1616
+ catch (e) {
1617
+ this.console.warn('Could not save captures:', e);
1618
+ }
1619
+ }
1620
+ imgPath(id) {
1621
+ return path_1.default.join(this.imgDir, `${id}.jpg`);
1604
1622
  }
1605
1623
  saveImage(id, buf) {
1606
- this.storage.setItem(`img:${id}`, buf.toString('base64'));
1624
+ try {
1625
+ fs_1.default.writeFileSync(this.imgPath(id), buf);
1626
+ }
1627
+ catch (e) {
1628
+ this.console.warn(`Could not save image ${id}:`, e);
1629
+ }
1630
+ }
1631
+ loadImage(id) {
1632
+ try {
1633
+ const p = this.imgPath(id);
1634
+ if (fs_1.default.existsSync(p))
1635
+ return fs_1.default.readFileSync(p);
1636
+ }
1637
+ catch { }
1638
+ return undefined;
1607
1639
  }
1608
1640
  deleteCapture(id) {
1609
- const old = this.storage.getItem(`img:${id}`);
1610
- if (old)
1611
- this.storage.removeItem(`img:${id}`);
1641
+ try {
1642
+ fs_1.default.unlinkSync(this.imgPath(id));
1643
+ }
1644
+ catch { }
1612
1645
  this.captures.delete(id);
1613
- this.images.delete(id);
1614
1646
  this.saveCaptures();
1615
1647
  }
1616
1648
  // ── Settings ─────────────────────────────────────────────────────────────
@@ -1744,7 +1776,6 @@ class DetectionTrainer extends sdk_1.ScryptedDeviceBase {
1744
1776
  reviewed: false,
1745
1777
  };
1746
1778
  this.captures.set(id, record);
1747
- this.images.set(id, jpeg);
1748
1779
  this.saveImage(id, jpeg);
1749
1780
  this.saveCaptures();
1750
1781
  this.console.log(`Captured ${best.className} (${Math.round((best.score || 0) * 100)}%) from ${cameraName} [${this.captures.size} total]`);
@@ -1755,8 +1786,8 @@ class DetectionTrainer extends sdk_1.ScryptedDeviceBase {
1755
1786
  const path = url.pathname.replace(request.rootPath, '');
1756
1787
  // Serve image
1757
1788
  if (path.startsWith('/img/')) {
1758
- const id = path.slice(5);
1759
- const img = this.images.get(id);
1789
+ const id = path.slice(5).replace(/[^a-zA-Z0-9_\-]/g, ''); // sanitize
1790
+ const img = this.loadImage(id);
1760
1791
  if (!img)
1761
1792
  return response.send('Not found', { code: 404 });
1762
1793
  return response.send(img, { headers: { 'Content-Type': 'image/jpeg', 'Cache-Control': 'max-age=3600' } });
@@ -1827,7 +1858,7 @@ class DetectionTrainer extends sdk_1.ScryptedDeviceBase {
1827
1858
  // Build a simple tarball-like structure as JSON for download
1828
1859
  const dataset = [];
1829
1860
  for (const record of labeled) {
1830
- const img = this.images.get(record.id);
1861
+ const img = this.loadImage(record.id);
1831
1862
  if (!img)
1832
1863
  continue;
1833
1864
  const fname = `${record.id}`;
@@ -2449,6 +2480,17 @@ setInterval(loadPending, 30_000);
2449
2480
  exports["default"] = DetectionTrainer;
2450
2481
 
2451
2482
 
2483
+ /***/ },
2484
+
2485
+ /***/ "fs"
2486
+ /*!*********************!*\
2487
+ !*** external "fs" ***!
2488
+ \*********************/
2489
+ (module) {
2490
+
2491
+ "use strict";
2492
+ module.exports = require("fs");
2493
+
2452
2494
  /***/ },
2453
2495
 
2454
2496
  /***/ "module"
@@ -2460,6 +2502,17 @@ exports["default"] = DetectionTrainer;
2460
2502
  "use strict";
2461
2503
  module.exports = require("module");
2462
2504
 
2505
+ /***/ },
2506
+
2507
+ /***/ "path"
2508
+ /*!***********************!*\
2509
+ !*** external "path" ***!
2510
+ \***********************/
2511
+ (module) {
2512
+
2513
+ "use strict";
2514
+ module.exports = require("path");
2515
+
2463
2516
  /***/ }
2464
2517
 
2465
2518
  /******/ });