@scrypted/prebuffer-mixin 0.1.222 → 0.1.225
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/dist/main.nodejs.js +1 -1
- package/dist/plugin.zip +0 -0
- package/package.json +3 -3
- package/src/main.ts +257 -144
- package/src/rfc4571.ts +115 -39
- package/src/sps-parser/bitstream.ts +75 -0
- package/src/sps-parser/index.ts +237 -0
- package/src/sps-parser/vui.ts +126 -0
- package/src/stream-settings.ts +81 -22
package/src/stream-settings.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getH264DecoderArgs } from "@scrypted/common/src/ffmpeg-hardware-acceleration";
|
|
2
|
+
import { StorageSetting, StorageSettings } from "@scrypted/common/src/settings";
|
|
2
3
|
import { MixinDeviceBase, ResponseMediaStreamOptions, VideoCamera } from "@scrypted/sdk";
|
|
3
4
|
|
|
4
5
|
export function getDefaultPrebufferedStreams(msos: ResponseMediaStreamOptions[]) {
|
|
@@ -54,13 +55,13 @@ export function createStreamSettings(device: MixinDeviceBase<VideoCamera>) {
|
|
|
54
55
|
const streamTypes = getStreamTypes({
|
|
55
56
|
defaultStream: {
|
|
56
57
|
title: 'Local Stream',
|
|
57
|
-
description: 'The media stream to use when streaming on your local network. This
|
|
58
|
+
description: 'The media stream to use when streaming on your local network. This stream should be prebuffered. Recommended resolution: 1920x1080 to 4K.',
|
|
58
59
|
hide: true,
|
|
59
60
|
prefersPrebuffer: true,
|
|
60
61
|
preferredResolution: 3840 * 2160,
|
|
61
62
|
},
|
|
62
63
|
remoteStream: {
|
|
63
|
-
title: 'Remote
|
|
64
|
+
title: 'Remote (Medium Resolution) Stream',
|
|
64
65
|
description: 'The media stream to use when streaming from outside your local network. Selecting a low birate stream is recommended. Recommended resolution: 1270x720.',
|
|
65
66
|
hide: true,
|
|
66
67
|
prefersPrebuffer: false,
|
|
@@ -71,18 +72,18 @@ export function createStreamSettings(device: MixinDeviceBase<VideoCamera>) {
|
|
|
71
72
|
description: 'The media stream to use for low resolution output, such as Apple Watch and Video Analysis. Recommended resolution: 480x360.',
|
|
72
73
|
hide: true,
|
|
73
74
|
prefersPrebuffer: false,
|
|
74
|
-
preferredResolution: 480 *
|
|
75
|
+
preferredResolution: 480 * 360,
|
|
75
76
|
},
|
|
76
77
|
recordingStream: {
|
|
77
78
|
title: 'Local Recording Stream',
|
|
78
|
-
description: 'The media stream to use when recording to local storage such as an NVR.',
|
|
79
|
+
description: 'The media stream to use when recording to local storage such as an NVR. This stream should be prebuffered. Recommended resolution: 1920x1080 to 4K.',
|
|
79
80
|
hide: true,
|
|
80
81
|
prefersPrebuffer: true,
|
|
81
82
|
preferredResolution: 3840 * 2160,
|
|
82
83
|
},
|
|
83
84
|
remoteRecordingStream: {
|
|
84
85
|
title: 'Remote Recording Stream',
|
|
85
|
-
description: 'The media stream to use when recording to cloud storage such as HomeKit Secure Video clips in iCloud.',
|
|
86
|
+
description: 'The media stream to use when recording to cloud storage such as HomeKit Secure Video clips in iCloud. This stream should be prebuffered. Recommended resolution: 1270x720.',
|
|
86
87
|
hide: true,
|
|
87
88
|
prefersPrebuffer: true,
|
|
88
89
|
preferredResolution: 1280 * 720,
|
|
@@ -94,21 +95,72 @@ export function createStreamSettings(device: MixinDeviceBase<VideoCamera>) {
|
|
|
94
95
|
title: 'Prebuffered Streams',
|
|
95
96
|
description: 'Prebuffering maintains an active connection to the stream and improves load times. Prebuffer also retains the recent video for capturing motion events with HomeKit Secure video. Enabling Prebuffer is not recommended on Cloud cameras.',
|
|
96
97
|
multiple: true,
|
|
97
|
-
hide:
|
|
98
|
+
hide: false,
|
|
98
99
|
},
|
|
99
100
|
...streamTypes,
|
|
101
|
+
transcodeStreams: {
|
|
102
|
+
group: 'Transcoding',
|
|
103
|
+
title: 'Transcode Streams',
|
|
104
|
+
description: 'The media streams to transcode. Transcoding audio and video is not recommended and should only be used when necessary. The Rebroadcast Plugin manages the system-wide Transcode settings. See the Rebroadcast Readme for optimal configuration.',
|
|
105
|
+
multiple: true,
|
|
106
|
+
choices: Object.values(streamTypes).map(st => st.title),
|
|
107
|
+
},
|
|
108
|
+
// 3/6/2022
|
|
109
|
+
// Ran into an issue where the RTSP source had SPS/PPS in the SDP,
|
|
110
|
+
// and none in the bitstream. Codec copy will not add SPS/PPS before IDR frames
|
|
111
|
+
// unless this flag is used.
|
|
112
|
+
// 3/7/2022
|
|
113
|
+
// This flag was enabled by default, but I believe this is causing issues with some users.
|
|
114
|
+
// Make it a setting.
|
|
115
|
+
missingCodecParameters: {
|
|
116
|
+
group: 'Transcoding',
|
|
117
|
+
title: 'Add H264 Extra Data',
|
|
118
|
+
description: 'Some cameras do not include H264 extra data in the stream and this causes live streaming to always fail (but recordings may be working). This is a inexpensive video filter and does not perform a transcode. Enable this setting only as necessary.',
|
|
119
|
+
type: 'boolean',
|
|
120
|
+
},
|
|
121
|
+
videoDecoderArguments: {
|
|
122
|
+
group: 'Transcoding',
|
|
123
|
+
title: 'Video Decoder Arguments',
|
|
124
|
+
description: 'FFmpeg arguments used to decode input video when transcoding a stream.',
|
|
125
|
+
placeholder: '-hwaccel auto',
|
|
126
|
+
choices: Object.keys(getH264DecoderArgs()),
|
|
127
|
+
combobox: true,
|
|
128
|
+
mapPut: (oldValue, newValue) => getH264DecoderArgs()[newValue]?.join(' ') || newValue,
|
|
129
|
+
}
|
|
100
130
|
});
|
|
101
131
|
|
|
102
|
-
function
|
|
132
|
+
function getDefaultMediaStream(v: StreamStorageSetting, msos: ResponseMediaStreamOptions[]) {
|
|
103
133
|
const enabledStreams = getPrebufferedStreams(storageSettings, msos);
|
|
104
134
|
const prebufferPreferenceStreams = v.prefersPrebuffer && enabledStreams?.length > 0 ? enabledStreams : msos;
|
|
105
135
|
return pickBestStream(prebufferPreferenceStreams, v.preferredResolution);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function getMediaStream(key: string, msos: ResponseMediaStreamOptions[]) {
|
|
139
|
+
const v: StreamStorageSetting = storageSettings.settings[key];
|
|
140
|
+
const value = storageSettings.values[key];
|
|
141
|
+
let isDefault = value === 'Default';
|
|
142
|
+
let stream = msos?.find(mso => mso.name === value);
|
|
143
|
+
if (isDefault || !stream) {
|
|
144
|
+
isDefault = true;
|
|
145
|
+
stream = getDefaultMediaStream(v, msos);
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
title: streamTypes[key].title,
|
|
149
|
+
isDefault,
|
|
150
|
+
stream,
|
|
151
|
+
};
|
|
106
152
|
};
|
|
153
|
+
|
|
107
154
|
function createStreamOptions(v: StreamStorageSetting, msos: ResponseMediaStreamOptions[]) {
|
|
108
|
-
const choices =
|
|
155
|
+
const choices = [
|
|
156
|
+
'Default',
|
|
157
|
+
...msos.map(mso => mso.name),
|
|
158
|
+
];
|
|
159
|
+
const defaultValue = getDefaultMediaStream(v, msos).name;
|
|
109
160
|
|
|
110
161
|
const streamOptions = {
|
|
111
|
-
defaultValue:
|
|
162
|
+
defaultValue: 'Default',
|
|
163
|
+
description: v.description + ` The default for this stream is ${defaultValue}.`,
|
|
112
164
|
choices,
|
|
113
165
|
hide: false,
|
|
114
166
|
};
|
|
@@ -117,18 +169,20 @@ export function createStreamSettings(device: MixinDeviceBase<VideoCamera>) {
|
|
|
117
169
|
|
|
118
170
|
storageSettings.options = {
|
|
119
171
|
onGet: async () => {
|
|
172
|
+
let enabledStreams: StorageSetting;
|
|
173
|
+
|
|
120
174
|
try {
|
|
121
175
|
const msos = await device.mixinDevice.getVideoStreamOptions();
|
|
122
176
|
|
|
123
|
-
|
|
124
|
-
|
|
177
|
+
enabledStreams = {
|
|
178
|
+
defaultValue: getDefaultPrebufferedStreams(msos)?.map(mso => mso.name),
|
|
179
|
+
choices: msos.map(mso => mso.name),
|
|
180
|
+
hide: false,
|
|
181
|
+
};
|
|
125
182
|
|
|
183
|
+
if (msos?.length > 1) {
|
|
126
184
|
return {
|
|
127
|
-
enabledStreams
|
|
128
|
-
defaultValue: getDefaultPrebufferedStreams(msos)?.map(mso => mso.name),
|
|
129
|
-
choices,
|
|
130
|
-
hide: false,
|
|
131
|
-
},
|
|
185
|
+
enabledStreams,
|
|
132
186
|
defaultStream: createStreamOptions(streamTypes.defaultStream, msos),
|
|
133
187
|
remoteStream: createStreamOptions(streamTypes.remoteStream, msos),
|
|
134
188
|
lowResolutionStream: createStreamOptions(streamTypes.lowResolutionStream, msos),
|
|
@@ -136,6 +190,11 @@ export function createStreamSettings(device: MixinDeviceBase<VideoCamera>) {
|
|
|
136
190
|
remoteRecordingStream: createStreamOptions(streamTypes.remoteRecordingStream, msos),
|
|
137
191
|
}
|
|
138
192
|
}
|
|
193
|
+
else {
|
|
194
|
+
return {
|
|
195
|
+
enabledStreams,
|
|
196
|
+
}
|
|
197
|
+
}
|
|
139
198
|
}
|
|
140
199
|
catch (e) {
|
|
141
200
|
device.console.error('error retrieving getVideoStreamOptions', e);
|
|
@@ -147,11 +206,11 @@ export function createStreamSettings(device: MixinDeviceBase<VideoCamera>) {
|
|
|
147
206
|
}
|
|
148
207
|
|
|
149
208
|
return {
|
|
150
|
-
getDefaultStream: (msos: ResponseMediaStreamOptions[]) => getMediaStream(
|
|
151
|
-
getRemoteStream: (msos: ResponseMediaStreamOptions[]) => getMediaStream(
|
|
152
|
-
getLowResolutionStream: (msos: ResponseMediaStreamOptions[]) => getMediaStream(
|
|
153
|
-
getRecordingStream: (msos: ResponseMediaStreamOptions[]) => getMediaStream(
|
|
154
|
-
getRemoteRecordingStream: (msos: ResponseMediaStreamOptions[]) => getMediaStream(
|
|
209
|
+
getDefaultStream: (msos: ResponseMediaStreamOptions[]) => getMediaStream(storageSettings.keys.defaultStream, msos),
|
|
210
|
+
getRemoteStream: (msos: ResponseMediaStreamOptions[]) => getMediaStream(storageSettings.keys.remoteStream, msos),
|
|
211
|
+
getLowResolutionStream: (msos: ResponseMediaStreamOptions[]) => getMediaStream(storageSettings.keys.lowResolutionStream, msos),
|
|
212
|
+
getRecordingStream: (msos: ResponseMediaStreamOptions[]) => getMediaStream(storageSettings.keys.recordingStream, msos),
|
|
213
|
+
getRemoteRecordingStream: (msos: ResponseMediaStreamOptions[]) => getMediaStream(storageSettings.keys.remoteRecordingStream, msos),
|
|
155
214
|
storageSettings,
|
|
156
215
|
};
|
|
157
216
|
}
|