mirror of
https://github.com/koush/scrypted.git
synced 2026-06-20 16:40:30 +01:00
Merge branch 'main' of github.com:koush/scrypted
This commit is contained in:
@@ -88,7 +88,10 @@ class CastDevice extends ScryptedDeviceBase implements MediaPlayer, Refresh, Eng
|
||||
}
|
||||
|
||||
client.removeAllListeners();
|
||||
client.close();
|
||||
try {
|
||||
client.close();
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
client.client.on('close', cleanup);
|
||||
client.on('error', err => {
|
||||
@@ -149,6 +152,14 @@ class CastDevice extends ScryptedDeviceBase implements MediaPlayer, Refresh, Eng
|
||||
}
|
||||
|
||||
async load(media: string | MediaObject, options: MediaPlayerOptions) {
|
||||
if (this.mediaPlayerPromise) {
|
||||
try {
|
||||
(await this.mediaPlayerPromise).close();
|
||||
} catch (e) {
|
||||
}
|
||||
this.mediaPlayerPromise = undefined;
|
||||
this.mediaPlayerStatus = undefined;
|
||||
}
|
||||
let url: string;
|
||||
let urlMimeType: string;
|
||||
|
||||
@@ -341,15 +352,7 @@ class CastDevice extends ScryptedDeviceBase implements MediaPlayer, Refresh, Eng
|
||||
});
|
||||
})
|
||||
|
||||
player.getStatus((err, status) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
this.mediaPlayerStatus = status;
|
||||
this.updateState();
|
||||
resolve(player);
|
||||
})
|
||||
resolve(player);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,7 +29,7 @@ class ChromecastViewCameraExample implements StartStop {
|
||||
}
|
||||
async stop() {
|
||||
device.running = false;
|
||||
return chromecast.stop();
|
||||
await chromecast.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,11 +58,11 @@ class CoreMLPlugin(PredictPlugin, scrypted_sdk.BufferConverter, scrypted_sdk.Set
|
||||
else:
|
||||
out_dict = self.model.predict({'image': input, 'confidenceThreshold': self.minThreshold })
|
||||
|
||||
coordinatesList = out_dict['coordinates']
|
||||
coordinatesList = out_dict['coordinates'].astype(float)
|
||||
|
||||
objs = []
|
||||
|
||||
for index, confidenceList in enumerate(out_dict['confidence']):
|
||||
for index, confidenceList in enumerate(out_dict['confidence'].astype(float)):
|
||||
values = confidenceList
|
||||
maxConfidenceIndex = max(range(len(values)), key=values.__getitem__)
|
||||
maxConfidence = confidenceList[maxConfidenceIndex]
|
||||
|
||||
@@ -10,7 +10,7 @@ import { addTrackControls, parseSdp } from '@scrypted/common/src/sdp-utils';
|
||||
import { SettingsMixinDeviceBase, SettingsMixinDeviceOptions } from "@scrypted/common/src/settings-mixin";
|
||||
import { sleep } from '@scrypted/common/src/sleep';
|
||||
import { createFragmentedMp4Parser, createMpegTsParser, StreamChunk, StreamParser } from '@scrypted/common/src/stream-parser';
|
||||
import sdk, { BufferConverter, DeviceProvider, DeviceState, EventListenerRegister, FFmpegInput, H264Info, MediaObject, MediaStreamDestination, MediaStreamOptions, MixinProvider, RequestMediaStreamOptions, ResponseMediaStreamOptions, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting, Settings, SettingValue, VideoCamera, VideoCameraConfiguration } from '@scrypted/sdk';
|
||||
import sdk, { BufferConverter, ChargeState, DeviceBase, DeviceProvider, DeviceState, EventListenerRegister, FFmpegInput, H264Info, MediaObject, MediaStreamDestination, MediaStreamOptions, MixinProvider, RequestMediaStreamOptions, ResponseMediaStreamOptions, ScryptedDevice, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting, Settings, SettingValue, VideoCamera, VideoCameraConfiguration } from '@scrypted/sdk';
|
||||
import { StorageSettings } from '@scrypted/sdk/storage-settings';
|
||||
import crypto from 'crypto';
|
||||
import { once } from 'events';
|
||||
@@ -105,7 +105,10 @@ class PrebufferSession {
|
||||
rtspServerPath: string;
|
||||
rtspServerMutedPath: string;
|
||||
|
||||
constructor(public mixin: PrebufferMixin, public advertisedMediaStreamOptions: ResponseMediaStreamOptions, public stopInactive: boolean) {
|
||||
batteryListener: EventListenerRegister;
|
||||
chargerListener: EventListenerRegister;
|
||||
|
||||
constructor(public mixin: PrebufferMixin, public advertisedMediaStreamOptions: ResponseMediaStreamOptions, public enabled: boolean, public forceBatteryPrebuffer: boolean) {
|
||||
this.storage = mixin.storage;
|
||||
this.console = mixin.console;
|
||||
this.mixinDevice = mixin.mixinDevice;
|
||||
@@ -129,6 +132,12 @@ class PrebufferSession {
|
||||
this.rtspServerMutedPath = crypto.randomBytes(8).toString('hex');
|
||||
this.storage.setItem(rtspServerMutedPathKey, this.rtspServerMutedPath);
|
||||
}
|
||||
|
||||
this.handleChargingBatteryEvents();
|
||||
}
|
||||
|
||||
get stopInactive() {
|
||||
return !this.enabled || this.shouldDisableBatteryPrebuffer();
|
||||
}
|
||||
|
||||
get canPrebuffer() {
|
||||
@@ -206,6 +215,14 @@ class PrebufferSession {
|
||||
parserSession.kill(new Error('rebroadcast disabled'));
|
||||
this.clearPrebuffers();
|
||||
});
|
||||
if (this.batteryListener) {
|
||||
this.batteryListener.removeListener();
|
||||
this.batteryListener = null;
|
||||
}
|
||||
if (this.chargerListener) {
|
||||
this.chargerListener.removeListener();
|
||||
this.chargerListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
ensurePrebufferSession() {
|
||||
@@ -934,6 +951,46 @@ class PrebufferSession {
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
handleChargingBatteryEvents() {
|
||||
if (!this.mixin.interfaces.includes(ScryptedInterface.Charger) ||
|
||||
!this.mixin.interfaces.includes(ScryptedInterface.Battery)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const checkDisablePrebuffer = async () => {
|
||||
if (this.stopInactive) {
|
||||
this.console.log(this.streamName, 'low battery or not charging, prebuffering and rebroadcasting will only work on demand')
|
||||
if (!this.activeClients && this.parserSessionPromise) {
|
||||
this.console.log(this.streamName, 'terminating rebroadcast due to low battery or not charging')
|
||||
const session = await this.parserSessionPromise;
|
||||
session.kill(new Error('low battery or not charging'));
|
||||
}
|
||||
} else {
|
||||
this.ensurePrebufferSession();
|
||||
}
|
||||
}
|
||||
|
||||
const id = this.mixin.id;
|
||||
if (!this.batteryListener) {
|
||||
this.batteryListener = systemManager.listenDevice(id, ScryptedInterface.Battery, () => checkDisablePrebuffer());
|
||||
}
|
||||
if (!this.chargerListener) {
|
||||
this.chargerListener = systemManager.listenDevice(id, ScryptedInterface.Charger, () => checkDisablePrebuffer());
|
||||
}
|
||||
}
|
||||
|
||||
shouldDisableBatteryPrebuffer(): boolean | null {
|
||||
if (!this.mixin.interfaces.includes(ScryptedInterface.Battery)) {
|
||||
return null;
|
||||
}
|
||||
if (this.forceBatteryPrebuffer) {
|
||||
return false;
|
||||
}
|
||||
const lowBattery = this.mixin.batteryLevel == null || this.mixin.batteryLevel < 20;
|
||||
const hasCharger = this.mixin.interfaces.includes(ScryptedInterface.Charger);
|
||||
return !hasCharger || lowBattery || this.mixin.chargeState !== ChargeState.Charging;
|
||||
}
|
||||
|
||||
async handleRebroadcasterClient(options: {
|
||||
findSyncFrame: boolean,
|
||||
isActiveClient: boolean,
|
||||
@@ -1497,8 +1554,6 @@ class PrebufferMixin extends SettingsMixinDeviceBase<VideoCamera> implements Vid
|
||||
}
|
||||
}
|
||||
|
||||
const isBatteryPowered = this.mixinDeviceInterfaces.includes(ScryptedInterface.Battery);
|
||||
|
||||
if (!enabledIds.length)
|
||||
this.online = true;
|
||||
|
||||
@@ -1524,22 +1579,27 @@ class PrebufferMixin extends SettingsMixinDeviceBase<VideoCamera> implements Vid
|
||||
}
|
||||
const name = mso?.name;
|
||||
const enabled = enabledIds.includes(id);
|
||||
const stopInactive = (isBatteryPowered && !mso.allowBatteryPrebuffer) || !enabled;
|
||||
session = new PrebufferSession(this, mso, stopInactive);
|
||||
session = new PrebufferSession(this, mso, enabled, mso.allowBatteryPrebuffer);
|
||||
this.sessions.set(id, session);
|
||||
|
||||
if (isBatteryPowered && !mso.allowBatteryPrebuffer) {
|
||||
this.console.log('camera is battery powered, prebuffering and rebroadcasting will only work on demand.');
|
||||
if (!enabled) {
|
||||
this.console.log('stream', name, 'is not enabled and will be rebroadcast on demand.');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
this.console.log('stream', name, 'will be rebroadcast on demand.');
|
||||
continue;
|
||||
if (session.shouldDisableBatteryPrebuffer()) {
|
||||
this.console.log('camera is battery powered and either not charging or on low battery, prebuffering and rebroadcasting will only work on demand.');
|
||||
}
|
||||
|
||||
(async () => {
|
||||
while (this.sessions.get(id) === session && !this.released) {
|
||||
if (session.shouldDisableBatteryPrebuffer()) {
|
||||
// since battery devices could be eligible for prebuffer, check periodically
|
||||
// in the event the battery device becomes eligible again
|
||||
await new Promise(resolve => setTimeout(resolve, 60000));
|
||||
continue;
|
||||
}
|
||||
|
||||
session.ensurePrebufferSession();
|
||||
let wasActive = false;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user