senza-sdk 4.5.0 → 4.5.2
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/dist/bundle.js +1 -1
- package/dist/implementation.bundle.js +1 -1
- package/package.json +1 -1
- package/src/implementation/lifecycle.js +1 -0
- package/src/implementation/overlay.js +178 -13
- package/src/implementation/remotePlayer.js +1 -1
- package/src/implementation/senzaShakaPlayer.js +46 -8
- package/src/interface/overlay.js +13 -0
- package/src/interface/version.js +1 -1
package/package.json
CHANGED
|
@@ -757,6 +757,7 @@ class Lifecycle extends LifecycleInterface {
|
|
|
757
757
|
class: "remotePlayer",
|
|
758
758
|
action: "stop",
|
|
759
759
|
streamType: remotePlayer._isAudioSyncEnabled() ? StreamType.VIDEO | StreamType.SUBTITLE : StreamType.AUDIO | StreamType.VIDEO | StreamType.SUBTITLE,
|
|
760
|
+
switchMode: remotePlayer._isAudioSyncEnabled() ? SwitchMode.SEAMLESS : SwitchMode.NON_SEAMLESS,
|
|
760
761
|
fcid: FCID
|
|
761
762
|
};
|
|
762
763
|
let timerId = 0;
|
|
@@ -1,24 +1,131 @@
|
|
|
1
1
|
import { Overlay as OverlayInterface } from "../interface/overlay.js";
|
|
2
2
|
import { getFCID, sdkLogger, SenzaError } from "./utils";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Named overlay capture plans. Each step: `{ quality, conditional, delay }`.
|
|
6
|
+
* Steps run when refresh() is called; `delay` is ms after the previous step in the batch.
|
|
7
|
+
* `conditional`: when true, capture only if overlay content changed since the last
|
|
8
|
+
* required (non-conditional) capture in this batch; when false, always capture on that step.
|
|
9
|
+
* Set per step by the plan author; the SDK does not derive it.
|
|
10
|
+
*/
|
|
11
|
+
const OVERLAY_CAPTURE_PRESETS = {
|
|
12
|
+
default: [
|
|
13
|
+
{ quality: "low", conditional: false, delay: 0 },
|
|
14
|
+
{ quality: "low", conditional: true, delay: 150 },
|
|
15
|
+
{ quality: "low", conditional: true, delay: 300 },
|
|
16
|
+
{ quality: "high", conditional: false, delay: 600 }
|
|
17
|
+
],
|
|
18
|
+
once: [
|
|
19
|
+
{ quality: "high", conditional: true, delay: 0 }
|
|
20
|
+
]
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const DEFAULT_CAPTURE_PRESET = "default";
|
|
24
|
+
const VALID_QUALITIES = new Set(["low", "mid", "high"]);
|
|
25
|
+
|
|
4
26
|
class Overlay extends OverlayInterface {
|
|
5
27
|
constructor() {
|
|
6
28
|
super();
|
|
7
29
|
|
|
8
30
|
this._element = null;
|
|
9
31
|
this._configuration = {
|
|
10
|
-
useTransparency: true
|
|
32
|
+
useTransparency: true,
|
|
33
|
+
overlayCapturePreset: DEFAULT_CAPTURE_PRESET,
|
|
34
|
+
overlayCapturePlan: null
|
|
11
35
|
};
|
|
36
|
+
this._activeCapturePlan = OVERLAY_CAPTURE_PRESETS[DEFAULT_CAPTURE_PRESET];
|
|
37
|
+
this._retryGeneration = 0;
|
|
38
|
+
this._planTimerId = null;
|
|
39
|
+
this._currentBatchId = null;
|
|
12
40
|
}
|
|
13
41
|
|
|
14
42
|
_isTransparencyEnabled() {
|
|
15
43
|
return this._configuration.useTransparency !== false;
|
|
16
44
|
}
|
|
17
45
|
|
|
18
|
-
|
|
46
|
+
_clearPlanTimer() {
|
|
47
|
+
if (this._planTimerId != null) {
|
|
48
|
+
clearTimeout(this._planTimerId);
|
|
49
|
+
this._planTimerId = null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
_clearRetryTimers() {
|
|
54
|
+
this._retryGeneration++;
|
|
55
|
+
this._clearPlanTimer();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
_validateCapturePlan(plan) {
|
|
59
|
+
if (!Array.isArray(plan) || plan.length === 0) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
for (let i = 0; i < plan.length; i++) {
|
|
63
|
+
const step = plan[i];
|
|
64
|
+
if (!step || typeof step !== "object") {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
if (!VALID_QUALITIES.has(step.quality)) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
if (typeof step.conditional !== "boolean") {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
if (typeof step.delay !== "number" || !Number.isFinite(step.delay) || step.delay < 0) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
_resolveCapturePlan() {
|
|
81
|
+
if (this._configuration.overlayCapturePlan != null) {
|
|
82
|
+
return structuredClone(this._configuration.overlayCapturePlan);
|
|
83
|
+
}
|
|
84
|
+
const presetName = this._configuration.overlayCapturePreset ?? DEFAULT_CAPTURE_PRESET;
|
|
85
|
+
const preset = OVERLAY_CAPTURE_PRESETS[presetName];
|
|
86
|
+
if (!preset) {
|
|
87
|
+
throw new Error(`Overlay: unknown overlayCapturePreset "${presetName}"`);
|
|
88
|
+
}
|
|
89
|
+
return structuredClone(preset);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
_scheduleCapturePlanFromStep(batchId, plan, generation, startIndex) {
|
|
93
|
+
const scheduleStep = (index) => {
|
|
94
|
+
if (this._retryGeneration !== generation) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const step = plan[index];
|
|
98
|
+
if (!step) {
|
|
99
|
+
sdkLogger.error(`Overlay: missing capture plan step at index ${index} (plan length ${plan.length})`);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
this._clearPlanTimer();
|
|
103
|
+
this._planTimerId = setTimeout(async () => {
|
|
104
|
+
if (this._retryGeneration !== generation) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
await this._renderFrame(batchId, step, index);
|
|
109
|
+
} catch (err) {
|
|
110
|
+
sdkLogger.error("Overlay: capture plan step error:", err);
|
|
111
|
+
}
|
|
112
|
+
if (index + 1 < plan.length && this._retryGeneration === generation) {
|
|
113
|
+
scheduleStep(index + 1);
|
|
114
|
+
}
|
|
115
|
+
}, step.delay);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
scheduleStep(startIndex);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @param {boolean} conditional - When true, capture only if overlay content changed since
|
|
123
|
+
* the last required capture in this batch; when false, always capture on this step.
|
|
124
|
+
*/
|
|
125
|
+
_sendFrame(x, y, width, height, batchId, quality, conditional, stepIndex = 0) {
|
|
19
126
|
if (window.cefQuery) {
|
|
20
127
|
return new Promise((resolve, reject) => {
|
|
21
|
-
const FCID = getFCID()
|
|
128
|
+
const FCID = `${stepIndex}-${getFCID()}`;
|
|
22
129
|
const message = {
|
|
23
130
|
type: "displayOverlay",
|
|
24
131
|
x,
|
|
@@ -26,8 +133,12 @@ class Overlay extends OverlayInterface {
|
|
|
26
133
|
width,
|
|
27
134
|
height,
|
|
28
135
|
useTransparency: this._isTransparencyEnabled(),
|
|
29
|
-
fcid: FCID
|
|
136
|
+
fcid: FCID,
|
|
137
|
+
batchId,
|
|
138
|
+
quality,
|
|
139
|
+
conditional
|
|
30
140
|
};
|
|
141
|
+
sdkLogger.log(`Overlay: rendering frame x=${x} y=${y} width=${width} height=${height} fcid=${FCID} (batchId=${batchId}, quality=${quality}, conditional=${conditional})`);
|
|
31
142
|
const request = { target: "UI-Streamer", waitForResponse: false, message: JSON.stringify(message) };
|
|
32
143
|
window.cefQuery({
|
|
33
144
|
request: JSON.stringify(request),
|
|
@@ -44,18 +155,26 @@ class Overlay extends OverlayInterface {
|
|
|
44
155
|
return Promise.reject("Overlay is not supported if NOT running e2e");
|
|
45
156
|
}
|
|
46
157
|
|
|
47
|
-
_renderFrame() {
|
|
158
|
+
_renderFrame(batchId, captureStep = { quality: "high", conditional: false }, stepIndex = 0) {
|
|
48
159
|
if (!this._element) {
|
|
49
160
|
return Promise.reject("No element configured");
|
|
50
161
|
}
|
|
51
162
|
const rect = this._element.getBoundingClientRect();
|
|
52
163
|
const frame = this._normalizeFrame(rect);
|
|
53
164
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
165
|
+
if (frame.width === 0 || frame.height === 0) {
|
|
166
|
+
sdkLogger.warn(`Overlay: skipping frame with zero size (width=${frame.width}, height=${frame.height})`);
|
|
167
|
+
return Promise.resolve(false);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const id = batchId ?? this._currentBatchId ?? getFCID();
|
|
171
|
+
|
|
172
|
+
return this._sendFrame(frame.x, frame.y, frame.width, frame.height, id, captureStep.quality, captureStep.conditional, stepIndex).then(() => {
|
|
173
|
+
if (!captureStep.conditional) {
|
|
174
|
+
const refreshEvent = new Event("refresh");
|
|
175
|
+
refreshEvent.frame = frame;
|
|
176
|
+
this.dispatchEvent(refreshEvent);
|
|
177
|
+
}
|
|
59
178
|
return true;
|
|
60
179
|
});
|
|
61
180
|
}
|
|
@@ -65,8 +184,8 @@ class Overlay extends OverlayInterface {
|
|
|
65
184
|
|
|
66
185
|
const x = Math.round(toFiniteNumber(rect.x));
|
|
67
186
|
const y = Math.round(toFiniteNumber(rect.y));
|
|
68
|
-
const width = Math.
|
|
69
|
-
const height = Math.
|
|
187
|
+
const width = Math.round(toFiniteNumber(rect.width));
|
|
188
|
+
const height = Math.round(toFiniteNumber(rect.height));
|
|
70
189
|
|
|
71
190
|
return { x, y, width, height };
|
|
72
191
|
}
|
|
@@ -74,11 +193,41 @@ class Overlay extends OverlayInterface {
|
|
|
74
193
|
_applyConfiguration(configuration) {
|
|
75
194
|
const normalizedConfiguration = { ...configuration };
|
|
76
195
|
|
|
196
|
+
if (
|
|
197
|
+
Object.prototype.hasOwnProperty.call(normalizedConfiguration, "overlayCapturePreset") ||
|
|
198
|
+
Object.prototype.hasOwnProperty.call(normalizedConfiguration, "overlayCapturePlan")
|
|
199
|
+
) {
|
|
200
|
+
this._clearRetryTimers();
|
|
201
|
+
}
|
|
202
|
+
|
|
77
203
|
if (Object.prototype.hasOwnProperty.call(normalizedConfiguration, "useTransparency")) {
|
|
78
204
|
normalizedConfiguration.useTransparency = normalizedConfiguration.useTransparency !== false;
|
|
79
205
|
}
|
|
80
206
|
|
|
207
|
+
if (Object.prototype.hasOwnProperty.call(normalizedConfiguration, "overlayCapturePreset")) {
|
|
208
|
+
const preset = normalizedConfiguration.overlayCapturePreset;
|
|
209
|
+
if (typeof preset === "string" && OVERLAY_CAPTURE_PRESETS[preset]) {
|
|
210
|
+
normalizedConfiguration.overlayCapturePreset = preset;
|
|
211
|
+
} else if (preset != null) {
|
|
212
|
+
sdkLogger.warn(`Overlay: invalid overlayCapturePreset "${preset}", keeping previous preset`);
|
|
213
|
+
delete normalizedConfiguration.overlayCapturePreset;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (Object.prototype.hasOwnProperty.call(normalizedConfiguration, "overlayCapturePlan")) {
|
|
218
|
+
const plan = normalizedConfiguration.overlayCapturePlan;
|
|
219
|
+
if (plan == null) {
|
|
220
|
+
normalizedConfiguration.overlayCapturePlan = null;
|
|
221
|
+
} else if (this._validateCapturePlan(plan)) {
|
|
222
|
+
normalizedConfiguration.overlayCapturePlan = structuredClone(plan);
|
|
223
|
+
} else {
|
|
224
|
+
sdkLogger.warn("Overlay: invalid overlayCapturePlan, keeping previous plan");
|
|
225
|
+
delete normalizedConfiguration.overlayCapturePlan;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
81
229
|
this._configuration = { ...this._configuration, ...normalizedConfiguration };
|
|
230
|
+
this._activeCapturePlan = this._resolveCapturePlan();
|
|
82
231
|
}
|
|
83
232
|
|
|
84
233
|
async addElement(element) {
|
|
@@ -111,6 +260,7 @@ class Overlay extends OverlayInterface {
|
|
|
111
260
|
return Promise.reject(errorMsg);
|
|
112
261
|
}
|
|
113
262
|
|
|
263
|
+
this._clearRetryTimers();
|
|
114
264
|
this._element = null;
|
|
115
265
|
|
|
116
266
|
return Promise.resolve(true);
|
|
@@ -122,11 +272,25 @@ class Overlay extends OverlayInterface {
|
|
|
122
272
|
sdkLogger.error(errorMsg);
|
|
123
273
|
return Promise.reject(errorMsg);
|
|
124
274
|
}
|
|
125
|
-
|
|
275
|
+
this._clearRetryTimers();
|
|
276
|
+
this._currentBatchId = getFCID();
|
|
277
|
+
const batchId = this._currentBatchId;
|
|
278
|
+
const generation = this._retryGeneration;
|
|
279
|
+
const plan = this._activeCapturePlan;
|
|
280
|
+
if (plan[0].delay === 0) {
|
|
281
|
+
const result = await this._renderFrame(batchId, plan[0], 0);
|
|
282
|
+
if (result === true && plan.length > 1) {
|
|
283
|
+
this._scheduleCapturePlanFromStep(batchId, plan, generation, 1);
|
|
284
|
+
}
|
|
285
|
+
return result;
|
|
286
|
+
}
|
|
287
|
+
this._scheduleCapturePlanFromStep(batchId, plan, generation, 0);
|
|
288
|
+
return true;
|
|
126
289
|
}
|
|
127
290
|
|
|
128
291
|
async removeAllElements() {
|
|
129
292
|
sdkLogger.log("Overlay: removing all elements");
|
|
293
|
+
this._clearRetryTimers();
|
|
130
294
|
this._element = null;
|
|
131
295
|
}
|
|
132
296
|
|
|
@@ -162,6 +326,7 @@ class Overlay extends OverlayInterface {
|
|
|
162
326
|
* @returns {Promise<boolean>} Resolves to true if successful, rejects with error if failed.
|
|
163
327
|
*/
|
|
164
328
|
hideOverlay() {
|
|
329
|
+
this._clearRetryTimers();
|
|
165
330
|
return this._sendHideOverlay();
|
|
166
331
|
}
|
|
167
332
|
|
|
@@ -1021,7 +1021,7 @@ class RemotePlayer extends RemotePlayerInterface {
|
|
|
1021
1021
|
}
|
|
1022
1022
|
// if load in background is supported, play called while state is in background should include all streams
|
|
1023
1023
|
const backgroundStreamType = this.textTrackVisibility ? (StreamType.AUDIO | StreamType.VIDEO | StreamType.SUBTITLE) : (StreamType.AUDIO | StreamType.VIDEO);
|
|
1024
|
-
const streamType = backgroundLoadSupported ? backgroundStreamType : StreamType.AUDIO;
|
|
1024
|
+
const streamType = (backgroundLoadSupported && !isForegroundState) ? backgroundStreamType : StreamType.AUDIO;
|
|
1025
1025
|
|
|
1026
1026
|
return this._play(streamType, switchMode);
|
|
1027
1027
|
}
|
|
@@ -504,6 +504,18 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
|
|
|
504
504
|
|
|
505
505
|
}
|
|
506
506
|
|
|
507
|
+
_hasActiveTrackForLanguageAndRole(tracks, language, role) {
|
|
508
|
+
const activeTrack = tracks.find(track => track.active);
|
|
509
|
+
if (!activeTrack) {
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if ((!role || activeTrack.roles?.includes(role)) && activeTrack.language === language) {
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return false;
|
|
518
|
+
}
|
|
507
519
|
|
|
508
520
|
_attach(videoElement) {
|
|
509
521
|
this.videoElement = videoElement;
|
|
@@ -525,7 +537,10 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
|
|
|
525
537
|
this.handleSenzaError(error.code, error.message || "Unknown play error");
|
|
526
538
|
throw error;
|
|
527
539
|
});
|
|
528
|
-
|
|
540
|
+
this._originalPlay.call(this.videoElement).catch(error => {
|
|
541
|
+
this.handleSenzaError(error.code, error.message || "Unknown play error");
|
|
542
|
+
});
|
|
543
|
+
return;
|
|
529
544
|
}
|
|
530
545
|
|
|
531
546
|
if (this.remotePlayer._isPlaying) {
|
|
@@ -620,7 +635,6 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
|
|
|
620
635
|
return [...new Set(tracks.map(item => item.lang))];
|
|
621
636
|
}
|
|
622
637
|
|
|
623
|
-
|
|
624
638
|
selectVariantTrack(track, clearBuffer = false, safeMargin = 0) {
|
|
625
639
|
const audioLang = track.language;
|
|
626
640
|
const audioRole = Array.isArray(track.audioRoles) && track.audioRoles.length > 0
|
|
@@ -632,8 +646,11 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
|
|
|
632
646
|
const apCode = this._getAccessibilityCodeFromPurpose(track.accessibilityPurpose);
|
|
633
647
|
remotePlayer.selectAudioLanguage(audioLang, audioRole, apCode);
|
|
634
648
|
|
|
635
|
-
|
|
636
|
-
|
|
649
|
+
if (track && !track.active) {
|
|
650
|
+
super.selectVariantTrack(track, clearBuffer, safeMargin);
|
|
651
|
+
} else {
|
|
652
|
+
sdkLogger.log("selectVariantTrack() skipping local Shaka selection because track is already active");
|
|
653
|
+
}
|
|
637
654
|
}
|
|
638
655
|
|
|
639
656
|
selectAudioTrack(audioTrack, safeMargin = 0) {
|
|
@@ -646,13 +663,24 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
|
|
|
646
663
|
const apCode = this._getAccessibilityCodeFromPurpose(audioTrack.accessibilityPurpose);
|
|
647
664
|
remotePlayer.selectAudioLanguage(audioLang, role, apCode);
|
|
648
665
|
|
|
649
|
-
|
|
666
|
+
if (audioTrack && !audioTrack.active) {
|
|
667
|
+
super.selectAudioTrack(audioTrack, safeMargin);
|
|
668
|
+
} else {
|
|
669
|
+
sdkLogger.log("selectAudioTrack() skipping local Shaka selection because track is already active");
|
|
670
|
+
}
|
|
650
671
|
}
|
|
651
672
|
|
|
652
673
|
selectAudioLanguage(language, role) {
|
|
653
674
|
sdkLogger.log("selectAudioLanguage() Selecting audio language:", language, "with role: ", role);
|
|
654
675
|
remotePlayer.selectAudioLanguage(language, role);
|
|
655
|
-
|
|
676
|
+
|
|
677
|
+
const tracks = this.getAudioTracks();
|
|
678
|
+
sdkLogger.log("selectAudioLanguage: audio tracks", JSON.stringify(tracks), "language", language, "role", role);
|
|
679
|
+
if (!this._hasActiveTrackForLanguageAndRole(tracks, language, role)) {
|
|
680
|
+
super.selectAudioLanguage(language, role);
|
|
681
|
+
} else {
|
|
682
|
+
sdkLogger.log("selectAudioLanguage() skipping local Shaka selection because language is already active");
|
|
683
|
+
}
|
|
656
684
|
}
|
|
657
685
|
|
|
658
686
|
selectTextTrack(textTrack) {
|
|
@@ -665,12 +693,22 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
|
|
|
665
693
|
const apCode = this._getAccessibilityCodeFromPurpose(textTrack.accessibilityPurpose);
|
|
666
694
|
remotePlayer.selectTextLanguage(textLang, role, apCode);
|
|
667
695
|
|
|
668
|
-
|
|
696
|
+
if (textTrack && !textTrack.active) {
|
|
697
|
+
super.selectTextTrack(textTrack);
|
|
698
|
+
} else {
|
|
699
|
+
sdkLogger.log("selectTextTrack() skipping local Shaka selection because track is already active");
|
|
700
|
+
}
|
|
669
701
|
}
|
|
670
702
|
selectTextLanguage(language, role) {
|
|
671
703
|
sdkLogger.log("selectTextLanguage() Selecting text language:", language, "with role: ", role);
|
|
672
704
|
remotePlayer.selectTextLanguage(language, role);
|
|
673
|
-
|
|
705
|
+
const tracks = this.getTextTracks();
|
|
706
|
+
sdkLogger.log("selectTextLanguage: text tracks", JSON.stringify(tracks));
|
|
707
|
+
if (!this._hasActiveTrackForLanguageAndRole(tracks, language, role)) {
|
|
708
|
+
super.selectTextLanguage(language, role);
|
|
709
|
+
} else {
|
|
710
|
+
sdkLogger.log("selectTextLanguage() skipping local Shaka selection because language is already active");
|
|
711
|
+
}
|
|
674
712
|
}
|
|
675
713
|
|
|
676
714
|
setTextTrackVisibility(visible) {
|
package/src/interface/overlay.js
CHANGED
|
@@ -46,6 +46,12 @@ class Overlay extends EventTarget {
|
|
|
46
46
|
* This is useful when the element's content or position has changed.
|
|
47
47
|
* The overlay must have an element registered before calling refresh.
|
|
48
48
|
*
|
|
49
|
+
* Runs the configured overlay capture plan after each call. The `default` preset sends
|
|
50
|
+
* low-quality captures with relative delays, ending with a high-quality capture.
|
|
51
|
+
* The `once` preset runs one high-quality conditional step immediately.
|
|
52
|
+
* All steps in one refresh share the same `batchId` (from `getFCID()`). Pending plan
|
|
53
|
+
* steps are cancelled by a subsequent call to refresh(), hideOverlay(), or removeElement().
|
|
54
|
+
*
|
|
49
55
|
* @returns {Promise<boolean>} Resolves to true if successful, rejects with error if failed.
|
|
50
56
|
*/
|
|
51
57
|
refresh() {
|
|
@@ -77,6 +83,13 @@ class Overlay extends EventTarget {
|
|
|
77
83
|
* @param {Object} configuration - The new configuration to apply.
|
|
78
84
|
* @param {boolean} [configuration.useTransparency=true] - Controls whether the overlay should be rendered with transparency.
|
|
79
85
|
* When set to `true`, the value is forwarded to UI-Streamer in `displayOverlay` requests.
|
|
86
|
+
* @param {string} [configuration.overlayCapturePreset="default"] - Named capture plan preset:
|
|
87
|
+
* `default` (progressive low→high captures) or `once` (one immediate high-quality conditional step).
|
|
88
|
+
* @param {Array<{quality: "low"|"mid"|"high", conditional: boolean, delay: number}>} [configuration.overlayCapturePlan]
|
|
89
|
+
* Explicit capture plan; overrides preset. Steps run on refresh(); each step's `delay` is ms after
|
|
90
|
+
* the previous step in the batch. Set `conditional` per step (the SDK does not derive it):
|
|
91
|
+
* when `true`, capture only if overlay content changed since the last required (non-conditional)
|
|
92
|
+
* capture in this batch; when `false`, always capture on that step.
|
|
80
93
|
*/
|
|
81
94
|
configure(configuration) {
|
|
82
95
|
noop(configuration);
|
package/src/interface/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "4.5.
|
|
1
|
+
export const version = "4.5.2";
|