edge-impulse-linux 1.20.1 → 1.21.0

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 (30) hide show
  1. package/build/cli/linux/linux.js +1 -0
  2. package/build/cli/linux/linux.js.map +1 -1
  3. package/build/cli/linux/runner.js +14 -4
  4. package/build/cli/linux/runner.js.map +1 -1
  5. package/build/library/classifier/image-classifier.d.ts +2 -0
  6. package/build/library/classifier/image-classifier.js +84 -54
  7. package/build/library/classifier/image-classifier.js.map +1 -1
  8. package/build/library/data-forwarder.d.ts +1 -1
  9. package/build/library/data-forwarder.js +17 -33
  10. package/build/library/data-forwarder.js.map +1 -1
  11. package/build/library/sensors/gstreamer.d.ts +6 -3
  12. package/build/library/sensors/gstreamer.js +156 -30
  13. package/build/library/sensors/gstreamer.js.map +1 -1
  14. package/build/library/sensors/icamera.d.ts +30 -1
  15. package/build/library/sensors/imagesnap.d.ts +2 -2
  16. package/build/library/sensors/imagesnap.js +8 -2
  17. package/build/library/sensors/imagesnap.js.map +1 -1
  18. package/build/library/sensors/prophesee.d.ts +2 -2
  19. package/build/library/sensors/prophesee.js +6 -1
  20. package/build/library/sensors/prophesee.js.map +1 -1
  21. package/build/library/sensors/sensors-helper.d.ts +2 -0
  22. package/build/library/sensors/sensors-helper.js +2 -2
  23. package/build/library/sensors/sensors-helper.js.map +1 -1
  24. package/build/sdk/studio/sdk/model/models.js +10 -17
  25. package/build/sdk/studio/sdk/model/models.js.map +1 -1
  26. package/package.json +1 -1
  27. package/test/gstreamer.test.ts +456 -5
  28. package/test/qualcomm-rb3-gen-2-ubuntu-no-external-camera-inspect-qtiqmmfsrc.txt +438 -0
  29. package/test/qualcomm-rb3-gen-2-ubuntu-no-external-camera-inspect.txt +958 -0
  30. package/test/qualcomm-rb3-gen-2-ubuntu-no-external-camera-monitor.txt +159 -0
@@ -5,12 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DataForwarder = void 0;
7
7
  const crypto_1 = __importDefault(require("crypto"));
8
- const request_1 = __importDefault(require("request"));
9
- const http_1 = __importDefault(require("http"));
10
- const https_1 = __importDefault(require("https"));
8
+ const undici_1 = require("undici");
11
9
  const encoding_1 = __importDefault(require("../shared/encoding"));
12
- const keepAliveAgentHttp = new http_1.default.Agent({ keepAlive: true });
13
- const keepAliveAgentHttps = new https_1.default.Agent({ keepAlive: true });
14
10
  class DataForwarder {
15
11
  constructor(options) {
16
12
  this._samples = [];
@@ -20,7 +16,7 @@ class DataForwarder {
20
16
  sensors: options.sensors,
21
17
  apiKey: options.apiKey || '',
22
18
  hmacKey: options.hmacKey || '0',
23
- intervalMs: options.intervalMs || (1000 / (options.frequency || 1)),
19
+ intervalMs: options.intervalMs || 1000 / (options.frequency || 1),
24
20
  ingestionHost: options.host || 'edgeimpulse.com'
25
21
  };
26
22
  if (typeof options.frequency === 'undefined' && typeof options.intervalMs === 'undefined') {
@@ -60,8 +56,7 @@ class DataForwarder {
60
56
  }
61
57
  addData(data) {
62
58
  if (data.length !== this._options.sensors.length) {
63
- throw new Error('Invalid data, expected ' + this._options.sensors.length + ' values, but got: ' +
64
- data.length);
59
+ throw new Error('Invalid data, expected ' + this._options.sensors.length + ' values, but got: ' + data.length);
65
60
  }
66
61
  this._samples.push(data);
67
62
  }
@@ -69,8 +64,8 @@ class DataForwarder {
69
64
  let emptySignature = Array(64).fill('0').join('');
70
65
  let data = {
71
66
  protected: {
72
- ver: "v1",
73
- alg: "HS256",
67
+ ver: 'v1',
68
+ alg: 'HS256',
74
69
  iat: Math.floor(Date.now() / 1000) // epoch time, seconds since 1970
75
70
  },
76
71
  signature: emptySignature,
@@ -101,7 +96,7 @@ class DataForwarder {
101
96
  'x-api-key': this._options.apiKey,
102
97
  'x-file-name': (0, encoding_1.default)(opts.filename),
103
98
  'Content-Type': 'application/json',
104
- 'Connection': 'keep-alive'
99
+ Connection: 'keep-alive'
105
100
  };
106
101
  if (opts.label) {
107
102
  headers['x-label'] = (0, encoding_1.default)(opts.label);
@@ -109,29 +104,18 @@ class DataForwarder {
109
104
  if (opts.allowDuplicates !== true) {
110
105
  headers['x-disallow-duplicates'] = '1';
111
106
  }
112
- return new Promise((res, rej) => {
113
- let agent = this._options.ingestionHost.indexOf('https:') === 0 ?
114
- keepAliveAgentHttps :
115
- keepAliveAgentHttp;
116
- let category = opts.category;
117
- // now upload the buffer to Edge Impulse
118
- request_1.default.post(this._options.ingestionHost + '/api/' + category + '/data', {
119
- headers: headers,
120
- body: dataBuffer,
121
- encoding: null,
122
- agent: agent
123
- }, (err, response, body) => {
124
- if (err)
125
- return rej(err);
126
- if (response.statusCode !== 200) {
127
- if (body instanceof Buffer) {
128
- return rej(body.toString('utf-8'));
129
- }
130
- return rej(body || response.statusCode.toString());
131
- }
132
- res(body instanceof Buffer ? body.toString('utf-8') : body);
133
- });
107
+ const category = opts.category;
108
+ const url = this._options.ingestionHost + '/api/' + category + '/data';
109
+ const response = await (0, undici_1.fetch)(url, {
110
+ method: 'POST',
111
+ headers: headers,
112
+ body: dataBuffer
134
113
  });
114
+ const body = await response.text();
115
+ if (response.status !== 200) {
116
+ throw body || response.status.toString();
117
+ }
118
+ return body;
135
119
  }
136
120
  }
137
121
  exports.DataForwarder = DataForwarder;
@@ -1 +1 @@
1
- {"version":3,"file":"data-forwarder.js","sourceRoot":"","sources":["../../library/data-forwarder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-forwarder.js","sourceRoot":"","sources":["../../library/data-forwarder.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  /// <reference types="node" />
3
3
  import { EventEmitter } from 'tsee';
4
4
  import { SpawnHelperType } from './spawn-helper';
5
- import { ICamera, ICameraInferenceDimensions, ICameraProfilingInfoEvent, ICameraStartOptions } from './icamera';
5
+ import { ICamera, ICameraInferenceDimensions, ICameraProfilingInfoEvent, ICameraSnapshotForInferenceEvent, ICameraStartOptions } from './icamera';
6
6
  type GStreamerCap = {
7
7
  type: 'video/x-raw' | 'image/jpeg' | 'nvarguscamerasrc' | 'pylonsrc';
8
8
  width: number;
@@ -13,14 +13,14 @@ type GStreamerCap = {
13
13
  export type GStreamerMode = 'default' | 'rpi' | 'rpi5' | 'qualcomm-rb3gen2' | 'qualcomm-yupik' | 'unoq';
14
14
  export declare class GStreamer extends EventEmitter<{
15
15
  snapshot: (buffer: Buffer, filename: string) => void;
16
- snapshotForInference: (buffer: Buffer, filename: string) => void;
16
+ snapshotForInference: (ev: ICameraSnapshotForInferenceEvent) => void;
17
17
  error: (message: string) => void;
18
18
  profilingInfo: (ev: ICameraProfilingInfoEvent) => void;
19
19
  }> implements ICamera {
20
20
  private _captureProcess?;
21
21
  private _tempDir?;
22
22
  private _watcher?;
23
- private _originalFilesSeen;
23
+ private _originalAndRgbFilesSeen;
24
24
  private _handledFiles;
25
25
  private _verbose;
26
26
  private _lastFile;
@@ -35,8 +35,10 @@ export declare class GStreamer extends EventEmitter<{
35
35
  private _customLaunchCommand;
36
36
  private _profiling;
37
37
  private _emitsOriginalSizeImages;
38
+ private _emitsRgbBuffers;
38
39
  private _overrideColorFormat;
39
40
  private _lastGstLaunchCommand;
41
+ private _outputRgbBuffers;
40
42
  private _imagesReceived;
41
43
  private _offset;
42
44
  constructor(verbose: boolean, options?: {
@@ -46,6 +48,7 @@ export declare class GStreamer extends EventEmitter<{
46
48
  profiling?: boolean;
47
49
  dontRunCleanupLoop?: boolean;
48
50
  colorFormat?: string;
51
+ dontOutputRgbBuffers?: boolean;
49
52
  });
50
53
  init(): Promise<void>;
51
54
  listDevices(): Promise<string[]>;
@@ -20,13 +20,14 @@ const DEFAULT_GST_VIDEO_SOURCE = 'v4l2src';
20
20
  class GStreamer extends tsee_1.EventEmitter {
21
21
  constructor(verbose, options) {
22
22
  super();
23
- this._originalFilesSeen = new Set();
23
+ this._originalAndRgbFilesSeen = new Set();
24
24
  this._handledFiles = {};
25
25
  this._processing = false;
26
26
  this._mode = 'default';
27
27
  this._isStarted = false;
28
28
  this._isRestarting = false;
29
29
  this._emitsOriginalSizeImages = false;
30
+ this._emitsRgbBuffers = false;
30
31
  this._lastGstLaunchCommand = '';
31
32
  this._imagesReceived = 0;
32
33
  this._offset = 0;
@@ -36,6 +37,9 @@ class GStreamer extends tsee_1.EventEmitter {
36
37
  this._modeOverride = options?.modeOverride;
37
38
  this._profiling = options?.profiling || false;
38
39
  this._overrideColorFormat = options?.colorFormat;
40
+ this._outputRgbBuffers = options?.dontOutputRgbBuffers === true ?
41
+ false :
42
+ true;
39
43
  if (options?.dontRunCleanupLoop === true) {
40
44
  // skip cleanup loop
41
45
  }
@@ -253,16 +257,20 @@ class GStreamer extends tsee_1.EventEmitter {
253
257
  }
254
258
  let lastPhoto = 0;
255
259
  let nextFrame = Date.now();
256
- this._originalFilesSeen = new Set();
260
+ this._originalAndRgbFilesSeen = new Set();
257
261
  this._watcher = fs_1.default.watch(this._tempDir, async (eventType, fileName) => {
258
262
  if (eventType !== 'rename')
259
263
  return;
260
264
  if (fileName === null)
261
265
  return;
262
- if (!(fileName.endsWith('.jpeg') || fileName.endsWith('.jpg')))
266
+ if (!(fileName.endsWith('.jpeg') || fileName.endsWith('.jpg') || fileName.endsWith('.rgb')))
263
267
  return;
264
268
  if (fileName.startsWith('original')) {
265
- this._originalFilesSeen.add(fileName);
269
+ this._originalAndRgbFilesSeen.add(fileName);
270
+ return;
271
+ }
272
+ if (fileName.endsWith('.rgb')) {
273
+ this._originalAndRgbFilesSeen.add(fileName);
266
274
  return;
267
275
  }
268
276
  if (!this._tempDir)
@@ -270,10 +278,11 @@ class GStreamer extends tsee_1.EventEmitter {
270
278
  if (this._handledFiles[fileName])
271
279
  return;
272
280
  this._imagesReceived++;
281
+ const tempDir = this._tempDir; // this can get unset later on -> so cache here
273
282
  // not next frame yet?
274
283
  if (this._processing || Date.now() < nextFrame) {
275
284
  this._handledFiles[fileName] = true;
276
- await this.safeUnlinkFile(path_1.default.join(this._tempDir, fileName));
285
+ await this.safeUnlinkFile(path_1.default.join(tempDir, fileName));
277
286
  return;
278
287
  }
279
288
  nextFrame = Date.now() + options.intervalMs;
@@ -282,7 +291,7 @@ class GStreamer extends tsee_1.EventEmitter {
282
291
  this._handledFiles[fileName] = true;
283
292
  const originalName = fileName.replace('resized', 'original');
284
293
  if (this._emitsOriginalSizeImages) {
285
- if (!this._originalFilesSeen.has(originalName)) {
294
+ if (!this._originalAndRgbFilesSeen.has(originalName)) {
286
295
  let waitForOriginalStart = Date.now();
287
296
  if (this._verbose) {
288
297
  console.log(PREFIX, `Waiting for original file "${originalName}"...`);
@@ -290,13 +299,13 @@ class GStreamer extends tsee_1.EventEmitter {
290
299
  await new Promise(async (resolve, reject) => {
291
300
  let start = Date.now();
292
301
  while (1) {
293
- if (this._originalFilesSeen.has(originalName)) {
302
+ if (this._originalAndRgbFilesSeen.has(originalName)) {
294
303
  return resolve();
295
304
  }
296
305
  if (Date.now() - start > 1000) {
297
306
  return reject(`Did not find original image ("${originalName}") within 1sec`);
298
307
  }
299
- await this.wait(10);
308
+ await this.wait(1);
300
309
  }
301
310
  });
302
311
  if (this._verbose) {
@@ -305,19 +314,46 @@ class GStreamer extends tsee_1.EventEmitter {
305
314
  }
306
315
  }
307
316
  }
317
+ const rgbName = fileName.replace('.jpg', '.rgb');
318
+ if (this._emitsRgbBuffers) {
319
+ if (!this._originalAndRgbFilesSeen.has(rgbName)) {
320
+ let waitForRgbStart = Date.now();
321
+ if (this._verbose) {
322
+ console.log(PREFIX, `Waiting for RGB file "${rgbName}"...`);
323
+ }
324
+ await new Promise(async (resolve, reject) => {
325
+ let start = Date.now();
326
+ while (1) {
327
+ if (this._originalAndRgbFilesSeen.has(rgbName)) {
328
+ return resolve();
329
+ }
330
+ if (Date.now() - start > 1000) {
331
+ return reject(`Did not find RGB image ("${rgbName}") within 1sec`);
332
+ }
333
+ await this.wait(1);
334
+ }
335
+ });
336
+ if (this._verbose) {
337
+ console.log(PREFIX, `Waiting for RGB file "${rgbName}" OK ` +
338
+ `(took ${Date.now() - waitForRgbStart}ms.)`);
339
+ }
340
+ }
341
+ }
308
342
  if (lastPhoto !== 0 && this._verbose) {
309
343
  console.log(PREFIX, 'Got snapshot', fileName, 'time since last:', (Date.now() - lastPhoto) + 'ms.', 'size');
310
344
  }
311
345
  if (this._keepAliveTimeout) {
312
346
  clearTimeout(this._keepAliveTimeout);
313
347
  }
314
- const tempDir = this._tempDir;
315
348
  try {
316
- let [imgBuffer, originalImgBuffer] = await Promise.all([
349
+ let [imgBuffer, originalImgBuffer, rgbBuffer,] = await Promise.all([
317
350
  fs_1.default.promises.readFile(path_1.default.join(tempDir, fileName)),
318
351
  this._emitsOriginalSizeImages ?
319
352
  fs_1.default.promises.readFile(path_1.default.join(tempDir, originalName)) :
320
353
  null,
354
+ this._emitsRgbBuffers ?
355
+ fs_1.default.promises.readFile(path_1.default.join(tempDir, rgbName)) :
356
+ null,
321
357
  ]);
322
358
  // hash not changed? don't emit another event (streamer does this on Rpi)
323
359
  let hash = crypto_1.default.createHash('sha256').update(imgBuffer).digest('hex');
@@ -325,7 +361,12 @@ class GStreamer extends tsee_1.EventEmitter {
325
361
  // snapshot() sends out the original size image
326
362
  this.emit('snapshot', originalImgBuffer || imgBuffer, path_1.default.basename(fileName));
327
363
  // snapshotForInference() sends out the resized image
328
- this.emit('snapshotForInference', imgBuffer, path_1.default.basename(fileName));
364
+ this.emit('snapshotForInference', {
365
+ imageForInferenceJpg: imgBuffer,
366
+ filename: path_1.default.basename(fileName),
367
+ imageFromCameraJpg: originalImgBuffer || imgBuffer,
368
+ imageForInferenceRgb: rgbBuffer || undefined,
369
+ });
329
370
  lastPhoto = Date.now();
330
371
  // 2 seconds no new data? trigger timeout
331
372
  if (this._keepAliveTimeout) {
@@ -354,7 +395,13 @@ class GStreamer extends tsee_1.EventEmitter {
354
395
  (async () => {
355
396
  if (originalName) {
356
397
  await this.safeUnlinkFile(path_1.default.join(tempDir, originalName));
357
- this._originalFilesSeen.delete(originalName);
398
+ this._originalAndRgbFilesSeen.delete(originalName);
399
+ }
400
+ })(),
401
+ (async () => {
402
+ if (rgbName) {
403
+ await this.safeUnlinkFile(path_1.default.join(tempDir, rgbName));
404
+ this._originalAndRgbFilesSeen.delete(rgbName);
358
405
  }
359
406
  })(),
360
407
  ]);
@@ -389,9 +436,25 @@ class GStreamer extends tsee_1.EventEmitter {
389
436
  return;
390
437
  }
391
438
  else {
439
+ const errMsg = `GStreamer (gst-launch-1.0) stopped before emitting any images. This most likely ` +
440
+ `means that the launch command is incorrect or that your camera is unresponsive. Here is the launch command:\n\n` +
441
+ `${this._lastGstLaunchCommand}\n\n` +
442
+ `You can try one of the following:\n\n` +
443
+ `* If your camera used to work:\n` +
444
+ ` * Disconnect and reconnect the camera (if you use an external camera)\n` +
445
+ ` * Kill all other GStreamer commands, via: 'sudo killall gst-launch-1.0'\n` +
446
+ `* Run with '--verbose' to see the raw GStreamer output. It might contain a hint why the process fails.\n` +
447
+ `* Run with '--dont-output-rgb-buffers' - this will disable RGB output buffer creation which can help with ` +
448
+ `targets that advertise RGB capabilities on the video source, but don't actually support this.\n\n` +
449
+ `If this does not resolve your issue, then please open a forum post at https://forum.edgeimpulse.com and include:\n\n` +
450
+ `* Your device, operating system, what camera you're using, and how the camera is connected (e.g. USB, CSI)\n` +
451
+ `* The launch command (above)\n` +
452
+ `* The verbose output (run this application with --verbose)\n` +
453
+ `* The output of 'gst-device-monitor-1.0'\n` +
454
+ `* The output of 'gst-inspect-1.0'`;
392
455
  if (this._imagesReceived === 0 && this._lastGstLaunchCommand) {
393
456
  reject(`Capture process failed with code ${code}\n\n` +
394
- `command: ${this._lastGstLaunchCommand}`);
457
+ `${errMsg}`);
395
458
  }
396
459
  else {
397
460
  reject('Capture process failed with code ' + code);
@@ -442,6 +505,7 @@ class GStreamer extends tsee_1.EventEmitter {
442
505
  }
443
506
  async getGstreamerLaunchCommand(device, dimensions, inferenceDims) {
444
507
  this._emitsOriginalSizeImages = false;
508
+ this._emitsRgbBuffers = false;
445
509
  if (device.id === CUSTOM_GST_LAUNCH_COMMAND) {
446
510
  if (!this._customLaunchCommand) {
447
511
  throw new Error('_customLaunchCommand is null');
@@ -524,6 +588,24 @@ class GStreamer extends tsee_1.EventEmitter {
524
588
  'pylonsrc',
525
589
  ];
526
590
  }
591
+ const frameReadyArgs = this._profiling ? [`!`, `identity name=frame_ready silent=false`] : [];
592
+ const jpgencDoneArgs = this._profiling ? [`!`, `identity name=jpegenc_done silent=false`] : [];
593
+ const resizeDoneArgs = this._profiling ? [`!`, `identity name=resize_done silent=false`] : [];
594
+ let teeToBothResizedJpgAndRgb;
595
+ let videoFormat = '';
596
+ if (this._outputRgbBuffers) {
597
+ teeToBothResizedJpgAndRgb = [
598
+ `tee name=u`,
599
+ `u. ! queue ! jpegenc ${jpgencDoneArgs.join(' ')} ! multifilesink location=resized%05d.jpg post-messages=true sync=false `,
600
+ `u. ! queue ! multifilesink location=resized%05d.rgb post-messages=true sync=false `,
601
+ ];
602
+ videoFormat = ',format=RGB'; // Don't do this if outputRgbBuffers is RGB, because we don't want to force RGB video format
603
+ }
604
+ else {
605
+ teeToBothResizedJpgAndRgb = [
606
+ `jpegenc ${jpgencDoneArgs.join(' ')} ! multifilesink location=resized%05d.jpg post-messages=true sync=false`,
607
+ ];
608
+ }
527
609
  let cropArgs = [];
528
610
  if (inferenceDims) {
529
611
  // fast path for fit-shortest and squash
@@ -535,14 +617,14 @@ class GStreamer extends tsee_1.EventEmitter {
535
617
  `!`,
536
618
  `videoscale`, `method=lanczos`,
537
619
  `!`,
538
- `video/x-raw,width=${inferenceDims.width},height=${inferenceDims.height}`,
620
+ `video/x-raw${videoFormat},width=${inferenceDims.width},height=${inferenceDims.height}`,
539
621
  ]);
540
622
  }
541
- else if (inferenceDims.resizeMode === 'squash' || inferenceDims.resizeMode === 'none' /* old model */) {
623
+ else if (inferenceDims.resizeMode === 'squash' || inferenceDims.resizeMode === 'none' /* old model -> squash */) {
542
624
  cropArgs.push(`!`);
543
625
  cropArgs.push(`videoscale`, `method=lanczos`);
544
626
  cropArgs.push(`!`);
545
- cropArgs.push(`video/x-raw,width=${inferenceDims.width},height=${inferenceDims.height}`);
627
+ cropArgs.push(`video/x-raw${videoFormat},width=${inferenceDims.width},height=${inferenceDims.height}`);
546
628
  }
547
629
  }
548
630
  let args;
@@ -553,6 +635,12 @@ class GStreamer extends tsee_1.EventEmitter {
553
635
  `video/x-raw,width=${cap.width},height=${cap.height},format=YUY2`
554
636
  ]);
555
637
  }
638
+ else if (device.videoSource === 'qtiqmmfsrc') {
639
+ videoSource = videoSource.concat([
640
+ `!`,
641
+ `video/x-raw,width=${cap.width},height=${cap.height},format=NV12`
642
+ ]);
643
+ }
556
644
  else if (this._mode === 'rpi5') {
557
645
  // on RPi 5 we need to set color format
558
646
  let colorFormat = '';
@@ -576,8 +664,6 @@ class GStreamer extends tsee_1.EventEmitter {
576
664
  `video/x-raw,width=${cap.width},height=${cap.height}`
577
665
  ]);
578
666
  }
579
- let frameReadyArgs = this._profiling ? [`!`, `identity name=frame_ready silent=false`] : [];
580
- let jpgencDoneArgs = this._profiling ? [`!`, `identity name=jpegenc_done silent=false`] : [];
581
667
  if (cropArgs.length === 0) {
582
668
  args = videoSource.concat([
583
669
  ...frameReadyArgs,
@@ -595,11 +681,9 @@ class GStreamer extends tsee_1.EventEmitter {
595
681
  let resized = [
596
682
  `t. ! queue`,
597
683
  ...cropArgs,
684
+ ...resizeDoneArgs,
598
685
  `!`,
599
- `jpegenc`,
600
- ...jpgencDoneArgs,
601
- `!`,
602
- `multifilesink location=resized%05d.jpg post-messages=true sync=false`,
686
+ ...teeToBothResizedJpgAndRgb,
603
687
  ];
604
688
  args = videoSource.concat([
605
689
  ...frameReadyArgs,
@@ -611,15 +695,51 @@ class GStreamer extends tsee_1.EventEmitter {
611
695
  ...resized,
612
696
  ]);
613
697
  this._emitsOriginalSizeImages = true;
698
+ if (this._outputRgbBuffers) {
699
+ this._emitsRgbBuffers = true;
700
+ }
614
701
  }
615
702
  }
616
703
  else if (cap.type === 'image/jpeg') {
617
- args = videoSource.concat([
704
+ videoSource = videoSource.concat([
618
705
  `!`,
619
706
  `image/jpeg,width=${cap.width},height=${cap.height}`,
620
- `!`,
621
- `multifilesink location=resized%05d.jpg post-messages=true sync=false`
622
707
  ]);
708
+ if (cropArgs.length === 0) {
709
+ args = videoSource.concat([
710
+ ...frameReadyArgs,
711
+ `!`,
712
+ `multifilesink`,
713
+ `location=resized%05d.jpg`,
714
+ `post-messages=true`,
715
+ `sync=false`,
716
+ ]);
717
+ }
718
+ else {
719
+ let original = `t. ! queue ! multifilesink location=original%05d.jpg post-messages=true sync=false`;
720
+ let resized = [
721
+ `t. ! queue`,
722
+ `!`,
723
+ `jpegdec`,
724
+ `!`,
725
+ `videoconvert`,
726
+ ...cropArgs,
727
+ ...resizeDoneArgs,
728
+ `!`,
729
+ ...teeToBothResizedJpgAndRgb,
730
+ ];
731
+ args = videoSource.concat([
732
+ ...frameReadyArgs,
733
+ `!`,
734
+ `tee name=t`,
735
+ original,
736
+ ...resized,
737
+ ]);
738
+ this._emitsOriginalSizeImages = true;
739
+ if (this._outputRgbBuffers) {
740
+ this._emitsRgbBuffers = true;
741
+ }
742
+ }
623
743
  }
624
744
  else if (cap.type === 'nvarguscamerasrc') {
625
745
  args = [
@@ -633,7 +753,8 @@ class GStreamer extends tsee_1.EventEmitter {
633
753
  }
634
754
  return {
635
755
  command: 'gst-launch-1.0',
636
- pipeline: args.join(' '),
756
+ // replace multiple spaces with one space
757
+ pipeline: args.join(' ').trim().replace(/(\s+)/g, ' '),
637
758
  };
638
759
  }
639
760
  async stop() {
@@ -645,7 +766,10 @@ class GStreamer extends tsee_1.EventEmitter {
645
766
  this._captureProcess.on('close', code => {
646
767
  if (this._watcher) {
647
768
  this._watcher.on('close', async () => {
648
- await this.cleanupTempDirAsync();
769
+ try {
770
+ await this.cleanupTempDirAsync();
771
+ }
772
+ catch (ex) { /* noop */ }
649
773
  });
650
774
  this._watcher.close();
651
775
  }
@@ -1317,6 +1441,8 @@ class GStreamer extends tsee_1.EventEmitter {
1317
1441
  const cropTop = Math.max(0, Math.floor((srcH - cropH) / 2));
1318
1442
  const cropBottom = Math.max(0, srcH - cropH - cropTop);
1319
1443
  return {
1444
+ width: cropW,
1445
+ height: cropH,
1320
1446
  left: cropLeft,
1321
1447
  right: cropRight,
1322
1448
  top: cropTop,
@@ -1341,7 +1467,7 @@ class GStreamer extends tsee_1.EventEmitter {
1341
1467
  }
1342
1468
  let filesToUnlink = [];
1343
1469
  // copy as we're manipulating this set
1344
- for (let originalFileName of Array.from(this._originalFilesSeen)) {
1470
+ for (let originalFileName of Array.from(this._originalAndRgbFilesSeen)) {
1345
1471
  let originalNumberMatch = originalFileName.match(/(\d+)/);
1346
1472
  let originalNumber = originalNumberMatch ? Number(originalNumberMatch[1]) : NaN;
1347
1473
  if (isNaN(originalNumber)) {
@@ -1356,13 +1482,13 @@ class GStreamer extends tsee_1.EventEmitter {
1356
1482
  filesToUnlink.push(originalFileName);
1357
1483
  }
1358
1484
  if (this._verbose) {
1359
- console.log(PREFIX, `Unlinking ${filesToUnlink.length} original files...`);
1485
+ console.log(PREFIX, `Unlinking ${filesToUnlink.length} original / RGB files...`);
1360
1486
  }
1361
1487
  if (filesToUnlink.length > 0) {
1362
1488
  const tempDir = this._tempDir;
1363
1489
  await (0, async_pool_1.asyncPool)(10, filesToUnlink, async (originalFileName) => {
1364
1490
  await this.safeUnlinkFile(path_1.default.join(tempDir, originalFileName));
1365
- this._originalFilesSeen.delete(originalFileName);
1491
+ this._originalAndRgbFilesSeen.delete(originalFileName);
1366
1492
  });
1367
1493
  }
1368
1494
  }