trtc-electron-sdk 13.5.802-beta.0 → 13.5.802-beta.1
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/liteav/MediaMixingDesigner/index.d.ts +1 -0
- package/liteav/MediaMixingDesigner/index.js +9 -1
- package/liteav/extensions/MediaMixingManager/MediaMixingManager.d.ts +62 -0
- package/liteav/extensions/MediaMixingManager/MediaMixingManager.js +261 -15
- package/liteav/extensions/MediaMixingManager/types.d.ts +9 -2
- package/package.json +1 -1
|
@@ -272,12 +272,16 @@ class TRTCMediaMixingDesigner {
|
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
274
|
updateOverlay() {
|
|
275
|
+
var _a;
|
|
275
276
|
if (this.moveAndResizeOverlay) {
|
|
276
277
|
let left = this.absoluteWorkingArea.left + this.previewLeft;
|
|
277
278
|
let top = this.absoluteWorkingArea.top + this.previewTop;
|
|
278
279
|
let width = 0;
|
|
279
280
|
let height = 0;
|
|
280
|
-
if (
|
|
281
|
+
// Even if a locked media source is forced into "selected" state (e.g. via
|
|
282
|
+
// an external list panel selection), the move/resize overlay must stay
|
|
283
|
+
// hidden so it cannot be dragged or resized from the canvas.
|
|
284
|
+
if (this.selectedMediaIndex >= 0 && !((_a = this.mediaList[this.selectedMediaIndex]) === null || _a === void 0 ? void 0 : _a.isLocked)) {
|
|
281
285
|
this.moveAndResizeOverlay.style.display = 'block';
|
|
282
286
|
const selectedPreviewRect = {
|
|
283
287
|
left: this.mediaList[this.selectedMediaIndex].rect.left * this.previewScale,
|
|
@@ -415,6 +419,10 @@ class TRTCMediaMixingDesigner {
|
|
|
415
419
|
for (let i = 0; i < this.mediaList.length; i++) {
|
|
416
420
|
const item = this.mediaList[i];
|
|
417
421
|
if (item.rect &&
|
|
422
|
+
// Locked media sources are excluded from hit test, so a click on a
|
|
423
|
+
// locked source falls through to the next (lower zOrder) hit, and
|
|
424
|
+
// it can never be selected/dragged/resized via canvas interaction.
|
|
425
|
+
!item.isLocked &&
|
|
418
426
|
xInImage >= item.rect.left &&
|
|
419
427
|
xInImage <= item.rect.right &&
|
|
420
428
|
yInImage >= item.rect.top &&
|
|
@@ -146,6 +146,7 @@ export declare class TRTCMediaMixingManager implements ITRTCMediaMixingManager {
|
|
|
146
146
|
private serverStatus;
|
|
147
147
|
private serverMode;
|
|
148
148
|
private addMediaSourceTimers;
|
|
149
|
+
private screenCaptureRectRestartCounts;
|
|
149
150
|
private webRenderer;
|
|
150
151
|
private pixelFormat;
|
|
151
152
|
private pixelLength;
|
|
@@ -540,6 +541,67 @@ export declare class TRTCMediaMixingManager implements ITRTCMediaMixingManager {
|
|
|
540
541
|
* setter call.
|
|
541
542
|
*/
|
|
542
543
|
private _isSameCaptureParams;
|
|
544
|
+
private _omitIsPaused;
|
|
545
|
+
/**
|
|
546
|
+
* @private
|
|
547
|
+
* Strip `captureRect` from a screen param so that the remaining object maps
|
|
548
|
+
* 1:1 onto the native `TRTCScreenCaptureProperty` structure.
|
|
549
|
+
*
|
|
550
|
+
* The capture region travels with the media source payload of
|
|
551
|
+
* add/updateMediaSource (and is consumed by the native `startScreenSource`),
|
|
552
|
+
* not through `setScreenCaptureProperty`. Keeping it out of the property
|
|
553
|
+
* object avoids both sending a field the native setter ignores and a false
|
|
554
|
+
* "changed" verdict from `_isSameCaptureParams`.
|
|
555
|
+
*/
|
|
556
|
+
private _omitCaptureRect;
|
|
557
|
+
/**
|
|
558
|
+
* @private
|
|
559
|
+
* Whether the capture region actually changed between two screen params.
|
|
560
|
+
*
|
|
561
|
+
* An absent `captureRect` means "leave the current capture region alone", so
|
|
562
|
+
* it never counts as a change. This mirrors the cpp-side diff, which only
|
|
563
|
+
* restarts the capture when a region is explicitly provided AND differs from
|
|
564
|
+
* the one currently applied.
|
|
565
|
+
*/
|
|
566
|
+
private _isScreenCaptureRectChanged;
|
|
567
|
+
private _screenCaptureRectRestartKey;
|
|
568
|
+
/**
|
|
569
|
+
* @private
|
|
570
|
+
* Record that one screen-capture restart has been requested for this source,
|
|
571
|
+
* so the resulting `onMediaSourceAdded` echo can be recognized and skipped.
|
|
572
|
+
*/
|
|
573
|
+
private _markScreenCaptureRectRestart;
|
|
574
|
+
/**
|
|
575
|
+
* @private
|
|
576
|
+
* Consume one pending restart marker. Returns true when the incoming
|
|
577
|
+
* notification is an echo of a capture-region restart we triggered ourselves.
|
|
578
|
+
*/
|
|
579
|
+
private _consumeScreenCaptureRectRestart;
|
|
580
|
+
/**
|
|
581
|
+
* @private
|
|
582
|
+
* Drop any pending restart markers for this source.
|
|
583
|
+
*
|
|
584
|
+
* Called whenever a source is added or removed: a marker only makes sense for
|
|
585
|
+
* the lifetime of one particular capture session. Should the native layer ever
|
|
586
|
+
* fail to echo a restart, a stale marker left behind would otherwise swallow
|
|
587
|
+
* the genuine insertion notification of a later re-add.
|
|
588
|
+
*/
|
|
589
|
+
private _clearScreenCaptureRectRestart;
|
|
590
|
+
/**
|
|
591
|
+
* @private
|
|
592
|
+
* Validate and normalize `screen.captureRect` in place.
|
|
593
|
+
*
|
|
594
|
+
* A rect is accepted when it is either all-zero (meaning "capture the whole
|
|
595
|
+
* target", matching the native default) or a well-formed region with a
|
|
596
|
+
* positive width and height. Anything else is dropped with a warning so that
|
|
597
|
+
* a malformed value never reaches the native layer and never disturbs the
|
|
598
|
+
* currently applied capture region.
|
|
599
|
+
*
|
|
600
|
+
* Only applies to kScreen sources; `captureRect` on any other source type is
|
|
601
|
+
* meaningless and is removed as well.
|
|
602
|
+
*/
|
|
603
|
+
private _normalizeScreenCaptureRect;
|
|
604
|
+
private _setVideoFilePaused;
|
|
543
605
|
private previewInNativeWindow;
|
|
544
606
|
private previewInWebElement;
|
|
545
607
|
private previewInNone;
|
|
@@ -8,12 +8,24 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
12
|
+
var t = {};
|
|
13
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
14
|
+
t[p] = s[p];
|
|
15
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
16
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
17
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
18
|
+
t[p[i]] = s[p[i]];
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
};
|
|
11
22
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
23
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
24
|
};
|
|
14
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
26
|
exports.TRTCMediaMixingManager = exports.TRTCMediaMixingEvent = void 0;
|
|
16
27
|
const events_1 = require("events");
|
|
28
|
+
const lodash_isequal_1 = __importDefault(require("lodash.isequal"));
|
|
17
29
|
const trtc_define_1 = require("../../trtc_define");
|
|
18
30
|
const types_1 = require("./types");
|
|
19
31
|
const utils_1 = require("../../utils");
|
|
@@ -107,6 +119,33 @@ const TRTCOnlineVideoParam_HACK_JSDOC = null;
|
|
|
107
119
|
* @property {Number} playoutVolume 播放音量,取值 0 - 100
|
|
108
120
|
*/
|
|
109
121
|
const TRTCVideoFileParam_HACK_JSDOC = null;
|
|
122
|
+
/**
|
|
123
|
+
* 本地视频文件媒体源参数
|
|
124
|
+
*
|
|
125
|
+
* 继承 `TRTCVideoFileParam` 的全部属性,并额外支持控制播放/暂停。
|
|
126
|
+
*
|
|
127
|
+
* @typedef {Object} TRTCMediaMixingLocalVideoParam
|
|
128
|
+
* @property {Number} playoutVolume 播放音量,取值 0 - 100
|
|
129
|
+
* @property {Boolean} isPaused 是否暂停播放,可选属性,默认 false(即播放)。
|
|
130
|
+
* `updateMediaSource` 时仅在该属性变化时才会下发暂停/恢复操作。
|
|
131
|
+
*/
|
|
132
|
+
const TRTCMediaMixingLocalVideoParam_HACK_JSDOC = null;
|
|
133
|
+
/**
|
|
134
|
+
* 屏幕/窗口采集参数
|
|
135
|
+
*
|
|
136
|
+
* 继承 `TRTCScreenCaptureProperty` 的全部属性,并额外支持指定采集区域。
|
|
137
|
+
*
|
|
138
|
+
* @typedef {Object} TRTCMediaMixingScreenParam
|
|
139
|
+
* @property {Boolean} enableCaptureMouse 是否采集目标内容的同时采集鼠标,可选属性,默认 true
|
|
140
|
+
* @property {Boolean} enableHighLight 是否高亮正在共享的窗口,可选属性,默认 true
|
|
141
|
+
* @property {Boolean} enableHighPerformance 是否开启高性能模式(仅分享屏幕时生效),可选属性,默认 true
|
|
142
|
+
* @property {Number} highLightColor 高亮边框颜色,RGB 格式,可选属性,传 0 使用默认颜色
|
|
143
|
+
* @property {Number} highLightWidth 高亮边框宽度,可选属性,传 0 使用默认宽度
|
|
144
|
+
* @property {Boolean} enableCaptureChildWindow 窗口采集时是否采集子窗口,可选属性,默认 false
|
|
145
|
+
* @property {Rect} captureRect 采集区域,单位:像素,可选属性。不传或传入全零表示采集完整画面;
|
|
146
|
+
* 传入合法区域(`right > left` 且 `bottom > top`)表示仅采集指定区域,非法区域会被忽略。
|
|
147
|
+
*/
|
|
148
|
+
const TRTCMediaMixingScreenParam_HACK_JSDOC = null;
|
|
110
149
|
/**
|
|
111
150
|
* 媒体源数据
|
|
112
151
|
*
|
|
@@ -117,12 +156,14 @@ const TRTCVideoFileParam_HACK_JSDOC = null;
|
|
|
117
156
|
* @property {Boolean} enableGreenScreen 是否开启绿幕(仅在 sourceType 为 kCamera 时生效),可选属性
|
|
118
157
|
* @property {Rect} rect 媒体源显示区域
|
|
119
158
|
* @property {Boolean} isSelected 媒体源是否选中,可选属性,默认:false
|
|
120
|
-
* @property {
|
|
159
|
+
* @property {Boolean} isLocked 媒体源是否锁定,可选属性,默认:false。锁定后该媒体源无法通过预览画布上的
|
|
160
|
+
* 点击、拖拽、缩放进行交互(即使被外部列表强制置为选中状态,也不会显示移动/缩放控件)。
|
|
161
|
+
* @property {TRTCVideoRotation} rotation 媒体源旋转角度,可选属性
|
|
121
162
|
* @property {TRTCVideoFillMode} fillMode 媒体源显示模式,可选属性,默认 `TRTCVideoFillMode_Fit`
|
|
122
163
|
* @property {TRTCVideoMirrorType} mirrorType 媒体源是否镜像,可选属性,默认不镜像
|
|
123
164
|
* @property {TRTCCameraCaptureParams} camera 摄像头采集参数,仅在 sourceType 为 kCamera 时生效,可选属性
|
|
124
|
-
* @property {
|
|
125
|
-
* @property {
|
|
165
|
+
* @property {TRTCMediaMixingScreenParam} screen 屏幕/窗口采集参数,仅在 sourceType 为 kScreen 时生效,可选属性
|
|
166
|
+
* @property {TRTCMediaMixingLocalVideoParam} localVideo 本地视频文件播放参数,仅在 sourceType 为 kVideoFile 时生效,可选属性
|
|
126
167
|
* @property {TRTCOnlineVideoParam} onlineVideo 在线视频播放参数,仅在 sourceType 为 kOnlineVideo 时生效,可选属性
|
|
127
168
|
*/
|
|
128
169
|
const TRTCMediaSource_HACK_JSDOC = null;
|
|
@@ -344,6 +385,17 @@ class TRTCMediaMixingManager {
|
|
|
344
385
|
// state machine stuck after a previous failure), which would otherwise leave
|
|
345
386
|
// the returned Promise pending forever and the UI stuck on "loading".
|
|
346
387
|
this.addMediaSourceTimers = new Map();
|
|
388
|
+
// Number of screen-capture restarts we have deliberately triggered per
|
|
389
|
+
// source, keyed by `${sourceType}-${sourceId}`.
|
|
390
|
+
//
|
|
391
|
+
// Changing `screen.captureRect` can only take effect by re-invoking the
|
|
392
|
+
// native `startScreenSource`, which makes the underlying SDK emit another
|
|
393
|
+
// `onScreenSourceStarted` -> `SM_OnSourceInserted`. That notification is an
|
|
394
|
+
// echo of an already-added source, not a new insertion, so it must not be
|
|
395
|
+
// mistaken for one. We count the restarts we asked for and swallow exactly
|
|
396
|
+
// that many successful notifications. A counter (rather than a flag) keeps
|
|
397
|
+
// rapid successive updates correct, since every restart echoes back once.
|
|
398
|
+
this.screenCaptureRectRestartCounts = new Map();
|
|
347
399
|
this.webRenderer = null;
|
|
348
400
|
this.pixelFormat = trtc_define_1.TRTCVideoPixelFormat.TRTCVideoPixelFormat_BGRA32;
|
|
349
401
|
this.pixelLength = 4;
|
|
@@ -431,6 +483,7 @@ class TRTCMediaMixingManager {
|
|
|
431
483
|
// callbacks touching a destroyed instance.
|
|
432
484
|
this.addMediaSourceTimers.forEach(timer => clearTimeout(timer));
|
|
433
485
|
this.addMediaSourceTimers.clear();
|
|
486
|
+
this.screenCaptureRectRestartCounts.clear();
|
|
434
487
|
this.paramsStore = null;
|
|
435
488
|
this.trtcParamsStore = null;
|
|
436
489
|
// 仅解除引用,pluginManager 生命周期由 TRTCCloud 统一管理
|
|
@@ -573,6 +626,7 @@ class TRTCMediaMixingManager {
|
|
|
573
626
|
});
|
|
574
627
|
}
|
|
575
628
|
const newMediaSource = (0, utils_1.safelyParse)(JSON.stringify(mediaSource));
|
|
629
|
+
this._normalizeScreenCaptureRect(newMediaSource);
|
|
576
630
|
if (newMediaSource.isSelected) {
|
|
577
631
|
const oldSelectedIndex = this.findSelectedMediaSource();
|
|
578
632
|
if (oldSelectedIndex !== -1) {
|
|
@@ -639,11 +693,15 @@ class TRTCMediaMixingManager {
|
|
|
639
693
|
// extra camera restart on first add. Other source types are handled in
|
|
640
694
|
// the onMediaSourceAdded callback once the C++ layer reports success.
|
|
641
695
|
this._applyCameraParamsBeforeAdd(newMediaSource);
|
|
696
|
+
// A fresh capture session starts here, so no restart echo can still be
|
|
697
|
+
// outstanding from a previous one.
|
|
698
|
+
this._clearScreenCaptureRectRestart(newMediaSource.sourceType, newMediaSource.sourceId);
|
|
642
699
|
this.nodeMediaMixingPlugin.addMediaSource(newMediaSource);
|
|
643
700
|
(_a = this.mediaMixingDesigner) === null || _a === void 0 ? void 0 : _a.addMedia({
|
|
644
701
|
id: `${newMediaSource.sourceType}__${newMediaSource.sourceId}`,
|
|
645
702
|
rect: newMediaSource.rect,
|
|
646
703
|
isSelected: newMediaSource.isSelected || false,
|
|
704
|
+
isLocked: newMediaSource.isLocked || false,
|
|
647
705
|
zOrder: newMediaSource.zOrder,
|
|
648
706
|
origin: newMediaSource
|
|
649
707
|
});
|
|
@@ -657,6 +715,8 @@ class TRTCMediaMixingManager {
|
|
|
657
715
|
return 11000;
|
|
658
716
|
case types_1.TRTCMediaSourceType.kVideoFile:
|
|
659
717
|
return 6000;
|
|
718
|
+
case types_1.TRTCMediaSourceType.kCamera:
|
|
719
|
+
return 8000; // camera maybe very slow
|
|
660
720
|
default:
|
|
661
721
|
return 5000;
|
|
662
722
|
}
|
|
@@ -702,10 +762,12 @@ class TRTCMediaMixingManager {
|
|
|
702
762
|
}
|
|
703
763
|
jsRemoveMediaSource(mediaSource, index) {
|
|
704
764
|
var _a;
|
|
765
|
+
this._clearScreenCaptureRectRestart(mediaSource.sourceType, mediaSource.sourceId);
|
|
705
766
|
(_a = this.mediaMixingDesigner) === null || _a === void 0 ? void 0 : _a.removeMedia({
|
|
706
767
|
id: `${mediaSource.sourceType}__${mediaSource.sourceId}`,
|
|
707
768
|
rect: mediaSource.rect,
|
|
708
769
|
isSelected: mediaSource.isSelected || false,
|
|
770
|
+
isLocked: mediaSource.isLocked || false,
|
|
709
771
|
zOrder: mediaSource.zOrder,
|
|
710
772
|
origin: (0, utils_1.safelyParse)(JSON.stringify(mediaSource))
|
|
711
773
|
});
|
|
@@ -717,7 +779,7 @@ class TRTCMediaMixingManager {
|
|
|
717
779
|
* @returns {Promise<void>}
|
|
718
780
|
*/
|
|
719
781
|
updateMediaSource(mediaSource) {
|
|
720
|
-
var _a;
|
|
782
|
+
var _a, _b;
|
|
721
783
|
return __awaiter(this, void 0, void 0, function* () {
|
|
722
784
|
logger_1.default.log(`${this.logPrefix}updateMediaSource:`, mediaSource);
|
|
723
785
|
const index = this.findMediaSourceIndex(mediaSource);
|
|
@@ -728,18 +790,40 @@ class TRTCMediaMixingManager {
|
|
|
728
790
|
});
|
|
729
791
|
}
|
|
730
792
|
const newMediaSource = Object.assign(Object.assign({}, this.sourceList[index]), (0, utils_1.safelyParse)(JSON.stringify(mediaSource)));
|
|
793
|
+
this._normalizeScreenCaptureRect(newMediaSource);
|
|
731
794
|
if (mediaSource.isSelected) {
|
|
732
795
|
const oldSelectedIndex = this.findSelectedMediaSource();
|
|
733
796
|
if (oldSelectedIndex !== -1 && oldSelectedIndex !== index) {
|
|
734
797
|
yield this.unselectMediaSource(oldSelectedIndex);
|
|
735
798
|
}
|
|
736
799
|
}
|
|
737
|
-
|
|
800
|
+
// The cpp layer re-invokes `startScreenSource` when the capture region
|
|
801
|
+
// changes, which echoes back one extra `SM_OnSourceInserted`. Record it
|
|
802
|
+
// before the call so the echo can be recognized instead of being handled
|
|
803
|
+
// as a brand-new insertion.
|
|
804
|
+
const captureRectChanged = newMediaSource.sourceType === types_1.TRTCMediaSourceType.kScreen
|
|
805
|
+
&& this._isScreenCaptureRectChanged(newMediaSource.screen, (_a = this.sourceList[index]) === null || _a === void 0 ? void 0 : _a.screen);
|
|
806
|
+
if (captureRectChanged) {
|
|
807
|
+
this._markScreenCaptureRectRestart(newMediaSource.sourceType, newMediaSource.sourceId);
|
|
808
|
+
}
|
|
809
|
+
try {
|
|
810
|
+
yield this.nodeMediaMixingPlugin.updateMediaSource(newMediaSource);
|
|
811
|
+
}
|
|
812
|
+
catch (err) {
|
|
813
|
+
// The native call failed before the capture restart could happen, so
|
|
814
|
+
// the expected echo will never arrive. Roll the marker back, otherwise
|
|
815
|
+
// the stale one would swallow a genuine insertion notification later.
|
|
816
|
+
if (captureRectChanged) {
|
|
817
|
+
this._clearScreenCaptureRectRestart(newMediaSource.sourceType, newMediaSource.sourceId);
|
|
818
|
+
}
|
|
819
|
+
throw err;
|
|
820
|
+
}
|
|
738
821
|
this._applyMediaSourceParams(newMediaSource, this.sourceList[index]);
|
|
739
|
-
(
|
|
822
|
+
(_b = this.mediaMixingDesigner) === null || _b === void 0 ? void 0 : _b.updateMedia({
|
|
740
823
|
id: `${mediaSource.sourceType}__${mediaSource.sourceId}`,
|
|
741
824
|
rect: mediaSource.rect,
|
|
742
825
|
isSelected: mediaSource.isSelected || false,
|
|
826
|
+
isLocked: mediaSource.isLocked || false,
|
|
743
827
|
zOrder: mediaSource.zOrder,
|
|
744
828
|
origin: (0, utils_1.safelyParse)(JSON.stringify(mediaSource))
|
|
745
829
|
});
|
|
@@ -1168,6 +1252,7 @@ class TRTCMediaMixingManager {
|
|
|
1168
1252
|
id: `${mediaSource.sourceType}__${mediaSource.sourceId}`,
|
|
1169
1253
|
rect: mediaSource.rect,
|
|
1170
1254
|
isSelected: mediaSource.isSelected || false,
|
|
1255
|
+
isLocked: mediaSource.isLocked || false,
|
|
1171
1256
|
zOrder: mediaSource.zOrder,
|
|
1172
1257
|
origin: mediaSource
|
|
1173
1258
|
});
|
|
@@ -1308,6 +1393,7 @@ class TRTCMediaMixingManager {
|
|
|
1308
1393
|
id: `${this.sourceList[index].sourceType}__${this.sourceList[index].sourceId}`,
|
|
1309
1394
|
rect: this.sourceList[index].rect,
|
|
1310
1395
|
isSelected: this.sourceList[index].isSelected || false,
|
|
1396
|
+
isLocked: this.sourceList[index].isLocked || false,
|
|
1311
1397
|
zOrder: this.sourceList[index].zOrder,
|
|
1312
1398
|
origin: (0, utils_1.safelyParse)(JSON.stringify(this.sourceList[index]))
|
|
1313
1399
|
});
|
|
@@ -1350,6 +1436,19 @@ class TRTCMediaMixingManager {
|
|
|
1350
1436
|
clearTimeout(timer);
|
|
1351
1437
|
this.addMediaSourceTimers.delete(promiseKey);
|
|
1352
1438
|
}
|
|
1439
|
+
// Deduplicate the echo of a capture-region restart that we triggered from
|
|
1440
|
+
// updateMediaSource: the source is already tracked and its params are
|
|
1441
|
+
// already applied, so re-running the add bookkeeping would only issue a
|
|
1442
|
+
// redundant setScreenCaptureProperty. Failures are deliberately NOT
|
|
1443
|
+
// swallowed - they still need to reach the caller through the normal
|
|
1444
|
+
// error path below.
|
|
1445
|
+
if (data.errCode === 0 && this._consumeScreenCaptureRectRestart(data.sourceType, data.sourceId)) {
|
|
1446
|
+
logger_1.default.log(`${this.logPrefix}screen capture rect restarted for sourceId:${data.sourceId}, skip duplicated onMediaSourceAdded`);
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
if (data.errCode !== 0) {
|
|
1450
|
+
this._clearScreenCaptureRectRestart(data.sourceType, data.sourceId);
|
|
1451
|
+
}
|
|
1353
1452
|
let flag = false;
|
|
1354
1453
|
if (data.errCode === 0) {
|
|
1355
1454
|
const addedIndex = this.findMediaSourceIndex({
|
|
@@ -1548,6 +1647,11 @@ class TRTCMediaMixingManager {
|
|
|
1548
1647
|
if ((_b = this.paramsStore) === null || _b === void 0 ? void 0 : _b.streamLayout) {
|
|
1549
1648
|
this.setStreamLayout(this.paramsStore.streamLayout);
|
|
1550
1649
|
}
|
|
1650
|
+
// The restarted media server holds no capture session yet, so every
|
|
1651
|
+
// source below is a genuine insertion. Drop restart markers left over
|
|
1652
|
+
// from before the crash, otherwise a stale one would swallow a recovery
|
|
1653
|
+
// notification and skip re-applying that source's capture params.
|
|
1654
|
+
this.screenCaptureRectRestartCounts.clear();
|
|
1551
1655
|
this.sourceList.forEach((item) => {
|
|
1552
1656
|
this._applyCameraParamsBeforeAdd(item);
|
|
1553
1657
|
this.nodeMediaMixingPlugin.addMediaSource(item);
|
|
@@ -1629,6 +1733,7 @@ class TRTCMediaMixingManager {
|
|
|
1629
1733
|
* setter is always invoked when params are present).
|
|
1630
1734
|
*/
|
|
1631
1735
|
_applyMediaSourceParams(mediaSource, oldMediaSource) {
|
|
1736
|
+
var _a;
|
|
1632
1737
|
switch (mediaSource.sourceType) {
|
|
1633
1738
|
case types_1.TRTCMediaSourceType.kCamera:
|
|
1634
1739
|
// Skip kCamera on the add path to avoid an extra camera restart;
|
|
@@ -1637,21 +1742,37 @@ class TRTCMediaMixingManager {
|
|
|
1637
1742
|
this.setCameraCaptureParam(mediaSource.sourceId, mediaSource.camera);
|
|
1638
1743
|
}
|
|
1639
1744
|
break;
|
|
1640
|
-
case types_1.TRTCMediaSourceType.kScreen:
|
|
1641
|
-
|
|
1642
|
-
|
|
1745
|
+
case types_1.TRTCMediaSourceType.kScreen: {
|
|
1746
|
+
const nextProperty = this._omitCaptureRect(mediaSource.screen);
|
|
1747
|
+
const prevProperty = this._omitCaptureRect(oldMediaSource === null || oldMediaSource === void 0 ? void 0 : oldMediaSource.screen);
|
|
1748
|
+
if (nextProperty && Object.keys(nextProperty).length > 0
|
|
1749
|
+
&& !this._isSameCaptureParams(nextProperty, prevProperty)) {
|
|
1750
|
+
this.setScreenCaptureProperty(mediaSource.sourceId, nextProperty);
|
|
1643
1751
|
}
|
|
1644
1752
|
break;
|
|
1753
|
+
}
|
|
1645
1754
|
case types_1.TRTCMediaSourceType.kOnlineVideo:
|
|
1646
1755
|
if (mediaSource.onlineVideo && !this._isSameCaptureParams(mediaSource.onlineVideo, oldMediaSource === null || oldMediaSource === void 0 ? void 0 : oldMediaSource.onlineVideo)) {
|
|
1647
1756
|
this.setOnlineVideoParam(mediaSource.sourceId, mediaSource.onlineVideo);
|
|
1648
1757
|
}
|
|
1649
1758
|
break;
|
|
1650
1759
|
case types_1.TRTCMediaSourceType.kVideoFile:
|
|
1651
|
-
if (mediaSource.localVideo
|
|
1652
|
-
this.
|
|
1760
|
+
if (mediaSource.localVideo) {
|
|
1761
|
+
const nextParam = this._omitIsPaused(mediaSource.localVideo);
|
|
1762
|
+
const prevParam = this._omitIsPaused(oldMediaSource === null || oldMediaSource === void 0 ? void 0 : oldMediaSource.localVideo);
|
|
1763
|
+
if (!this._isSameCaptureParams(nextParam, prevParam)) {
|
|
1764
|
+
this.setVideoFileParam(mediaSource.sourceId, mediaSource.localVideo);
|
|
1765
|
+
}
|
|
1766
|
+
const nextIsPaused = !!mediaSource.localVideo.isPaused;
|
|
1767
|
+
const prevIsPaused = !!((_a = oldMediaSource === null || oldMediaSource === void 0 ? void 0 : oldMediaSource.localVideo) === null || _a === void 0 ? void 0 : _a.isPaused);
|
|
1768
|
+
if (nextIsPaused !== prevIsPaused) {
|
|
1769
|
+
this._setVideoFilePaused(mediaSource.sourceId, nextIsPaused);
|
|
1770
|
+
}
|
|
1653
1771
|
}
|
|
1654
1772
|
break;
|
|
1773
|
+
default:
|
|
1774
|
+
logger_1.default.warn(`[TRTC] Unknown media source type: ${mediaSource.sourceType}`);
|
|
1775
|
+
break;
|
|
1655
1776
|
}
|
|
1656
1777
|
}
|
|
1657
1778
|
/**
|
|
@@ -1683,13 +1804,138 @@ class TRTCMediaMixingManager {
|
|
|
1683
1804
|
if (nextEmpty || prevEmpty) {
|
|
1684
1805
|
return false;
|
|
1685
1806
|
}
|
|
1686
|
-
|
|
1687
|
-
|
|
1807
|
+
return (0, lodash_isequal_1.default)(next, prev);
|
|
1808
|
+
}
|
|
1809
|
+
_omitIsPaused(param) {
|
|
1810
|
+
if (!param) {
|
|
1811
|
+
return undefined;
|
|
1812
|
+
}
|
|
1813
|
+
const { isPaused } = param, rest = __rest(param, ["isPaused"]);
|
|
1814
|
+
return rest;
|
|
1815
|
+
}
|
|
1816
|
+
/**
|
|
1817
|
+
* @private
|
|
1818
|
+
* Strip `captureRect` from a screen param so that the remaining object maps
|
|
1819
|
+
* 1:1 onto the native `TRTCScreenCaptureProperty` structure.
|
|
1820
|
+
*
|
|
1821
|
+
* The capture region travels with the media source payload of
|
|
1822
|
+
* add/updateMediaSource (and is consumed by the native `startScreenSource`),
|
|
1823
|
+
* not through `setScreenCaptureProperty`. Keeping it out of the property
|
|
1824
|
+
* object avoids both sending a field the native setter ignores and a false
|
|
1825
|
+
* "changed" verdict from `_isSameCaptureParams`.
|
|
1826
|
+
*/
|
|
1827
|
+
_omitCaptureRect(param) {
|
|
1828
|
+
if (!param) {
|
|
1829
|
+
return undefined;
|
|
1688
1830
|
}
|
|
1689
|
-
|
|
1690
|
-
|
|
1831
|
+
const { captureRect } = param, rest = __rest(param, ["captureRect"]);
|
|
1832
|
+
return rest;
|
|
1833
|
+
}
|
|
1834
|
+
/**
|
|
1835
|
+
* @private
|
|
1836
|
+
* Whether the capture region actually changed between two screen params.
|
|
1837
|
+
*
|
|
1838
|
+
* An absent `captureRect` means "leave the current capture region alone", so
|
|
1839
|
+
* it never counts as a change. This mirrors the cpp-side diff, which only
|
|
1840
|
+
* restarts the capture when a region is explicitly provided AND differs from
|
|
1841
|
+
* the one currently applied.
|
|
1842
|
+
*/
|
|
1843
|
+
_isScreenCaptureRectChanged(next, prev) {
|
|
1844
|
+
const nextRect = next === null || next === void 0 ? void 0 : next.captureRect;
|
|
1845
|
+
if (nextRect === undefined || nextRect === null) {
|
|
1846
|
+
return false;
|
|
1847
|
+
}
|
|
1848
|
+
return !(0, lodash_isequal_1.default)(nextRect, prev === null || prev === void 0 ? void 0 : prev.captureRect);
|
|
1849
|
+
}
|
|
1850
|
+
_screenCaptureRectRestartKey(sourceType, sourceId) {
|
|
1851
|
+
return `${sourceType}-${sourceId}`;
|
|
1852
|
+
}
|
|
1853
|
+
/**
|
|
1854
|
+
* @private
|
|
1855
|
+
* Record that one screen-capture restart has been requested for this source,
|
|
1856
|
+
* so the resulting `onMediaSourceAdded` echo can be recognized and skipped.
|
|
1857
|
+
*/
|
|
1858
|
+
_markScreenCaptureRectRestart(sourceType, sourceId) {
|
|
1859
|
+
const key = this._screenCaptureRectRestartKey(sourceType, sourceId);
|
|
1860
|
+
this.screenCaptureRectRestartCounts.set(key, (this.screenCaptureRectRestartCounts.get(key) || 0) + 1);
|
|
1861
|
+
}
|
|
1862
|
+
/**
|
|
1863
|
+
* @private
|
|
1864
|
+
* Consume one pending restart marker. Returns true when the incoming
|
|
1865
|
+
* notification is an echo of a capture-region restart we triggered ourselves.
|
|
1866
|
+
*/
|
|
1867
|
+
_consumeScreenCaptureRectRestart(sourceType, sourceId) {
|
|
1868
|
+
const key = this._screenCaptureRectRestartKey(sourceType, sourceId);
|
|
1869
|
+
const count = this.screenCaptureRectRestartCounts.get(key) || 0;
|
|
1870
|
+
if (count <= 0) {
|
|
1691
1871
|
return false;
|
|
1692
1872
|
}
|
|
1873
|
+
if (count === 1) {
|
|
1874
|
+
this.screenCaptureRectRestartCounts.delete(key);
|
|
1875
|
+
}
|
|
1876
|
+
else {
|
|
1877
|
+
this.screenCaptureRectRestartCounts.set(key, count - 1);
|
|
1878
|
+
}
|
|
1879
|
+
return true;
|
|
1880
|
+
}
|
|
1881
|
+
/**
|
|
1882
|
+
* @private
|
|
1883
|
+
* Drop any pending restart markers for this source.
|
|
1884
|
+
*
|
|
1885
|
+
* Called whenever a source is added or removed: a marker only makes sense for
|
|
1886
|
+
* the lifetime of one particular capture session. Should the native layer ever
|
|
1887
|
+
* fail to echo a restart, a stale marker left behind would otherwise swallow
|
|
1888
|
+
* the genuine insertion notification of a later re-add.
|
|
1889
|
+
*/
|
|
1890
|
+
_clearScreenCaptureRectRestart(sourceType, sourceId) {
|
|
1891
|
+
this.screenCaptureRectRestartCounts.delete(this._screenCaptureRectRestartKey(sourceType, sourceId));
|
|
1892
|
+
}
|
|
1893
|
+
/**
|
|
1894
|
+
* @private
|
|
1895
|
+
* Validate and normalize `screen.captureRect` in place.
|
|
1896
|
+
*
|
|
1897
|
+
* A rect is accepted when it is either all-zero (meaning "capture the whole
|
|
1898
|
+
* target", matching the native default) or a well-formed region with a
|
|
1899
|
+
* positive width and height. Anything else is dropped with a warning so that
|
|
1900
|
+
* a malformed value never reaches the native layer and never disturbs the
|
|
1901
|
+
* currently applied capture region.
|
|
1902
|
+
*
|
|
1903
|
+
* Only applies to kScreen sources; `captureRect` on any other source type is
|
|
1904
|
+
* meaningless and is removed as well.
|
|
1905
|
+
*/
|
|
1906
|
+
_normalizeScreenCaptureRect(mediaSource) {
|
|
1907
|
+
const screen = mediaSource.screen;
|
|
1908
|
+
if (!screen || screen.captureRect === undefined || screen.captureRect === null) {
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1911
|
+
if (mediaSource.sourceType !== types_1.TRTCMediaSourceType.kScreen) {
|
|
1912
|
+
logger_1.default.warn(`${this.logPrefix}screen.captureRect is only supported for kScreen source, ignored. sourceType:${mediaSource.sourceType}`);
|
|
1913
|
+
delete screen.captureRect;
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
const { left, top, right, bottom } = screen.captureRect;
|
|
1917
|
+
const isValidNumber = [left, top, right, bottom].every(item => typeof item === 'number' && Number.isInteger(item) && item >= -2147483648 && item <= 2147483647);
|
|
1918
|
+
if (!isValidNumber) {
|
|
1919
|
+
logger_1.default.warn(`${this.logPrefix}screen.captureRect must contain int32 integers, ignored:`, screen.captureRect);
|
|
1920
|
+
delete screen.captureRect;
|
|
1921
|
+
return;
|
|
1922
|
+
}
|
|
1923
|
+
const isFullTarget = left === 0 && top === 0 && right === 0 && bottom === 0;
|
|
1924
|
+
if (isFullTarget) {
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1927
|
+
if (left < 0 || top < 0 || right <= left || bottom <= top) {
|
|
1928
|
+
logger_1.default.warn(`${this.logPrefix}screen.captureRect is invalid, ignored:`, screen.captureRect);
|
|
1929
|
+
delete screen.captureRect;
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
_setVideoFilePaused(sourceId, isPaused) {
|
|
1933
|
+
if (isPaused) {
|
|
1934
|
+
this.nodeMediaMixingPlugin.pauseVideoFileSource(sourceId);
|
|
1935
|
+
}
|
|
1936
|
+
else {
|
|
1937
|
+
this.nodeMediaMixingPlugin.resumeVideoFileSource(sourceId);
|
|
1938
|
+
}
|
|
1693
1939
|
}
|
|
1694
1940
|
previewInNativeWindow(viewOrRegion) {
|
|
1695
1941
|
var _a;
|
|
@@ -46,6 +46,12 @@ export declare type TRTCOnlineVideoParam = {
|
|
|
46
46
|
export declare type TRTCVideoFileParam = {
|
|
47
47
|
playoutVolume: number;
|
|
48
48
|
};
|
|
49
|
+
export declare type TRTCMediaMixingLocalVideoParam = TRTCVideoFileParam & {
|
|
50
|
+
isPaused?: boolean;
|
|
51
|
+
};
|
|
52
|
+
export declare type TRTCMediaMixingScreenParam = TRTCScreenCaptureProperty & {
|
|
53
|
+
captureRect?: Rect;
|
|
54
|
+
};
|
|
49
55
|
export declare type TRTCMediaSource = {
|
|
50
56
|
sourceType: TRTCMediaSourceType;
|
|
51
57
|
sourceId: string;
|
|
@@ -53,12 +59,13 @@ export declare type TRTCMediaSource = {
|
|
|
53
59
|
enableGreenScreen?: boolean;
|
|
54
60
|
rect: Rect;
|
|
55
61
|
isSelected?: boolean;
|
|
62
|
+
isLocked?: boolean;
|
|
56
63
|
rotation?: TRTCVideoRotation;
|
|
57
64
|
fillMode?: TRTCVideoFillMode;
|
|
58
65
|
mirrorType?: TRTCVideoMirrorType;
|
|
59
66
|
camera?: TRTCCameraCaptureParams;
|
|
60
|
-
screen?:
|
|
61
|
-
localVideo?:
|
|
67
|
+
screen?: TRTCMediaMixingScreenParam;
|
|
68
|
+
localVideo?: TRTCMediaMixingLocalVideoParam;
|
|
62
69
|
onlineVideo?: TRTCOnlineVideoParam;
|
|
63
70
|
};
|
|
64
71
|
export declare type TRTCMediaMixingEncParam = {
|