mirror of
https://github.com/koush/scrypted.git
synced 2026-02-10 17:22:03 +00:00
homekit/unifi: dynamic bitrate support on remote streaming
This commit is contained in:
@@ -74,6 +74,7 @@ export class CameraMixin extends SettingsMixinDeviceBase<any> implements Setting
|
||||
readonly: true,
|
||||
description: 'Transcoding audio and video for HomeKit is not recommended. Configure your camera using the camera web portal or app to output the correct HomeKit compatible codecs (h264/aac/2000kbps).',
|
||||
})
|
||||
|
||||
settings.push({
|
||||
title: 'Transcode Streaming',
|
||||
group: 'HomeKit Transcoding',
|
||||
@@ -88,7 +89,15 @@ export class CameraMixin extends SettingsMixinDeviceBase<any> implements Setting
|
||||
type: 'boolean',
|
||||
key: 'transcodeStreamingHub',
|
||||
value: (this.storage.getItem('transcodeStreamingHub') === 'true').toString(),
|
||||
description: 'Use FFMpeg to transcode streaming to a format supported by HomeKit.',
|
||||
description: 'Remote Viewing through a HomeKit Hub only: Use FFMpeg to transcode streaming to a format supported by HomeKit.',
|
||||
});
|
||||
settings.push({
|
||||
title: 'Dynamic Bitrate (Hub)',
|
||||
group: 'HomeKit Transcoding',
|
||||
type: 'boolean',
|
||||
key: 'dynamicBitrate',
|
||||
value: (this.storage.getItem('dynamicBitrate') === 'true').toString(),
|
||||
description: 'Remote Viewing through a HomeKit Hub only: Adjust the bitrate of the native camera stream on demand to accomodate available bandwidth. This setting should be used on secondary streams (sub streams), and not the main stream connected to an NVR, as it will reduce the recording quality.',
|
||||
});
|
||||
let showTranscodeArgs = this.storage.getItem('transcodeStreaming') === 'true'
|
||||
|| this.storage.getItem('transcodeStreamingHub') === 'true';
|
||||
|
||||
@@ -186,23 +186,37 @@ addSupportedType({
|
||||
selectedStream = msos.find(mso => mso.name === streamingChannel);
|
||||
}
|
||||
|
||||
if (request.type === StreamRequestTypes.RECONFIGURE) {
|
||||
const tryReconfigureBitrate = () => {
|
||||
if (!isHomeKitHub)
|
||||
return;
|
||||
|
||||
if (!device.interfaces.includes(ScryptedInterface.VideoCameraConfiguration))
|
||||
return;
|
||||
|
||||
const dynamicBitrate = storage.getItem('dynamicBitrate') === 'true';
|
||||
if (!dynamicBitrate)
|
||||
return;
|
||||
|
||||
const reconfigured = Object.assign({
|
||||
video: {
|
||||
},
|
||||
}, selectedStream || {});
|
||||
reconfigured.video.bitrate = request.video.max_bit_rate;
|
||||
const bitrate = request.video.max_bit_rate * 1000;
|
||||
reconfigured.video.bitrate = bitrate;
|
||||
reconfigured.video.maxBitrate = bitrate;
|
||||
|
||||
device.setVideoStreamOptions(reconfigured);
|
||||
console.log('reconfigure selected stream', selectedStream);
|
||||
}
|
||||
|
||||
if (request.type === StreamRequestTypes.RECONFIGURE) {
|
||||
tryReconfigureBitrate();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
session.startRequest = request as StartStreamRequest;
|
||||
}
|
||||
tryReconfigureBitrate();
|
||||
|
||||
// watch for data to verify other side is alive.
|
||||
session.videoReturn.on('data', () => debounce(() => {
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
# Unifi Protect Plugin
|
||||
# Unifi Protect Plugin for Scrypted
|
||||
|
||||
## npm commands
|
||||
* npm run scrypted-webpack
|
||||
* npm run scrypted-deploy <ipaddress>
|
||||
* npm run scrypted-debug <ipaddress>
|
||||
The Unifi Protect Plugin connects your Unifi Cameras to Scrypted. The Protect appliance such as a Cloud Key or Dream Machine is required.
|
||||
|
||||
## scrypted distribution via npm
|
||||
1. Ensure package.json is set up properly for publishing on npm.
|
||||
2. npm publish
|
||||
## Unifi Beta 1.21.0-beta.3
|
||||
|
||||
## Visual Studio Code configuration
|
||||
This beta has a bug in it that causes HomeKit Secure Video recordings to fail. Please roll back to a prior or stable release, and flag [this issue](https://community.ui.com/releases/UniFi-Protect-Application-1-21-0-beta-3/32c7bb7a-697d-4841-8b9f-eef49b8682e9#comment/ad1c2710-2451-4612-847f-6413eb8ec0db).
|
||||
|
||||
* If using a remote server, edit [.vscode/settings.json](blob/master/.vscode/settings.json) to specify the IP Address of the Scrypted server.
|
||||
* Launch Scrypted Debugger from the launch menu.
|
||||
|
||||
4
plugins/unifi-protect/package-lock.json
generated
4
plugins/unifi-protect/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@scrypted/unifi-protect",
|
||||
"version": "0.0.64",
|
||||
"version": "0.0.66",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@scrypted/unifi-protect",
|
||||
"version": "0.0.64",
|
||||
"version": "0.0.66",
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"@koush/unifi-protect": "^0.0.6",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@scrypted/unifi-protect",
|
||||
"version": "0.0.64",
|
||||
"version": "0.0.66",
|
||||
"description": "Unifi Protect Plugin for Scrypted",
|
||||
"author": "Scrypted",
|
||||
"license": "Apache",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import sdk, { ScryptedDeviceBase, DeviceProvider, Settings, Setting, ScryptedDeviceType, VideoCamera, MediaObject, Device, MotionSensor, ScryptedInterface, Camera, MediaStreamOptions, Intercom, ScryptedMimeTypes, FFMpegInput, ObjectDetector, PictureOptions, ObjectDetectionTypes, ObjectsDetected, ObjectDetectionResult, Notifier, SCRYPTED_MEDIA_SCHEME } from "@scrypted/sdk";
|
||||
import sdk, { ScryptedDeviceBase, DeviceProvider, Settings, Setting, ScryptedDeviceType, VideoCamera, MediaObject, Device, MotionSensor, ScryptedInterface, Camera, MediaStreamOptions, Intercom, ScryptedMimeTypes, FFMpegInput, ObjectDetector, PictureOptions, ObjectDetectionTypes, ObjectsDetected, ObjectDetectionResult, Notifier, SCRYPTED_MEDIA_SCHEME, VideoCameraConfiguration } from "@scrypted/sdk";
|
||||
import { ProtectApi, ProtectCameraLcdMessagePayload } from "@koush/unifi-protect";
|
||||
import { ProtectApiUpdates, ProtectNvrUpdatePayloadCameraUpdate, ProtectNvrUpdatePayloadEventAdd } from "@koush/unifi-protect";
|
||||
import { ProtectCameraChannelConfig, ProtectCameraConfigInterface } from "@koush/unifi-protect";
|
||||
@@ -12,7 +12,7 @@ const { log, deviceManager, mediaManager } = sdk;
|
||||
|
||||
const defaultSensorTimeout = 30;
|
||||
|
||||
class UnifiCamera extends ScryptedDeviceBase implements Camera, VideoCamera, MotionSensor, Settings, ObjectDetector {
|
||||
class UnifiCamera extends ScryptedDeviceBase implements Camera, VideoCamera, VideoCameraConfiguration, MotionSensor, Settings, ObjectDetector {
|
||||
protect: UnifiProtect;
|
||||
motionTimeout: NodeJS.Timeout;
|
||||
detectionTimeout: NodeJS.Timeout;
|
||||
@@ -229,6 +229,22 @@ class UnifiCamera extends ScryptedDeviceBase implements Camera, VideoCamera, Mot
|
||||
return this.getDefaultOrderedVideoStreamOptions(video);
|
||||
}
|
||||
|
||||
async setVideoStreamOptions(options: MediaStreamOptions): Promise<void> {
|
||||
const bitrate = options?.video?.bitrate;
|
||||
const maxBitrate = options?.video?.maxBitrate;
|
||||
if (!bitrate || !maxBitrate)
|
||||
return;
|
||||
|
||||
const camera = this.findCamera();
|
||||
const channel = camera.channels.find(channel => channel.id === options.id);
|
||||
channel.bitrate = bitrate;
|
||||
channel.maxBitrate = maxBitrate;
|
||||
const cameraResult = await this.protect.api.updateChannels(camera);
|
||||
if (!cameraResult) {
|
||||
throw new Error("setVideoStreamOptions failed")
|
||||
}
|
||||
}
|
||||
|
||||
async getPictureOptions(): Promise<PictureOptions[]> {
|
||||
return;
|
||||
}
|
||||
@@ -245,7 +261,7 @@ class UnifiDoorbell extends UnifiCamera implements Intercom, Notifier {
|
||||
this.protect.api.updateCamera(this.findCamera(), {
|
||||
lcdMessage: payload,
|
||||
})
|
||||
|
||||
|
||||
if (typeof media === 'string' && media.startsWith(SCRYPTED_MEDIA_SCHEME)) {
|
||||
media = await mediaManager.createMediaObjectFromUrl(media);
|
||||
}
|
||||
@@ -294,7 +310,7 @@ class UnifiProtect extends ScryptedDeviceBase implements Settings, DeviceProvide
|
||||
cameras: Map<string, UnifiCamera> = new Map();
|
||||
api: ProtectApi;
|
||||
startup: Promise<void>;
|
||||
runningEvents = new Map<string, {promise: Promise<unknown>, resolve: (value: unknown) => void}>();
|
||||
runningEvents = new Map<string, { promise: Promise<unknown>, resolve: (value: unknown) => void }>();
|
||||
|
||||
constructor(nativeId?: string, createOnly?: boolean) {
|
||||
super(nativeId);
|
||||
@@ -541,6 +557,7 @@ class UnifiProtect extends ScryptedDeviceBase implements Settings, DeviceProvide
|
||||
ScryptedInterface.Settings,
|
||||
ScryptedInterface.Camera,
|
||||
ScryptedInterface.VideoCamera,
|
||||
ScryptedInterface.VideoCameraConfiguration,
|
||||
ScryptedInterface.MotionSensor,
|
||||
],
|
||||
type: camera.featureFlags.hasChime
|
||||
|
||||
Reference in New Issue
Block a user