cameras: add default request timeouts on snapshots

This commit is contained in:
Koushik Dutta
2024-03-05 08:47:49 -08:00
parent ec19410e0c
commit fd48eee7b2
18 changed files with 39 additions and 39 deletions

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/amcrest",
"version": "0.0.133",
"version": "0.0.134",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@scrypted/amcrest",
"version": "0.0.133",
"version": "0.0.134",
"license": "Apache",
"dependencies": {
"@scrypted/common": "file:../../common",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/amcrest",
"version": "0.0.133",
"version": "0.0.134",
"description": "Amcrest Plugin for Scrypted",
"author": "Scrypted",
"license": "Apache",

View File

@@ -69,10 +69,10 @@ export class AmcrestCameraClient {
return getDeviceInfo(this.credential, this.ip);
}
async jpegSnapshot(): Promise<Buffer> {
async jpegSnapshot(timeout = 10000): Promise<Buffer> {
const response = await this.request({
url: `http://${this.ip}/cgi-bin/snapshot.cgi`,
timeout: 60000,
timeout,
});
return response.body;

View File

@@ -1,6 +1,6 @@
import { ffmpegLogInitialOutput } from '@scrypted/common/src/media-helpers';
import { readLength } from "@scrypted/common/src/read-stream";
import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, FFmpegInput, Intercom, MediaObject, MediaStreamOptions, PictureOptions, Reboot, RequestRecordingStreamOptions, ResponseMediaStreamOptions, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting, VideoCameraConfiguration, VideoRecorder } from "@scrypted/sdk";
import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, FFmpegInput, Intercom, MediaObject, MediaStreamOptions, PictureOptions, Reboot, RequestPictureOptions, RequestRecordingStreamOptions, ResponseMediaStreamOptions, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting, VideoCameraConfiguration, VideoRecorder } from "@scrypted/sdk";
import child_process, { ChildProcess } from 'child_process';
import { PassThrough, Readable, Stream } from "stream";
import { OnvifIntercom } from "../../onvif/src/onvif-intercom";
@@ -318,8 +318,8 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
}
async takeSmartCameraPicture(option?: PictureOptions): Promise<MediaObject> {
return this.createMediaObject(await this.getClient().jpegSnapshot(), 'image/jpeg');
async takeSmartCameraPicture(options?: RequestPictureOptions): Promise<MediaObject> {
return this.createMediaObject(await this.getClient().jpegSnapshot(options?.timeout), 'image/jpeg');
}
async getUrlSettings() {

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/hikvision",
"version": "0.0.136",
"version": "0.0.137",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@scrypted/hikvision",
"version": "0.0.136",
"version": "0.0.137",
"license": "Apache",
"dependencies": {
"@scrypted/common": "file:../../common",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/hikvision",
"version": "0.0.136",
"version": "0.0.137",
"description": "Hikvision Plugin for Scrypted",
"author": "Scrypted",
"license": "Apache",

View File

@@ -1,4 +1,4 @@
import { AuthFetchCredentialState, HttpFetchOptions, HttpFetchResponseType, authHttpFetch } from '@scrypted/common/src/http-auth-fetch';
import { AuthFetchCredentialState, HttpFetchOptions, authHttpFetch } from '@scrypted/common/src/http-auth-fetch';
import { IncomingMessage } from 'http';
import { Readable } from 'stream';
import { getDeviceInfo } from './probe';
@@ -118,12 +118,12 @@ export class HikvisionCameraAPI {
}
}
async jpegSnapshot(channel: string): Promise<Buffer> {
async jpegSnapshot(channel: string, timeout = 10000): Promise<Buffer> {
const url = `http://${this.ip}/ISAPI/Streaming/channels/${getChannel(channel)}/picture?snapShotImageType=JPEG`
const response = await this.request({
url: url,
timeout: 60000,
timeout,
});
return response.body;

View File

@@ -1,4 +1,4 @@
import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, FFmpegInput, Intercom, MediaObject, MediaStreamOptions, Reboot, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting } from "@scrypted/sdk";
import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, FFmpegInput, Intercom, MediaObject, MediaStreamOptions, Reboot, RequestPictureOptions, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting } from "@scrypted/sdk";
import { PassThrough } from "stream";
import xml2js from 'xml2js';
import { RtpPacket } from '../../../external/werift/packages/rtp/src/rtp/rtp';
@@ -121,9 +121,9 @@ class HikvisionCamera extends RtspSmartCamera implements Camera, Intercom, Reboo
return this.client;
}
async takeSmartCameraPicture(): Promise<MediaObject> {
async takeSmartCameraPicture(options?: RequestPictureOptions): Promise<MediaObject> {
const api = this.getClient();
return mediaManager.createMediaObject(await api.jpegSnapshot(this.getRtspChannel()), 'image/jpeg');
return mediaManager.createMediaObject(await api.jpegSnapshot(this.getRtspChannel(), options?.timeout), 'image/jpeg');
}
async getRtspUrlSettings(): Promise<Setting[]> {

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/onvif",
"version": "0.1.8",
"version": "0.1.10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@scrypted/onvif",
"version": "0.1.8",
"version": "0.1.10",
"license": "Apache",
"dependencies": {
"@scrypted/common": "file:../../common",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/onvif",
"version": "0.1.8",
"version": "0.1.10",
"description": "ONVIF Camera Plugin for Scrypted",
"author": "Scrypted",
"license": "Apache",

View File

@@ -1,4 +1,4 @@
import sdk, { AdoptDevice, Device, DeviceCreatorSettings, DeviceDiscovery, DeviceInformation, DiscoveredDevice, Intercom, MediaObject, MediaStreamOptions, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, PanTiltZoom, PanTiltZoomCommand, PictureOptions, Reboot, ScryptedDeviceType, ScryptedInterface, ScryptedNativeId, Setting, Settings, SettingValue, VideoCamera, VideoCameraConfiguration } from "@scrypted/sdk";
import sdk, { AdoptDevice, Device, DeviceCreatorSettings, DeviceDiscovery, DeviceInformation, DiscoveredDevice, Intercom, MediaObject, MediaStreamOptions, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, PanTiltZoom, PanTiltZoomCommand, PictureOptions, Reboot, RequestPictureOptions, ScryptedDeviceType, ScryptedInterface, ScryptedNativeId, Setting, Settings, SettingValue, VideoCamera, VideoCameraConfiguration } from "@scrypted/sdk";
import { AddressInfo } from "net";
import onvif from 'onvif';
import { Stream } from "stream";
@@ -159,7 +159,7 @@ class OnvifCamera extends RtspSmartCamera implements ObjectDetector, Intercom, V
}
}
async takeSmartCameraPicture(options?: PictureOptions): Promise<MediaObject> {
async takeSmartCameraPicture(options?: RequestPictureOptions): Promise<MediaObject> {
const client = await this.getClient();
let snapshot: Buffer;
let id = options?.id;
@@ -170,7 +170,7 @@ class OnvifCamera extends RtspSmartCamera implements ObjectDetector, Intercom, V
id = vso?.id;
}
snapshot = await client.jpegSnapshot(id);
snapshot = await client.jpegSnapshot(id, options?.timeout);
// it is possible that onvif does not support snapshots, in which case return the video stream
if (!snapshot) {

View File

@@ -270,7 +270,7 @@ export class OnvifCameraAPI {
return this.rtspUrls.get(profileToken);
}
async jpegSnapshot(profileToken?: string): Promise<Buffer | undefined> {
async jpegSnapshot(profileToken?: string, timeout = 10000): Promise<Buffer | undefined> {
if (!profileToken)
profileToken = await this.getMainProfileToken();
if (!this.snapshotUrls.has(profileToken)) {
@@ -294,7 +294,7 @@ export class OnvifCameraAPI {
const response = await this.request({
url: snapshotUri,
timeout: 60000,
timeout,
});
return response.body;

View File

@@ -1,7 +1,7 @@
import { DeviceState, MixinDeviceBase, MixinDeviceOptions, MixinProvider, PanTiltZoom, PanTiltZoomCommand, PanTiltZoomMovement, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, Setting, Settings, SettingValue } from "@scrypted/sdk";
import { MixinProvider, PanTiltZoom, PanTiltZoomCommand, PanTiltZoomMovement, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, Setting, Settings, SettingValue, WritableDeviceState } from "@scrypted/sdk";
import { StorageSettings } from "@scrypted/sdk/storage-settings";
import { connectCameraAPI } from "./onvif-api";
import { SettingsMixinDeviceBase, SettingsMixinDeviceOptions } from '../../../common/src/settings-mixin';
import { connectCameraAPI } from "./onvif-api";
export class OnvifPtzMixin extends SettingsMixinDeviceBase<Settings> implements PanTiltZoom, Settings {
storageSettings = new StorageSettings(this, {
@@ -121,7 +121,7 @@ export class OnvifPTZMixinProvider extends ScryptedDeviceBase implements MixinPr
];
}
async getMixin(mixinDevice: any, mixinDeviceInterfaces: ScryptedInterface[], mixinDeviceState: DeviceState): Promise<any> {
async getMixin(mixinDevice: any, mixinDeviceInterfaces: ScryptedInterface[], mixinDeviceState: WritableDeviceState): Promise<any> {
return new OnvifPtzMixin({
group: 'ONVIF PTZ',
groupKey: 'ptz',

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/reolink",
"version": "0.0.60",
"version": "0.0.61",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@scrypted/reolink",
"version": "0.0.60",
"version": "0.0.61",
"license": "Apache",
"dependencies": {
"@scrypted/common": "file:../../common",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/reolink",
"version": "0.0.60",
"version": "0.0.61",
"description": "Reolink Plugin for Scrypted",
"author": "Scrypted",
"license": "Apache",

View File

@@ -1,5 +1,5 @@
import { sleep } from '@scrypted/common/src/sleep';
import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, Intercom, MediaObject, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, PanTiltZoom, PanTiltZoomCommand, PictureOptions, Reboot, ScryptedDeviceType, ScryptedInterface, Setting } from "@scrypted/sdk";
import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, Intercom, MediaObject, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, PanTiltZoom, PanTiltZoomCommand, PictureOptions, Reboot, RequestPictureOptions, ScryptedDeviceType, ScryptedInterface, Setting } from "@scrypted/sdk";
import { StorageSettings } from '@scrypted/sdk/storage-settings';
import { EventEmitter } from "stream";
import { Destroyable, RtspProvider, RtspSmartCamera, UrlMediaStreamOptions } from "../../rtsp/src/rtsp";
@@ -302,8 +302,8 @@ class ReolinkCamera extends RtspSmartCamera implements Camera, Reboot, Intercom,
return ret;
}
async takeSmartCameraPicture(option?: PictureOptions): Promise<MediaObject> {
return this.createMediaObject(await this.getClient().jpegSnapshot(), 'image/jpeg');
async takeSmartCameraPicture(options?: RequestPictureOptions): Promise<MediaObject> {
return this.createMediaObject(await this.getClient().jpegSnapshot(options?.timeout), 'image/jpeg');
}
async getUrlSettings(): Promise<Setting[]> {

View File

@@ -127,7 +127,7 @@ export class ReolinkCameraClient {
};
}
async jpegSnapshot() {
async jpegSnapshot(timeout = 10000) {
const url = new URL(`http://${this.host}/cgi-bin/api.cgi`);
const params = url.searchParams;
params.set('cmd', 'Snap');
@@ -138,7 +138,7 @@ export class ReolinkCameraClient {
const response = await this.request({
url,
timeout: 60000,
timeout,
});
return response.body;

View File

@@ -1,5 +1,5 @@
import { timeoutPromise } from '@scrypted/common/src/promise-utils';
import sdk, { MediaObject, MediaStreamUrl, PictureOptions, ResponseMediaStreamOptions, ScryptedInterface, ScryptedMimeTypes, Setting, SettingValue } from "@scrypted/sdk";
import sdk, { MediaObject, MediaStreamUrl, PictureOptions, RequestPictureOptions, ResponseMediaStreamOptions, ScryptedInterface, ScryptedMimeTypes, Setting, SettingValue } from "@scrypted/sdk";
import url from 'url';
import { CameraBase, CameraProviderBase, UrlMediaStreamOptions } from "../../ffmpeg-camera/src/common";
@@ -234,8 +234,8 @@ export abstract class RtspSmartCamera extends RtspCamera {
this.listener.then(l => l.emit('error', new Error("new settings")));
}
async takePicture(option?: PictureOptions) {
return this.takeSmartCameraPicture(option);;
async takePicture(options?: RequestPictureOptions) {
return this.takeSmartCameraPicture(options);
}
abstract takeSmartCameraPicture(options?: PictureOptions): Promise<MediaObject>;