diff --git a/common/src/autoconfigure-codecs.ts b/common/src/autoconfigure-codecs.ts index d8d3a53a7..a58b32a97 100644 --- a/common/src/autoconfigure-codecs.ts +++ b/common/src/autoconfigure-codecs.ts @@ -8,6 +8,12 @@ export const automaticallyConfigureSettings: Setting = { value: true, }; +export const onvifAutoConfigureSettings: Setting = { + key: 'onvif-autoconfigure', + type: 'html', + value: 'ONVIF autoconfiguration will configure the camera codecs. The camera motion sensor must still be configured manually.', +}; + const MEGABIT = 1024 * 1000; function getBitrateForResolution(resolution: number) { @@ -98,7 +104,8 @@ export async function autoconfigureCodecs( // get the fps of 20 or highest available let fps = Math.min(20, Math.max(...l.video.fpsRange)); - await configureCodecs({ + const waiting: Promise[] = []; + const confLow = configureCodecs({ id: l.id, video: { width: resolution[0], @@ -113,6 +120,7 @@ export async function autoconfigureCodecs( }, audio: audioOptions, }); + waiting.push(confLow); if (used.length === 3) { // find remote and low @@ -123,7 +131,7 @@ export async function autoconfigureCodecs( const lResolution = findResolutionTarget(l, 640, 360); fps = Math.min(20, Math.max(...r.video.fpsRange)); - await configureCodecs({ + const confRemote = configureCodecs({ id: r.id, video: { width: rResolution[0], @@ -138,9 +146,10 @@ export async function autoconfigureCodecs( }, audio: audioOptions, }); + waiting.push(confRemote); fps = Math.min(20, Math.max(...l.video.fpsRange)); - await configureCodecs({ + const confLow = configureCodecs({ id: l.id, video: { width: lResolution[0], @@ -155,6 +164,8 @@ export async function autoconfigureCodecs( }, audio: audioOptions, }); + + waiting.push(confLow); } else if (used.length == 2) { let target: [number, number]; @@ -165,7 +176,7 @@ export async function autoconfigureCodecs( const rResolution = findResolutionTarget(used[1], target[0], target[1]); const fps = Math.min(20, Math.max(...used[1].video.fpsRange)); - await configureCodecs({ + const confRemote = configureCodecs({ id: used[1].id, video: { width: rResolution[0], @@ -180,8 +191,23 @@ export async function autoconfigureCodecs( }, audio: audioOptions, }); + + waiting.push(confRemote); } else if (used.length === 1) { // no nop } -} \ No newline at end of file + + const waited = await Promise.allSettled(waiting); + + let errors = ''; + for (const w of waited) { + if (w.status === 'rejected') { + console.error(w.reason?.message); + errors += w.reason?.message + '\n'; + } + } + + if (errors) + throw new Error(errors); +} diff --git a/plugins/amcrest/src/main.ts b/plugins/amcrest/src/main.ts index ba5116899..f7c62b305 100644 --- a/plugins/amcrest/src/main.ts +++ b/plugins/amcrest/src/main.ts @@ -702,7 +702,7 @@ class AmcrestProvider extends RtspProvider { { key: 'httpPort', title: 'HTTP Port', - description: 'Optional: Override the HTTP Port from the default value of 80', + description: 'Optional: Override the HTTP Port from the default value of 80.', placeholder: '80', }, automaticallyConfigureSettings, diff --git a/plugins/hikvision/src/hikvision-autoconfigure.ts b/plugins/hikvision/src/hikvision-autoconfigure.ts index 6793108b6..db19cb641 100644 --- a/plugins/hikvision/src/hikvision-autoconfigure.ts +++ b/plugins/hikvision/src/hikvision-autoconfigure.ts @@ -1,6 +1,13 @@ +import { Setting } from '@scrypted/sdk'; import { autoconfigureCodecs as ac } from '../../../common/src/autoconfigure-codecs'; import { HikvisionAPI } from './hikvision-api-channels'; +export const hikvisionAutoConfigureSettings: Setting = { + key: 'onvif-autoconfigure', + type: 'html', + value: 'Hikvision autoconfiguration will configure the camera codecs. The camera motion sensor must still be configured manually.', +}; + export async function autoconfigureSettings(client: HikvisionAPI, camNumber: string) { return ac( () => client.getCodecs(camNumber), diff --git a/plugins/hikvision/src/main.ts b/plugins/hikvision/src/main.ts index a3fb74bb5..b61edd21a 100644 --- a/plugins/hikvision/src/main.ts +++ b/plugins/hikvision/src/main.ts @@ -8,7 +8,7 @@ import { OnvifIntercom } from "../../onvif/src/onvif-intercom"; import { createRtspMediaStreamOptions, RtspProvider, RtspSmartCamera, UrlMediaStreamOptions } from "../../rtsp/src/rtsp"; import { startRtpForwarderProcess } from '../../webrtc/src/rtp-forwarders'; import { HikvisionAPI } from "./hikvision-api-channels"; -import { autoconfigureSettings } from "./hikvision-autoconfigure"; +import { autoconfigureSettings, hikvisionAutoConfigureSettings } from "./hikvision-autoconfigure"; import { detectionMap, HikvisionCameraAPI, HikvisionCameraEvent } from "./hikvision-camera-api"; const rtspChannelSetting: Setting = { @@ -467,6 +467,7 @@ export class HikvisionCamera extends RtspSmartCamera implements Camera, Intercom }; ac.type = 'button'; ret.push(ac); + ret.push(hikvisionAutoConfigureSettings); return ret; } @@ -724,10 +725,11 @@ class HikvisionProvider extends RtspProvider { { key: 'httpPort', title: 'HTTP Port', - description: 'Optional: Override the HTTP Port from the default value of 80', + description: 'Optional: Override the HTTP Port from the default value of 80.', placeholder: '80', }, automaticallyConfigureSettings, + hikvisionAutoConfigureSettings, { key: 'skipValidate', title: 'Skip Validation', diff --git a/plugins/onvif/src/main.ts b/plugins/onvif/src/main.ts index d9ceb68eb..83e859919 100644 --- a/plugins/onvif/src/main.ts +++ b/plugins/onvif/src/main.ts @@ -9,7 +9,7 @@ import { autoconfigureSettings, configureCodecs, getCodecs } from "./onvif-confi import { listenEvents } from "./onvif-events"; import { OnvifIntercom } from "./onvif-intercom"; import { OnvifPTZMixinProvider } from "./onvif-ptz"; -import { automaticallyConfigureSettings, checkPluginNeedsAutoConfigure } from "@scrypted/common/src/autoconfigure-codecs"; +import { automaticallyConfigureSettings, checkPluginNeedsAutoConfigure, onvifAutoConfigureSettings } from "@scrypted/common/src/autoconfigure-codecs"; const { mediaManager, systemManager, deviceManager } = sdk; @@ -519,10 +519,11 @@ class OnvifProvider extends RtspProvider implements DeviceDiscovery { { key: 'httpPort', title: 'HTTP Port', - description: 'Optional: Override the HTTP Port from the default value of 80', + description: 'Optional: Override the HTTP Port from the default value of 80.', placeholder: '80', }, automaticallyConfigureSettings, + onvifAutoConfigureSettings, { key: 'skipValidate', title: 'Skip Validation', @@ -549,6 +550,7 @@ class OnvifProvider extends RtspProvider implements DeviceDiscovery { type: 'password', }, automaticallyConfigureSettings, + onvifAutoConfigureSettings, ] })); } @@ -563,6 +565,7 @@ class OnvifProvider extends RtspProvider implements DeviceDiscovery { if (adopt.settings.autoconfigure) { const client = await connectCameraAPI(`${entry.host}:${entry.port || 80}`, adopt.settings.username as string, adopt.settings.password as string, this.console, undefined); await autoconfigureSettings(this.console, client); + adopt.settings.autoconfigure = false; } await this.createDevice(adopt.settings, adopt.nativeId); this.discoveredDevices.delete(adopt.nativeId); diff --git a/plugins/onvif/src/onvif-configure.ts b/plugins/onvif/src/onvif-configure.ts index d68ccf3a9..1d4c3bdcb 100644 --- a/plugins/onvif/src/onvif-configure.ts +++ b/plugins/onvif/src/onvif-configure.ts @@ -129,13 +129,6 @@ export async function configureCodecs(console: Console, client: OnvifCameraAPI, vc.rateControl.bitrateLimit = Math.floor(videoOptions?.bitrate / 1000); } - // can't be set by onvif. But see if it is settable and doesn't match to direct user. - if (videoOptions?.bitrateControl && vc.rateControl?.$?.ConstantBitRate !== undefined) { - const constant = videoOptions?.bitrateControl === 'constant'; - if (vc.rateControl.$.ConstantBitRate !== constant) - throw new Error(options.id + ': camera video Bitrate Type must be manually set to ' + videoOptions?.bitrateControl + ' in the camera web admin.'); - } - if (videoOptions?.fps) { vc.rateControl ||= {}; vc.rateControl.frameRateLimit = videoOptions?.fps; @@ -163,6 +156,14 @@ export async function configureCodecs(console: Console, client: OnvifCameraAPI, ...configuredVideo, } }; + + // can't be set by onvif. But see if it is settable and doesn't match to direct user. + if (videoOptions?.bitrateControl && vc.rateControl?.$?.ConstantBitRate !== undefined) { + const constant = videoOptions?.bitrateControl === 'constant'; + if (vc.rateControl.$.ConstantBitRate !== constant) + throw new Error(options.id + ': camera video Bitrate Type must be manually set to ' + videoOptions?.bitrateControl + ' in the camera web admin.'); + } + return ret; } diff --git a/plugins/reolink/src/main.ts b/plugins/reolink/src/main.ts index 262fa9978..6eec33a70 100644 --- a/plugins/reolink/src/main.ts +++ b/plugins/reolink/src/main.ts @@ -806,7 +806,7 @@ class ReolinkProvider extends RtspProvider { { key: 'httpPort', title: 'HTTP Port', - description: 'Optional: Override the HTTP Port from the default value of 80', + description: 'Optional: Override the HTTP Port from the default value of 80.', placeholder: '80', }, {