mirror of
https://github.com/koush/scrypted.git
synced 2026-05-26 14:40:29 +01:00
snapshot: relax some cpu and memory usage
This commit is contained in:
4
plugins/snapshot/package-lock.json
generated
4
plugins/snapshot/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/snapshot",
|
||||
"version": "0.0.16",
|
||||
"version": "0.0.17",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/snapshot",
|
||||
"version": "0.0.16",
|
||||
"version": "0.0.17",
|
||||
"dependencies": {
|
||||
"@koush/axios-digest-auth": "^0.8.5",
|
||||
"@types/node": "^16.6.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/snapshot",
|
||||
"version": "0.0.16",
|
||||
"version": "0.0.17",
|
||||
"description": "Snapshot Plugin for Scrypted",
|
||||
"scripts": {
|
||||
"prepublishOnly": "NODE_ENV=production scrypted-webpack",
|
||||
|
||||
@@ -4,13 +4,15 @@ import { StorageSettings } from "@scrypted/common/src/settings"
|
||||
import AxiosDigestAuth from '@koush/axios-digest-auth';
|
||||
import https from 'https';
|
||||
import axios, { Axios } from "axios";
|
||||
import { TimeoutError, timeoutPromise } from "@scrypted/common/src/promise-utils";
|
||||
import { RefreshPromise, singletonPromise, TimeoutError, timeoutPromise } from "@scrypted/common/src/promise-utils";
|
||||
import { AutoenableMixinProvider } from "@scrypted/common/src/autoenable-mixin-provider";
|
||||
import jimp from 'jimp';
|
||||
|
||||
const { systemManager } = sdk;
|
||||
const { mediaManager, systemManager } = sdk;
|
||||
|
||||
// lol
|
||||
const FOREVER = 24 * 60 * 60 * 1000;
|
||||
|
||||
const { mediaManager } = sdk;
|
||||
const httpsAgent = new https.Agent({
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
@@ -27,8 +29,11 @@ class SnapshotMixin extends SettingsMixinDeviceBase<Camera> implements Camera {
|
||||
title: 'Default Snapshot Channel',
|
||||
description: 'The default channel to use for snapshots.',
|
||||
defaultValue: 'Camera Default',
|
||||
hide: true,
|
||||
hide: !this.mixinDeviceInterfaces.includes(ScryptedInterface.Camera),
|
||||
onGet: async () => {
|
||||
if (!this.mixinDeviceInterfaces.includes(ScryptedInterface.Camera))
|
||||
return {};
|
||||
|
||||
let psos: PictureOptions[];
|
||||
try {
|
||||
psos = await this.mixinDevice.getPictureOptions();
|
||||
@@ -92,10 +97,11 @@ class SnapshotMixin extends SettingsMixinDeviceBase<Camera> implements Camera {
|
||||
});
|
||||
axiosClient: Axios | AxiosDigestAuth;
|
||||
pendingPicture: Promise<Buffer>;
|
||||
// this will contain the last picture retrieved,
|
||||
// or an outdated picture blurred with an error overlay.
|
||||
lastPicture: Buffer;
|
||||
rawLastPicture: Buffer;
|
||||
errorPicture: RefreshPromise<Buffer>;
|
||||
timeoutPicture: RefreshPromise<Buffer>;
|
||||
progressPicture: RefreshPromise<Buffer>;
|
||||
currentPicture: Buffer;
|
||||
lastAvailablePicture: Buffer;
|
||||
|
||||
constructor(options: SettingsMixinDeviceOptions<Camera>) {
|
||||
super(options);
|
||||
@@ -190,17 +196,18 @@ class SnapshotMixin extends SettingsMixinDeviceBase<Camera> implements Camera {
|
||||
try {
|
||||
picture = await takePicture();
|
||||
picture = await this.cropAndScale(picture);
|
||||
this.rawLastPicture = picture;
|
||||
this.clearCachedPictures();
|
||||
this.currentPicture = picture;
|
||||
this.lastAvailablePicture = picture;
|
||||
setTimeout(() => {
|
||||
if (this.currentPicture === picture) {
|
||||
this.clearCachedPictures();
|
||||
}
|
||||
}, 30000);
|
||||
}
|
||||
catch (e) {
|
||||
picture = await this.createErrorImage(e);
|
||||
}
|
||||
this.lastPicture = picture;
|
||||
setTimeout(() => {
|
||||
if (this.lastPicture === picture) {
|
||||
this.lastPicture = undefined;
|
||||
}
|
||||
}, 30000);
|
||||
return picture;
|
||||
})();
|
||||
|
||||
@@ -222,13 +229,13 @@ class SnapshotMixin extends SettingsMixinDeviceBase<Camera> implements Camera {
|
||||
else {
|
||||
try {
|
||||
if (this.storageSettings.values.snapshotMode === 'Never Wait') {
|
||||
if (!this.lastPicture) {
|
||||
if (!this.currentPicture) {
|
||||
// this triggers an event to refresh the web ui.
|
||||
this.pendingPicture.then(() => this.onDeviceEvent(ScryptedInterface.Camera, undefined));
|
||||
data = await this.createErrorImage(new NeverWaitError());
|
||||
}
|
||||
else {
|
||||
data = this.lastPicture;
|
||||
data = this.currentPicture;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -266,16 +273,37 @@ class SnapshotMixin extends SettingsMixinDeviceBase<Camera> implements Camera {
|
||||
return cropped;
|
||||
}
|
||||
|
||||
clearCachedPictures() {
|
||||
this.currentPicture = undefined;
|
||||
this.errorPicture = undefined;
|
||||
this.pendingPicture = undefined;
|
||||
this.timeoutPicture = undefined;
|
||||
}
|
||||
|
||||
async createErrorImage(e: any) {
|
||||
this.console.log('creating error snapshot', e);
|
||||
let text: string;
|
||||
if (e instanceof TimeoutError)
|
||||
text = 'Snapshot Timed Out';
|
||||
else if (e instanceof NeverWaitError)
|
||||
text = 'Snapshot in Progress';
|
||||
else
|
||||
text = 'Snapshot Failed';
|
||||
if (!this.rawLastPicture) {
|
||||
if (e instanceof TimeoutError) {
|
||||
this.timeoutPicture = singletonPromise(this.timeoutPicture,
|
||||
() => this.createTextErrorImage('Snapshot Timed Out'),
|
||||
FOREVER);
|
||||
return this.timeoutPicture.promise;
|
||||
}
|
||||
else if (e instanceof NeverWaitError) {
|
||||
this.progressPicture = singletonPromise(this.timeoutPicture,
|
||||
() => this.createTextErrorImage('Snapshot In Progress'),
|
||||
FOREVER);
|
||||
return this.progressPicture.promise;
|
||||
}
|
||||
else {
|
||||
this.errorPicture = singletonPromise(this.timeoutPicture,
|
||||
() => this.createTextErrorImage('Snapshot Failed'),
|
||||
FOREVER);
|
||||
return this.errorPicture.promise;
|
||||
}
|
||||
}
|
||||
|
||||
async createTextErrorImage(text: string) {
|
||||
if (!this.currentPicture) {
|
||||
const img = await jimp.create(1920 / 2, 1080 / 2);
|
||||
const font = await fontPromise;
|
||||
img.print(font, 0, 0, {
|
||||
@@ -286,7 +314,7 @@ class SnapshotMixin extends SettingsMixinDeviceBase<Camera> implements Camera {
|
||||
return img.getBufferAsync('image/jpeg');
|
||||
}
|
||||
else {
|
||||
const img = await jimp.read(this.rawLastPicture);
|
||||
const img = await jimp.read(this.currentPicture);
|
||||
img.resize(1920 / 2, jimp.AUTO);
|
||||
img.blur(15);
|
||||
img.brightness(-.2);
|
||||
|
||||
Reference in New Issue
Block a user