trtc-electron-sdk 13.4.801-alpha.0 → 13.4.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/extensions/MediaMixingManager/MediaMixingManager.d.ts +132 -7
- package/liteav/extensions/MediaMixingManager/MediaMixingManager.js +306 -44
- package/liteav/extensions/MediaMixingManager/types.d.ts +11 -10
- package/liteav/trtc.js +9 -0
- package/package.json +1 -1
- package/scripts/download.js +17 -5
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TRTCCameraCaptureParams, Rect, TRTCScreenCaptureProperty } from '../../trtc_define';
|
|
2
|
+
import TRTCPluginManager from '../PluginManager';
|
|
2
3
|
import { TRTCMediaSource, TRTCMediaMixingEncParam, ITRTCMediaMixingManager, TRTCPhoneMirrorParam, TRTCStreamLayout, TRTCOnlineVideoParam, TRTCVideoFileParam } from './types';
|
|
3
4
|
import { TRTCDeviceManager } from '../DeviceManager';
|
|
4
5
|
declare const NodeTRTCEngine: any;
|
|
@@ -54,6 +55,8 @@ export declare enum TRTCMediaMixingEvent {
|
|
|
54
55
|
onError = "onError",
|
|
55
56
|
/**
|
|
56
57
|
* @description 设备插入事件
|
|
58
|
+
* @deprecated
|
|
59
|
+
* @private
|
|
57
60
|
*
|
|
58
61
|
* @event TRTCMediaMixingEvent#onSourcePlugged
|
|
59
62
|
* @param {TRTCPhoneMirrorParam} source 投屏手机状态信息
|
|
@@ -62,6 +65,8 @@ export declare enum TRTCMediaMixingEvent {
|
|
|
62
65
|
onSourcePlugged = "onSourcePlugged",
|
|
63
66
|
/**
|
|
64
67
|
* @description 设备链接事件
|
|
68
|
+
* @deprecated
|
|
69
|
+
* @private
|
|
65
70
|
*
|
|
66
71
|
* @event TRTCMediaMixingEvent#onSourceConnected
|
|
67
72
|
* @param {TRTCPhoneMirrorParam} source 投屏手机状态信息
|
|
@@ -70,6 +75,8 @@ export declare enum TRTCMediaMixingEvent {
|
|
|
70
75
|
onSourceConnected = "onSourceConnected",
|
|
71
76
|
/**
|
|
72
77
|
* @description 设备断开链接事件
|
|
78
|
+
* @deprecated
|
|
79
|
+
* @private
|
|
73
80
|
*
|
|
74
81
|
* @event TRTCMediaMixingEvent#onSourceDisconnected
|
|
75
82
|
* @param {TRTCPhoneMirrorParam} source 投屏手机状态信息
|
|
@@ -78,6 +85,8 @@ export declare enum TRTCMediaMixingEvent {
|
|
|
78
85
|
onSourceDisconnected = "onSourceDisconnected",
|
|
79
86
|
/**
|
|
80
87
|
* @description 设备拔出事件
|
|
88
|
+
* @deprecated
|
|
89
|
+
* @private
|
|
81
90
|
*
|
|
82
91
|
* @event TRTCMediaMixingEvent#onSourceUnplugged
|
|
83
92
|
* @param {TRTCPhoneMirrorParam} source 投屏手机状态信息
|
|
@@ -95,6 +104,13 @@ export declare enum TRTCMediaMixingEvent {
|
|
|
95
104
|
* @param {Number} size.height 媒体源最新高度
|
|
96
105
|
*/
|
|
97
106
|
onMediaSourceSizeChanged = "onMediaSourceSizeChanged",
|
|
107
|
+
/**
|
|
108
|
+
* @description 本地混流服务丢失事件
|
|
109
|
+
* @deprecated
|
|
110
|
+
* @private
|
|
111
|
+
*
|
|
112
|
+
* @event TRTCMediaMixingEvent#onMediaMixingServerLost
|
|
113
|
+
*/
|
|
98
114
|
onMediaMixingServerLost = "onMediaMixingServerLost"
|
|
99
115
|
}
|
|
100
116
|
declare enum TRTCMediaMixingServerMode {
|
|
@@ -125,6 +141,7 @@ export declare class TRTCMediaMixingManager implements ITRTCMediaMixingManager {
|
|
|
125
141
|
private streamLayoutManager;
|
|
126
142
|
private trtcParamsStore;
|
|
127
143
|
private paramsStore;
|
|
144
|
+
private pluginManager;
|
|
128
145
|
private autoControlServer;
|
|
129
146
|
private serverStatus;
|
|
130
147
|
private serverMode;
|
|
@@ -139,6 +156,7 @@ export declare class TRTCMediaMixingManager implements ITRTCMediaMixingManager {
|
|
|
139
156
|
nodeTRTCCloud: typeof NodeTRTCEngine.NodeRemoteTRTCCloud;
|
|
140
157
|
trtcParamsStore: Record<string, any>;
|
|
141
158
|
autoControlServer: boolean;
|
|
159
|
+
pluginManager: TRTCPluginManager;
|
|
142
160
|
});
|
|
143
161
|
destroy(): Promise<void>;
|
|
144
162
|
/**
|
|
@@ -241,13 +259,6 @@ export declare class TRTCMediaMixingManager implements ITRTCMediaMixingManager {
|
|
|
241
259
|
* @returns {Promise<void>}
|
|
242
260
|
*/
|
|
243
261
|
addMediaSource(mediaSource: TRTCMediaSource): Promise<void>;
|
|
244
|
-
/**
|
|
245
|
-
* Returns the per-sourceType timeout (ms) used by addMediaSource. The
|
|
246
|
-
* defaults are intentionally larger than the cpp-layer timeout in
|
|
247
|
-
* SourceManagerProxy so that, in the normal case, the cpp side resolves the
|
|
248
|
-
* promise first. This JS timer is the last-resort safety net in case the
|
|
249
|
-
* cpp side itself fails to emit any callback (older builds, ipc lost, etc.).
|
|
250
|
-
*/
|
|
251
262
|
private getAddMediaSourceTimeoutMs;
|
|
252
263
|
/**
|
|
253
264
|
* 删除本地混流媒体源
|
|
@@ -265,12 +276,17 @@ export declare class TRTCMediaMixingManager implements ITRTCMediaMixingManager {
|
|
|
265
276
|
updateMediaSource(mediaSource: TRTCMediaSource): Promise<void>;
|
|
266
277
|
/**
|
|
267
278
|
* 设置摄像头采集参数
|
|
279
|
+
*
|
|
280
|
+
* @deprecated 请使用 `addMediaSource` 或 `updateMediaSource` 代替
|
|
281
|
+
*
|
|
268
282
|
* @param cameraID {string} - 摄像头 ID
|
|
269
283
|
* @param params {TRTCCameraCaptureParams} - 摄像头采集参数
|
|
270
284
|
*/
|
|
271
285
|
setCameraCaptureParam(cameraID: string, params: TRTCCameraCaptureParams): void;
|
|
272
286
|
/**
|
|
273
287
|
* 设置手机投屏参数
|
|
288
|
+
*
|
|
289
|
+
* @deprecated
|
|
274
290
|
* @private
|
|
275
291
|
* @param phoneMirrorSourceId {string} - 手机投屏媒体源 ID
|
|
276
292
|
* @param param {TRTCPhoneMirrorParam} - 手机投屏参数
|
|
@@ -278,18 +294,27 @@ export declare class TRTCMediaMixingManager implements ITRTCMediaMixingManager {
|
|
|
278
294
|
setPhoneMirrorParam(phoneMirrorSourceId: string, param: TRTCPhoneMirrorParam): void;
|
|
279
295
|
/**
|
|
280
296
|
* 设置屏幕采集参数
|
|
297
|
+
*
|
|
298
|
+
* @deprecated 请使用 `addMediaSource` 或 `updateMediaSource` 代替
|
|
299
|
+
*
|
|
281
300
|
* @param screenOrWindowID {String} - 屏幕 ID 或 窗口 ID
|
|
282
301
|
* @param property {TRTCScreenCaptureProperty} - 屏幕采集属性
|
|
283
302
|
*/
|
|
284
303
|
setScreenCaptureProperty(screenOrWindowID: string, property: TRTCScreenCaptureProperty): void;
|
|
285
304
|
/**
|
|
286
305
|
* 设置在线视频源播放参数
|
|
306
|
+
*
|
|
307
|
+
* @deprecated 请使用 `addMediaSource` 或 `updateMediaSource` 代替
|
|
308
|
+
*
|
|
287
309
|
* @param url {string} - 在线视频源 URL
|
|
288
310
|
* @param param {TRTCOnlineVideoParam} - 在线视频源播放参数
|
|
289
311
|
*/
|
|
290
312
|
setOnlineVideoParam(url: string, param: TRTCOnlineVideoParam): void;
|
|
291
313
|
/**
|
|
292
314
|
* 设置视频文件播放参数
|
|
315
|
+
*
|
|
316
|
+
* @deprecated 请使用 `addMediaSource` 或 `updateMediaSource` 代替
|
|
317
|
+
*
|
|
293
318
|
* @param videoFilePath {string} - 视频文件路径
|
|
294
319
|
* @param param {TRTCVideoFileParam} - 视频文件播放参数
|
|
295
320
|
*/
|
|
@@ -458,9 +483,109 @@ export declare class TRTCMediaMixingManager implements ITRTCMediaMixingManager {
|
|
|
458
483
|
private onCallExperimentalAPIFinish;
|
|
459
484
|
private recoverMediaMixingServer;
|
|
460
485
|
private onDevicePixelRatioChange;
|
|
486
|
+
/**
|
|
487
|
+
* @private
|
|
488
|
+
* Apply camera capture params BEFORE native addMediaSource.
|
|
489
|
+
*
|
|
490
|
+
* Calling setCameraCaptureParam after the camera has already been added
|
|
491
|
+
* triggers an extra camera restart (the camera first starts with default
|
|
492
|
+
* params and then restarts with the new ones). To avoid this we set
|
|
493
|
+
* camera params up-front for the add path. For all other source types
|
|
494
|
+
* the corresponding setters are dispatched in the post-add callback
|
|
495
|
+
* (`onMediaSourceAdded` -> `_applyMediaSourceParams`).
|
|
496
|
+
*/
|
|
497
|
+
private _applyCameraParamsBeforeAdd;
|
|
498
|
+
/**
|
|
499
|
+
* @private
|
|
500
|
+
* Apply capture params from TRTCMediaSource to the native plugin.
|
|
501
|
+
*
|
|
502
|
+
* This method is called after media source is added or updated. To avoid
|
|
503
|
+
* costly side-effects of native setters (e.g. setCameraCaptureParam will
|
|
504
|
+
* restart the camera), the setter is invoked only when params are actually
|
|
505
|
+
* provided AND differ from the previous value carried by `oldMediaSource`.
|
|
506
|
+
*
|
|
507
|
+
* Camera handling differs by phase:
|
|
508
|
+
* - Add path (oldMediaSource is undefined): camera params have been set
|
|
509
|
+
* before native addMediaSource via `_applyCameraParamsBeforeAdd`, so
|
|
510
|
+
* this method skips kCamera to avoid duplicate setter invocation.
|
|
511
|
+
* - Update path (oldMediaSource is provided): kCamera goes through the
|
|
512
|
+
* same diff check as other types and is dispatched only when changed.
|
|
513
|
+
*
|
|
514
|
+
* @param mediaSource - The new media source carrying capture params.
|
|
515
|
+
* @param oldMediaSource - The previous media source (omit for the add path
|
|
516
|
+
* where no previous params exist; in that case the
|
|
517
|
+
* setter is always invoked when params are present).
|
|
518
|
+
*/
|
|
519
|
+
private _applyMediaSourceParams;
|
|
520
|
+
/**
|
|
521
|
+
* @private
|
|
522
|
+
* Shallow-but-stable equality check on capture param objects via JSON.
|
|
523
|
+
*
|
|
524
|
+
* Returns true when both sides represent the "same" params, false otherwise.
|
|
525
|
+
* Semantics:
|
|
526
|
+
* - both empty (undefined / null) → true (no change requested)
|
|
527
|
+
* - exactly one side empty → false (first-time apply or transition)
|
|
528
|
+
* - both non-empty → byte-equal after JSON.stringify
|
|
529
|
+
*
|
|
530
|
+
* Note: JSON.stringify is sensitive to key ordering. Capture param objects
|
|
531
|
+
* carried by `TRTCMediaSource` are constructed by the SDK via
|
|
532
|
+
* `JSON.parse(JSON.stringify(...))` flow, so key order is stable in
|
|
533
|
+
* practice; for caller-supplied literal objects with unstable key order,
|
|
534
|
+
* the comparison may yield a false-negative and trigger an unnecessary
|
|
535
|
+
* setter call.
|
|
536
|
+
*/
|
|
537
|
+
private _isSameCaptureParams;
|
|
461
538
|
private previewInNativeWindow;
|
|
462
539
|
private previewInWebElement;
|
|
463
540
|
private previewInNone;
|
|
541
|
+
/**
|
|
542
|
+
* @private
|
|
543
|
+
* Ensure the media server is running in the mode required by the current
|
|
544
|
+
* preview target, before doing any preview binding.
|
|
545
|
+
*
|
|
546
|
+
* - Native-window preview -> Independent server (out-of-process, comes
|
|
547
|
+
* with onMediaServerState crash monitoring & auto-recovery).
|
|
548
|
+
* - Web-element preview -> Embedded server (in-process) that drives
|
|
549
|
+
* the video-frame render callback.
|
|
550
|
+
*
|
|
551
|
+
* The decision is driven by `serverStatus` (the single source of truth),
|
|
552
|
+
* NOT by `serverMode`. `serverMode` only reflects the mode of a *running*
|
|
553
|
+
* server and becomes meaningless once the server is stopped (Idle), where
|
|
554
|
+
* it keeps its last value. Keying the switch on `serverStatus` avoids that
|
|
555
|
+
* stale-value trap:
|
|
556
|
+
*
|
|
557
|
+
* - running (Started/Starting) in a different mode -> stop then restart in
|
|
558
|
+
* the required mode (mode switch).
|
|
559
|
+
* - running already in the required mode -> no-op.
|
|
560
|
+
* - Idle (e.g. after stopMediaMixingServer on logout) -> (re)start in the
|
|
561
|
+
* required mode. Without this, a logout -> login cycle would leave no
|
|
562
|
+
* monitored server, so a later crash of liteav_media_server.exe emits no
|
|
563
|
+
* state=3 event and neither the SDK's built-in recovery nor the app-layer
|
|
564
|
+
* recovery runs.
|
|
565
|
+
*
|
|
566
|
+
* `Lost` handling depends on autoControlServer, so the two recovery paths
|
|
567
|
+
* never overlap / race:
|
|
568
|
+
*
|
|
569
|
+
* - autoControlServer = true (getMediaMixingManager): the SDK owns crash
|
|
570
|
+
* recovery via onMediaServerState(state=3) -> recoverMediaMixingServer,
|
|
571
|
+
* which restarts the server AND re-binds the preview itself. We must NOT
|
|
572
|
+
* also restart here, otherwise a concurrent app-driven bindPreviewArea
|
|
573
|
+
* would double-start the server and race the built-in recovery. So when
|
|
574
|
+
* autoControlServer is true, `Lost` is intentionally left untouched here.
|
|
575
|
+
*
|
|
576
|
+
* - autoControlServer = false (getMediaMixingService): the SDK does NOT
|
|
577
|
+
* auto-recover (onMediaMixingServerLost only clears local state); the app
|
|
578
|
+
* is expected to drive recovery by calling bindPreviewArea again. In that
|
|
579
|
+
* case a `Lost` server must be (re)started here, exactly like `Idle`,
|
|
580
|
+
* otherwise the app's re-bind would silently do nothing and the preview
|
|
581
|
+
* would never come back.
|
|
582
|
+
*
|
|
583
|
+
* Safe against the first-launch path: startMediaMixingServer sets
|
|
584
|
+
* serverStatus to Starting synchronously, and the constructor's embedded
|
|
585
|
+
* auto-start runs before any bindPreviewArea, so the first bind never
|
|
586
|
+
* observes Idle here.
|
|
587
|
+
*/
|
|
588
|
+
private ensureMediaServerMode;
|
|
464
589
|
private createWebRenderer;
|
|
465
590
|
private destroyWebRenderer;
|
|
466
591
|
private createWebRendererBuffer;
|
|
@@ -92,6 +92,21 @@ const TRTCMediaSourceType_HACK_JSDOC = {
|
|
|
92
92
|
*
|
|
93
93
|
*/
|
|
94
94
|
const TRTCPhoneMirrorParam_HACK_JSDOC = null;
|
|
95
|
+
/**
|
|
96
|
+
* 在线视频播放参数
|
|
97
|
+
*
|
|
98
|
+
* @typedef {Object} TRTCOnlineVideoParam
|
|
99
|
+
* @property {Number} networkCacheSizeKB 网络缓存大小,单位 KB
|
|
100
|
+
* @property {Number} playoutVolume 播放音量,取值 0 - 100
|
|
101
|
+
*/
|
|
102
|
+
const TRTCOnlineVideoParam_HACK_JSDOC = null;
|
|
103
|
+
/**
|
|
104
|
+
* 本地视频文件播放参数
|
|
105
|
+
*
|
|
106
|
+
* @typedef {Object} TRTCVideoFileParam
|
|
107
|
+
* @property {Number} playoutVolume 播放音量,取值 0 - 100
|
|
108
|
+
*/
|
|
109
|
+
const TRTCVideoFileParam_HACK_JSDOC = null;
|
|
95
110
|
/**
|
|
96
111
|
* 媒体源数据
|
|
97
112
|
*
|
|
@@ -99,12 +114,16 @@ const TRTCPhoneMirrorParam_HACK_JSDOC = null;
|
|
|
99
114
|
* @property {TRTCMediaSourceType} sourceType 媒体源类型
|
|
100
115
|
* @property {String} sourceId 媒体源唯一 ID
|
|
101
116
|
* @property {Number} zOrder 媒体源展示层级,取值 0 - 15
|
|
117
|
+
* @property {Boolean} enableGreenScreen 是否开启绿幕(仅在 sourceType 为 kCamera 时生效),可选属性
|
|
102
118
|
* @property {Rect} rect 媒体源显示区域
|
|
103
119
|
* @property {Boolean} isSelected 媒体源是否选中,可选属性,默认:false
|
|
104
120
|
* @property {TRTCVideoRotation} rotation 媒体源选中角度,可选属性
|
|
105
121
|
* @property {TRTCVideoFillMode} fillMode 媒体源显示模式,可选属性,默认 `TRTCVideoFillMode_Fit`
|
|
106
122
|
* @property {TRTCVideoMirrorType} mirrorType 媒体源是否镜像,可选属性,默认不镜像
|
|
107
|
-
* @property {
|
|
123
|
+
* @property {TRTCCameraCaptureParams} camera 摄像头采集参数,仅在 sourceType 为 kCamera 时生效,可选属性
|
|
124
|
+
* @property {TRTCScreenCaptureProperty} screen 屏幕/窗口采集属性,仅在 sourceType 为 kScreen 时生效,可选属性
|
|
125
|
+
* @property {TRTCVideoFileParam} localVideo 本地视频文件播放参数,仅在 sourceType 为 kVideoFile 时生效,可选属性
|
|
126
|
+
* @property {TRTCOnlineVideoParam} onlineVideo 在线视频播放参数,仅在 sourceType 为 kOnlineVideo 时生效,可选属性
|
|
108
127
|
*/
|
|
109
128
|
const TRTCMediaSource_HACK_JSDOC = null;
|
|
110
129
|
/**
|
|
@@ -133,20 +152,20 @@ const TRTCStreamLayoutMode_HACK_JSDOC = {
|
|
|
133
152
|
* 单路连麦视频流布局信息
|
|
134
153
|
*
|
|
135
154
|
* 本地混流高性能渲染模式下,单路视频流布局信息
|
|
136
|
-
* @typedef {Object}
|
|
155
|
+
* @typedef {Object} TRTCUserStream
|
|
137
156
|
* @property {String} userId 用户 ID,本地用户需填空字符长
|
|
138
157
|
* @property {TRTCVideoFillMode} fillMode 视频填充模式
|
|
139
158
|
* @property {Rect} rect 视频流显示区域
|
|
140
159
|
* @property {Number} zOrder 视频流展示层级,取值 0 - 15
|
|
141
160
|
*/
|
|
142
|
-
const
|
|
161
|
+
const TRTCUserStream_HACK_JSDOC = null;
|
|
143
162
|
/**
|
|
144
163
|
* 连麦视频流布局信息
|
|
145
164
|
*
|
|
146
165
|
* 本地混流高性能渲染模式下,所有视频流布局信息
|
|
147
166
|
* @typedef {Object} TRTCStreamLayout
|
|
148
167
|
* @property {TRTCStreamLayoutMode} layoutMode 布局模式
|
|
149
|
-
* @property {Array<
|
|
168
|
+
* @property {Array<TRTCUserStream>} userList 非必填,用户视频流布局
|
|
150
169
|
*/
|
|
151
170
|
const TRTCStreamLayout_HACK_JSDOC = null;
|
|
152
171
|
const initResolutionMap = () => {
|
|
@@ -217,6 +236,8 @@ var TRTCMediaMixingEvent;
|
|
|
217
236
|
TRTCMediaMixingEvent["onError"] = "onError";
|
|
218
237
|
/**
|
|
219
238
|
* @description 设备插入事件
|
|
239
|
+
* @deprecated
|
|
240
|
+
* @private
|
|
220
241
|
*
|
|
221
242
|
* @event TRTCMediaMixingEvent#onSourcePlugged
|
|
222
243
|
* @param {TRTCPhoneMirrorParam} source 投屏手机状态信息
|
|
@@ -225,6 +246,8 @@ var TRTCMediaMixingEvent;
|
|
|
225
246
|
TRTCMediaMixingEvent["onSourcePlugged"] = "onSourcePlugged";
|
|
226
247
|
/**
|
|
227
248
|
* @description 设备链接事件
|
|
249
|
+
* @deprecated
|
|
250
|
+
* @private
|
|
228
251
|
*
|
|
229
252
|
* @event TRTCMediaMixingEvent#onSourceConnected
|
|
230
253
|
* @param {TRTCPhoneMirrorParam} source 投屏手机状态信息
|
|
@@ -233,6 +256,8 @@ var TRTCMediaMixingEvent;
|
|
|
233
256
|
TRTCMediaMixingEvent["onSourceConnected"] = "onSourceConnected";
|
|
234
257
|
/**
|
|
235
258
|
* @description 设备断开链接事件
|
|
259
|
+
* @deprecated
|
|
260
|
+
* @private
|
|
236
261
|
*
|
|
237
262
|
* @event TRTCMediaMixingEvent#onSourceDisconnected
|
|
238
263
|
* @param {TRTCPhoneMirrorParam} source 投屏手机状态信息
|
|
@@ -241,6 +266,8 @@ var TRTCMediaMixingEvent;
|
|
|
241
266
|
TRTCMediaMixingEvent["onSourceDisconnected"] = "onSourceDisconnected";
|
|
242
267
|
/**
|
|
243
268
|
* @description 设备拔出事件
|
|
269
|
+
* @deprecated
|
|
270
|
+
* @private
|
|
244
271
|
*
|
|
245
272
|
* @event TRTCMediaMixingEvent#onSourceUnplugged
|
|
246
273
|
* @param {TRTCPhoneMirrorParam} source 投屏手机状态信息
|
|
@@ -258,6 +285,13 @@ var TRTCMediaMixingEvent;
|
|
|
258
285
|
* @param {Number} size.height 媒体源最新高度
|
|
259
286
|
*/
|
|
260
287
|
TRTCMediaMixingEvent["onMediaSourceSizeChanged"] = "onMediaSourceSizeChanged";
|
|
288
|
+
/**
|
|
289
|
+
* @description 本地混流服务丢失事件
|
|
290
|
+
* @deprecated
|
|
291
|
+
* @private
|
|
292
|
+
*
|
|
293
|
+
* @event TRTCMediaMixingEvent#onMediaMixingServerLost
|
|
294
|
+
*/
|
|
261
295
|
TRTCMediaMixingEvent["onMediaMixingServerLost"] = "onMediaMixingServerLost";
|
|
262
296
|
})(TRTCMediaMixingEvent = exports.TRTCMediaMixingEvent || (exports.TRTCMediaMixingEvent = {}));
|
|
263
297
|
const promiseKeys = {
|
|
@@ -323,6 +357,7 @@ class TRTCMediaMixingManager {
|
|
|
323
357
|
this.nodeTRTCCloud = options.nodeTRTCCloud;
|
|
324
358
|
this.trtcParamsStore = options.trtcParamsStore;
|
|
325
359
|
this.autoControlServer = options.autoControlServer;
|
|
360
|
+
this.pluginManager = options.pluginManager;
|
|
326
361
|
this.paramsStore = {};
|
|
327
362
|
this.previewRenderParams = {
|
|
328
363
|
fillMode: trtc_define_1.TRTCVideoFillMode.TRTCVideoFillMode_Fit,
|
|
@@ -398,6 +433,8 @@ class TRTCMediaMixingManager {
|
|
|
398
433
|
this.addMediaSourceTimers.clear();
|
|
399
434
|
this.paramsStore = null;
|
|
400
435
|
this.trtcParamsStore = null;
|
|
436
|
+
// 仅解除引用,pluginManager 生命周期由 TRTCCloud 统一管理
|
|
437
|
+
this.pluginManager = null;
|
|
401
438
|
});
|
|
402
439
|
}
|
|
403
440
|
/**
|
|
@@ -598,6 +635,10 @@ class TRTCMediaMixingManager {
|
|
|
598
635
|
}
|
|
599
636
|
}, timeoutMs);
|
|
600
637
|
this.addMediaSourceTimers.set(key, timer);
|
|
638
|
+
// Apply camera capture params BEFORE native addMediaSource to avoid an
|
|
639
|
+
// extra camera restart on first add. Other source types are handled in
|
|
640
|
+
// the onMediaSourceAdded callback once the C++ layer reports success.
|
|
641
|
+
this._applyCameraParamsBeforeAdd(newMediaSource);
|
|
601
642
|
this.nodeMediaMixingPlugin.addMediaSource(newMediaSource);
|
|
602
643
|
(_a = this.mediaMixingDesigner) === null || _a === void 0 ? void 0 : _a.addMedia({
|
|
603
644
|
id: `${newMediaSource.sourceType}__${newMediaSource.sourceId}`,
|
|
@@ -610,13 +651,6 @@ class TRTCMediaMixingManager {
|
|
|
610
651
|
});
|
|
611
652
|
});
|
|
612
653
|
}
|
|
613
|
-
/**
|
|
614
|
-
* Returns the per-sourceType timeout (ms) used by addMediaSource. The
|
|
615
|
-
* defaults are intentionally larger than the cpp-layer timeout in
|
|
616
|
-
* SourceManagerProxy so that, in the normal case, the cpp side resolves the
|
|
617
|
-
* promise first. This JS timer is the last-resort safety net in case the
|
|
618
|
-
* cpp side itself fails to emit any callback (older builds, ipc lost, etc.).
|
|
619
|
-
*/
|
|
620
654
|
getAddMediaSourceTimeoutMs(sourceType) {
|
|
621
655
|
switch (sourceType) {
|
|
622
656
|
case types_1.TRTCMediaSourceType.kOnlineVideo:
|
|
@@ -701,6 +735,7 @@ class TRTCMediaMixingManager {
|
|
|
701
735
|
}
|
|
702
736
|
}
|
|
703
737
|
yield this.nodeMediaMixingPlugin.updateMediaSource(newMediaSource);
|
|
738
|
+
this._applyMediaSourceParams(newMediaSource, this.sourceList[index]);
|
|
704
739
|
(_a = this.mediaMixingDesigner) === null || _a === void 0 ? void 0 : _a.updateMedia({
|
|
705
740
|
id: `${mediaSource.sourceType}__${mediaSource.sourceId}`,
|
|
706
741
|
rect: mediaSource.rect,
|
|
@@ -713,6 +748,9 @@ class TRTCMediaMixingManager {
|
|
|
713
748
|
}
|
|
714
749
|
/**
|
|
715
750
|
* 设置摄像头采集参数
|
|
751
|
+
*
|
|
752
|
+
* @deprecated 请使用 `addMediaSource` 或 `updateMediaSource` 代替
|
|
753
|
+
*
|
|
716
754
|
* @param cameraID {string} - 摄像头 ID
|
|
717
755
|
* @param params {TRTCCameraCaptureParams} - 摄像头采集参数
|
|
718
756
|
*/
|
|
@@ -731,6 +769,8 @@ class TRTCMediaMixingManager {
|
|
|
731
769
|
}
|
|
732
770
|
/**
|
|
733
771
|
* 设置手机投屏参数
|
|
772
|
+
*
|
|
773
|
+
* @deprecated
|
|
734
774
|
* @private
|
|
735
775
|
* @param phoneMirrorSourceId {string} - 手机投屏媒体源 ID
|
|
736
776
|
* @param param {TRTCPhoneMirrorParam} - 手机投屏参数
|
|
@@ -740,6 +780,9 @@ class TRTCMediaMixingManager {
|
|
|
740
780
|
}
|
|
741
781
|
/**
|
|
742
782
|
* 设置屏幕采集参数
|
|
783
|
+
*
|
|
784
|
+
* @deprecated 请使用 `addMediaSource` 或 `updateMediaSource` 代替
|
|
785
|
+
*
|
|
743
786
|
* @param screenOrWindowID {String} - 屏幕 ID 或 窗口 ID
|
|
744
787
|
* @param property {TRTCScreenCaptureProperty} - 屏幕采集属性
|
|
745
788
|
*/
|
|
@@ -748,6 +791,9 @@ class TRTCMediaMixingManager {
|
|
|
748
791
|
}
|
|
749
792
|
/**
|
|
750
793
|
* 设置在线视频源播放参数
|
|
794
|
+
*
|
|
795
|
+
* @deprecated 请使用 `addMediaSource` 或 `updateMediaSource` 代替
|
|
796
|
+
*
|
|
751
797
|
* @param url {string} - 在线视频源 URL
|
|
752
798
|
* @param param {TRTCOnlineVideoParam} - 在线视频源播放参数
|
|
753
799
|
*/
|
|
@@ -756,6 +802,9 @@ class TRTCMediaMixingManager {
|
|
|
756
802
|
}
|
|
757
803
|
/**
|
|
758
804
|
* 设置视频文件播放参数
|
|
805
|
+
*
|
|
806
|
+
* @deprecated 请使用 `addMediaSource` 或 `updateMediaSource` 代替
|
|
807
|
+
*
|
|
759
808
|
* @param videoFilePath {string} - 视频文件路径
|
|
760
809
|
* @param param {TRTCVideoFileParam} - 视频文件播放参数
|
|
761
810
|
*/
|
|
@@ -1294,6 +1343,13 @@ class TRTCMediaMixingManager {
|
|
|
1294
1343
|
}
|
|
1295
1344
|
let flag = false;
|
|
1296
1345
|
if (data.errCode === 0) {
|
|
1346
|
+
const addedIndex = this.findMediaSourceIndex({
|
|
1347
|
+
sourceId: data.sourceId,
|
|
1348
|
+
sourceType: data.sourceType,
|
|
1349
|
+
});
|
|
1350
|
+
if (addedIndex !== -1) {
|
|
1351
|
+
this._applyMediaSourceParams(this.sourceList[addedIndex]);
|
|
1352
|
+
}
|
|
1297
1353
|
flag = this.promiseStore.resolvePromise(promiseKey, undefined);
|
|
1298
1354
|
}
|
|
1299
1355
|
else {
|
|
@@ -1434,42 +1490,71 @@ class TRTCMediaMixingManager {
|
|
|
1434
1490
|
else {
|
|
1435
1491
|
this.sourceList = [];
|
|
1436
1492
|
(_a = this.mediaMixingDesigner) === null || _a === void 0 ? void 0 : _a.removeAllMedia();
|
|
1437
|
-
(_b = this.eventEmitter) === null || _b === void 0 ? void 0 : _b.emit(TRTCMediaMixingEvent.onMediaMixingServerLost);
|
|
1438
1493
|
}
|
|
1494
|
+
// Notify the application layer AFTER the internal recovery/cleanup finishes,
|
|
1495
|
+
// regardless of autoControlServer mode. This lets the app perform extra
|
|
1496
|
+
// recovery on top of the SDK's built-in one (e.g. re-applying beauty /
|
|
1497
|
+
// xmagic effect plugins, which the SDK does not restore). Note
|
|
1498
|
+
// recoverMediaMixingServer swallows its own errors, so this emit is always
|
|
1499
|
+
// reached once server-lost handling completes.
|
|
1500
|
+
(_b = this.eventEmitter) === null || _b === void 0 ? void 0 : _b.emit(TRTCMediaMixingEvent.onMediaMixingServerLost);
|
|
1439
1501
|
});
|
|
1440
1502
|
}
|
|
1441
1503
|
onCallExperimentalAPIFinish(data) {
|
|
1442
1504
|
logger_1.default.log(`${this.logPrefix}onCallExperimentalAPIFinish:`, data);
|
|
1443
1505
|
}
|
|
1444
1506
|
recoverMediaMixingServer() {
|
|
1445
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
1507
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
1446
1508
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1447
1509
|
if (!this.view) {
|
|
1448
1510
|
return;
|
|
1449
1511
|
}
|
|
1450
1512
|
try {
|
|
1451
|
-
|
|
1513
|
+
// Restart the server in the SAME mode as the pre-crash preview target,
|
|
1514
|
+
// derived from windowID the same way bindPreviewArea dispatches:
|
|
1515
|
+
// - windowID !== 0 -> native-window preview -> Independent
|
|
1516
|
+
// - windowID === 0 -> web-element preview -> Embedded
|
|
1517
|
+
// Using the matching mode here makes the subsequent bindPreviewArea ->
|
|
1518
|
+
// ensureMediaServerMode a no-op (server already running in the right
|
|
1519
|
+
// mode), avoiding an extra stop/start process bounce and a transient
|
|
1520
|
+
// window running in the wrong mode. Previously this hardcoded the default
|
|
1521
|
+
// (Independent), so recovering a web-element (Embedded) preview would
|
|
1522
|
+
// start Independent and then immediately stop+restart as Embedded.
|
|
1523
|
+
const recoverMode = this.windowID !== 0
|
|
1524
|
+
? TRTCMediaMixingServerMode.Independent
|
|
1525
|
+
: TRTCMediaMixingServerMode.Embedded;
|
|
1526
|
+
yield this.startMediaMixingServer('', recoverMode);
|
|
1452
1527
|
yield this.bindPreviewArea(this.windowID, this.view);
|
|
1453
1528
|
yield this.startPublish();
|
|
1454
1529
|
yield this.nodeMediaMixingPlugin.updatePublishParams(this.publishParams);
|
|
1455
|
-
|
|
1530
|
+
// 混流服务崩溃重启后,底层 NodeRemoteVideoPluginManager 为全新初始状态,
|
|
1531
|
+
// 需要重放之前通过 setPluginParams 设置的插件参数。
|
|
1532
|
+
const pluginManager = this.pluginManager;
|
|
1533
|
+
const pluginParams = (_a = this.trtcParamsStore) === null || _a === void 0 ? void 0 : _a.pluginParams;
|
|
1534
|
+
if (pluginManager && pluginParams) {
|
|
1535
|
+
Object.keys(pluginParams).forEach((typeKey) => {
|
|
1536
|
+
pluginManager.setPluginParams(Number(typeKey), pluginParams[typeKey]);
|
|
1537
|
+
});
|
|
1538
|
+
}
|
|
1539
|
+
if ((_b = this.paramsStore) === null || _b === void 0 ? void 0 : _b.streamLayout) {
|
|
1456
1540
|
this.setStreamLayout(this.paramsStore.streamLayout);
|
|
1457
1541
|
}
|
|
1458
1542
|
this.sourceList.forEach((item) => {
|
|
1543
|
+
this._applyCameraParamsBeforeAdd(item);
|
|
1459
1544
|
this.nodeMediaMixingPlugin.addMediaSource(item);
|
|
1460
1545
|
});
|
|
1461
|
-
if (((
|
|
1546
|
+
if (((_c = this.trtcParamsStore) === null || _c === void 0 ? void 0 : _c.enterRoomParams) && ((_d = this.trtcParamsStore) === null || _d === void 0 ? void 0 : _d.enterRoomScene)) {
|
|
1462
1547
|
this.nodeTRTCCloud.enterRoom(this.trtcParamsStore.enterRoomParams, this.trtcParamsStore.enterRoomScene);
|
|
1463
1548
|
}
|
|
1464
|
-
if ((
|
|
1465
|
-
if ((
|
|
1466
|
-
this.nodeTRTCCloud.startLocalAudio((
|
|
1549
|
+
if ((_e = this.trtcParamsStore) === null || _e === void 0 ? void 0 : _e.localAudioParams) {
|
|
1550
|
+
if ((_f = this.trtcParamsStore) === null || _f === void 0 ? void 0 : _f.localAudioParams.audioQuality) {
|
|
1551
|
+
this.nodeTRTCCloud.startLocalAudio((_g = this.trtcParamsStore) === null || _g === void 0 ? void 0 : _g.localAudioParams.audioQuality);
|
|
1467
1552
|
}
|
|
1468
|
-
if (((
|
|
1553
|
+
if (((_h = this.trtcParamsStore) === null || _h === void 0 ? void 0 : _h.localAudioParams.isMute) !== undefined) {
|
|
1469
1554
|
this.nodeTRTCCloud.muteLocalAudio(this.trtcParamsStore.localAudioParams.isMute);
|
|
1470
1555
|
}
|
|
1471
1556
|
}
|
|
1472
|
-
if ((
|
|
1557
|
+
if ((_j = this.trtcParamsStore) === null || _j === void 0 ? void 0 : _j.systemAudioParams) {
|
|
1473
1558
|
if (this.trtcParamsStore.systemAudioParams.isOpen) {
|
|
1474
1559
|
this.nodeTRTCCloud.startSystemAudioLoopback(this.trtcParamsStore.systemAudioParams.path || null);
|
|
1475
1560
|
}
|
|
@@ -1477,9 +1562,9 @@ class TRTCMediaMixingManager {
|
|
|
1477
1562
|
this.nodeTRTCCloud.setSystemAudioLoopbackVolume(this.trtcParamsStore.systemAudioParams.volume);
|
|
1478
1563
|
}
|
|
1479
1564
|
}
|
|
1480
|
-
if (typeof ((
|
|
1481
|
-
const isEnabled = ((
|
|
1482
|
-
const interval = ((
|
|
1565
|
+
if (typeof ((_k = this.trtcParamsStore) === null || _k === void 0 ? void 0 : _k.audioVolumeEvaluationInterval) === 'number') {
|
|
1566
|
+
const isEnabled = ((_l = this.trtcParamsStore) === null || _l === void 0 ? void 0 : _l.audioVolumeEvaluationInterval) > 0;
|
|
1567
|
+
const interval = ((_m = this.trtcParamsStore) === null || _m === void 0 ? void 0 : _m.audioVolumeEvaluationInterval) > 0 ? (_o = this.trtcParamsStore) === null || _o === void 0 ? void 0 : _o.audioVolumeEvaluationInterval : 0;
|
|
1483
1568
|
this.nodeTRTCCloud.enableAudioVolumeEvaluation(isEnabled, {
|
|
1484
1569
|
enableSpectrumCalculation: isEnabled,
|
|
1485
1570
|
enableVadDetection: true,
|
|
@@ -1497,17 +1582,115 @@ class TRTCMediaMixingManager {
|
|
|
1497
1582
|
logger_1.default.debug(`${this.logPrefix}onDevicePixelRatioChange:`, window.devicePixelRatio);
|
|
1498
1583
|
this.setDisplayRect();
|
|
1499
1584
|
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1585
|
+
/**
|
|
1586
|
+
* @private
|
|
1587
|
+
* Apply camera capture params BEFORE native addMediaSource.
|
|
1588
|
+
*
|
|
1589
|
+
* Calling setCameraCaptureParam after the camera has already been added
|
|
1590
|
+
* triggers an extra camera restart (the camera first starts with default
|
|
1591
|
+
* params and then restarts with the new ones). To avoid this we set
|
|
1592
|
+
* camera params up-front for the add path. For all other source types
|
|
1593
|
+
* the corresponding setters are dispatched in the post-add callback
|
|
1594
|
+
* (`onMediaSourceAdded` -> `_applyMediaSourceParams`).
|
|
1595
|
+
*/
|
|
1596
|
+
_applyCameraParamsBeforeAdd(mediaSource) {
|
|
1597
|
+
if (mediaSource.sourceType === types_1.TRTCMediaSourceType.kCamera && mediaSource.camera) {
|
|
1598
|
+
this.setCameraCaptureParam(mediaSource.sourceId, mediaSource.camera);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
/**
|
|
1602
|
+
* @private
|
|
1603
|
+
* Apply capture params from TRTCMediaSource to the native plugin.
|
|
1604
|
+
*
|
|
1605
|
+
* This method is called after media source is added or updated. To avoid
|
|
1606
|
+
* costly side-effects of native setters (e.g. setCameraCaptureParam will
|
|
1607
|
+
* restart the camera), the setter is invoked only when params are actually
|
|
1608
|
+
* provided AND differ from the previous value carried by `oldMediaSource`.
|
|
1609
|
+
*
|
|
1610
|
+
* Camera handling differs by phase:
|
|
1611
|
+
* - Add path (oldMediaSource is undefined): camera params have been set
|
|
1612
|
+
* before native addMediaSource via `_applyCameraParamsBeforeAdd`, so
|
|
1613
|
+
* this method skips kCamera to avoid duplicate setter invocation.
|
|
1614
|
+
* - Update path (oldMediaSource is provided): kCamera goes through the
|
|
1615
|
+
* same diff check as other types and is dispatched only when changed.
|
|
1616
|
+
*
|
|
1617
|
+
* @param mediaSource - The new media source carrying capture params.
|
|
1618
|
+
* @param oldMediaSource - The previous media source (omit for the add path
|
|
1619
|
+
* where no previous params exist; in that case the
|
|
1620
|
+
* setter is always invoked when params are present).
|
|
1621
|
+
*/
|
|
1622
|
+
_applyMediaSourceParams(mediaSource, oldMediaSource) {
|
|
1623
|
+
switch (mediaSource.sourceType) {
|
|
1624
|
+
case types_1.TRTCMediaSourceType.kCamera:
|
|
1625
|
+
// Skip kCamera on the add path to avoid an extra camera restart;
|
|
1626
|
+
// it has been handled by `_applyCameraParamsBeforeAdd` already.
|
|
1627
|
+
if (oldMediaSource && mediaSource.camera && !this._isSameCaptureParams(mediaSource.camera, oldMediaSource.camera)) {
|
|
1628
|
+
this.setCameraCaptureParam(mediaSource.sourceId, mediaSource.camera);
|
|
1506
1629
|
}
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1630
|
+
break;
|
|
1631
|
+
case types_1.TRTCMediaSourceType.kScreen:
|
|
1632
|
+
if (mediaSource.screen && !this._isSameCaptureParams(mediaSource.screen, oldMediaSource === null || oldMediaSource === void 0 ? void 0 : oldMediaSource.screen)) {
|
|
1633
|
+
this.setScreenCaptureProperty(mediaSource.sourceId, mediaSource.screen);
|
|
1634
|
+
}
|
|
1635
|
+
break;
|
|
1636
|
+
case types_1.TRTCMediaSourceType.kOnlineVideo:
|
|
1637
|
+
if (mediaSource.onlineVideo && !this._isSameCaptureParams(mediaSource.onlineVideo, oldMediaSource === null || oldMediaSource === void 0 ? void 0 : oldMediaSource.onlineVideo)) {
|
|
1638
|
+
this.setOnlineVideoParam(mediaSource.sourceId, mediaSource.onlineVideo);
|
|
1639
|
+
}
|
|
1640
|
+
break;
|
|
1641
|
+
case types_1.TRTCMediaSourceType.kVideoFile:
|
|
1642
|
+
if (mediaSource.localVideo && !this._isSameCaptureParams(mediaSource.localVideo, oldMediaSource === null || oldMediaSource === void 0 ? void 0 : oldMediaSource.localVideo)) {
|
|
1643
|
+
this.setVideoFileParam(mediaSource.sourceId, mediaSource.localVideo);
|
|
1510
1644
|
}
|
|
1645
|
+
break;
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
/**
|
|
1649
|
+
* @private
|
|
1650
|
+
* Shallow-but-stable equality check on capture param objects via JSON.
|
|
1651
|
+
*
|
|
1652
|
+
* Returns true when both sides represent the "same" params, false otherwise.
|
|
1653
|
+
* Semantics:
|
|
1654
|
+
* - both empty (undefined / null) → true (no change requested)
|
|
1655
|
+
* - exactly one side empty → false (first-time apply or transition)
|
|
1656
|
+
* - both non-empty → byte-equal after JSON.stringify
|
|
1657
|
+
*
|
|
1658
|
+
* Note: JSON.stringify is sensitive to key ordering. Capture param objects
|
|
1659
|
+
* carried by `TRTCMediaSource` are constructed by the SDK via
|
|
1660
|
+
* `JSON.parse(JSON.stringify(...))` flow, so key order is stable in
|
|
1661
|
+
* practice; for caller-supplied literal objects with unstable key order,
|
|
1662
|
+
* the comparison may yield a false-negative and trigger an unnecessary
|
|
1663
|
+
* setter call.
|
|
1664
|
+
*/
|
|
1665
|
+
_isSameCaptureParams(next, prev) {
|
|
1666
|
+
if (next === prev) {
|
|
1667
|
+
return true;
|
|
1668
|
+
}
|
|
1669
|
+
const nextEmpty = next === undefined || next === null;
|
|
1670
|
+
const prevEmpty = prev === undefined || prev === null;
|
|
1671
|
+
if (nextEmpty && prevEmpty) {
|
|
1672
|
+
return true;
|
|
1673
|
+
}
|
|
1674
|
+
if (nextEmpty || prevEmpty) {
|
|
1675
|
+
return false;
|
|
1676
|
+
}
|
|
1677
|
+
try {
|
|
1678
|
+
return JSON.stringify(next) === JSON.stringify(prev);
|
|
1679
|
+
}
|
|
1680
|
+
catch (err) {
|
|
1681
|
+
logger_1.default.warn(`${this.logPrefix}_isSameCaptureParams: stringify failed, treat as different.`, err);
|
|
1682
|
+
return false;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
previewInNativeWindow(viewOrRegion) {
|
|
1686
|
+
var _a;
|
|
1687
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1688
|
+
try {
|
|
1689
|
+
yield this.ensureMediaServerMode(TRTCMediaMixingServerMode.Independent);
|
|
1690
|
+
}
|
|
1691
|
+
catch (err) {
|
|
1692
|
+
logger_1.default.error(`${this.logPrefix}previewInNativeWindow ensureMediaServerMode failed:`, err);
|
|
1693
|
+
throw err;
|
|
1511
1694
|
}
|
|
1512
1695
|
if (viewOrRegion instanceof HTMLElement) {
|
|
1513
1696
|
if (this.view !== viewOrRegion) {
|
|
@@ -1530,19 +1713,22 @@ class TRTCMediaMixingManager {
|
|
|
1530
1713
|
this.destroyDesigner();
|
|
1531
1714
|
this.nodeMediaMixingPlugin.setDisplayParams(this.windowID, viewOrRegion);
|
|
1532
1715
|
}
|
|
1716
|
+
if (!((_a = this.paramsStore) === null || _a === void 0 ? void 0 : _a.streamLayout)) {
|
|
1717
|
+
this.setStreamLayout({
|
|
1718
|
+
layoutMode: types_1.TRTCStreamLayoutMode.None,
|
|
1719
|
+
});
|
|
1720
|
+
}
|
|
1533
1721
|
});
|
|
1534
1722
|
}
|
|
1535
1723
|
previewInWebElement(viewOrRegion) {
|
|
1724
|
+
var _a;
|
|
1536
1725
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
}
|
|
1542
|
-
|
|
1543
|
-
logger_1.default.error(`${this.logPrefix}previewInWebElement startMediaMixingServer failed:`, err);
|
|
1544
|
-
throw err;
|
|
1545
|
-
}
|
|
1726
|
+
try {
|
|
1727
|
+
yield this.ensureMediaServerMode(TRTCMediaMixingServerMode.Embedded);
|
|
1728
|
+
}
|
|
1729
|
+
catch (err) {
|
|
1730
|
+
logger_1.default.error(`${this.logPrefix}previewInWebElement ensureMediaServerMode failed:`, err);
|
|
1731
|
+
throw err;
|
|
1546
1732
|
}
|
|
1547
1733
|
if (viewOrRegion instanceof HTMLElement) {
|
|
1548
1734
|
if (this.view !== viewOrRegion) {
|
|
@@ -1559,6 +1745,11 @@ class TRTCMediaMixingManager {
|
|
|
1559
1745
|
this.createDesigner();
|
|
1560
1746
|
}
|
|
1561
1747
|
}
|
|
1748
|
+
if (!((_a = this.paramsStore) === null || _a === void 0 ? void 0 : _a.streamLayout)) {
|
|
1749
|
+
this.setStreamLayout({
|
|
1750
|
+
layoutMode: types_1.TRTCStreamLayoutMode.None,
|
|
1751
|
+
});
|
|
1752
|
+
}
|
|
1562
1753
|
}
|
|
1563
1754
|
else {
|
|
1564
1755
|
// neither native window nor web element, stop preview
|
|
@@ -1567,12 +1758,83 @@ class TRTCMediaMixingManager {
|
|
|
1567
1758
|
});
|
|
1568
1759
|
}
|
|
1569
1760
|
previewInNone() {
|
|
1761
|
+
var _a;
|
|
1570
1762
|
this.destroyResizeObserver();
|
|
1571
1763
|
this.destroyLayoutManager();
|
|
1572
1764
|
this.destroyDesigner();
|
|
1573
1765
|
this.destroyWebRenderer();
|
|
1574
1766
|
this.view = null;
|
|
1575
1767
|
this.nodeMediaMixingPlugin.setDisplayParams(this.windowID, { left: 0, right: 0, top: 0, bottom: 0 });
|
|
1768
|
+
if ((_a = this.paramsStore) === null || _a === void 0 ? void 0 : _a.streamLayout) {
|
|
1769
|
+
this.paramsStore.streamLayout = null;
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
/**
|
|
1773
|
+
* @private
|
|
1774
|
+
* Ensure the media server is running in the mode required by the current
|
|
1775
|
+
* preview target, before doing any preview binding.
|
|
1776
|
+
*
|
|
1777
|
+
* - Native-window preview -> Independent server (out-of-process, comes
|
|
1778
|
+
* with onMediaServerState crash monitoring & auto-recovery).
|
|
1779
|
+
* - Web-element preview -> Embedded server (in-process) that drives
|
|
1780
|
+
* the video-frame render callback.
|
|
1781
|
+
*
|
|
1782
|
+
* The decision is driven by `serverStatus` (the single source of truth),
|
|
1783
|
+
* NOT by `serverMode`. `serverMode` only reflects the mode of a *running*
|
|
1784
|
+
* server and becomes meaningless once the server is stopped (Idle), where
|
|
1785
|
+
* it keeps its last value. Keying the switch on `serverStatus` avoids that
|
|
1786
|
+
* stale-value trap:
|
|
1787
|
+
*
|
|
1788
|
+
* - running (Started/Starting) in a different mode -> stop then restart in
|
|
1789
|
+
* the required mode (mode switch).
|
|
1790
|
+
* - running already in the required mode -> no-op.
|
|
1791
|
+
* - Idle (e.g. after stopMediaMixingServer on logout) -> (re)start in the
|
|
1792
|
+
* required mode. Without this, a logout -> login cycle would leave no
|
|
1793
|
+
* monitored server, so a later crash of liteav_media_server.exe emits no
|
|
1794
|
+
* state=3 event and neither the SDK's built-in recovery nor the app-layer
|
|
1795
|
+
* recovery runs.
|
|
1796
|
+
*
|
|
1797
|
+
* `Lost` handling depends on autoControlServer, so the two recovery paths
|
|
1798
|
+
* never overlap / race:
|
|
1799
|
+
*
|
|
1800
|
+
* - autoControlServer = true (getMediaMixingManager): the SDK owns crash
|
|
1801
|
+
* recovery via onMediaServerState(state=3) -> recoverMediaMixingServer,
|
|
1802
|
+
* which restarts the server AND re-binds the preview itself. We must NOT
|
|
1803
|
+
* also restart here, otherwise a concurrent app-driven bindPreviewArea
|
|
1804
|
+
* would double-start the server and race the built-in recovery. So when
|
|
1805
|
+
* autoControlServer is true, `Lost` is intentionally left untouched here.
|
|
1806
|
+
*
|
|
1807
|
+
* - autoControlServer = false (getMediaMixingService): the SDK does NOT
|
|
1808
|
+
* auto-recover (onMediaMixingServerLost only clears local state); the app
|
|
1809
|
+
* is expected to drive recovery by calling bindPreviewArea again. In that
|
|
1810
|
+
* case a `Lost` server must be (re)started here, exactly like `Idle`,
|
|
1811
|
+
* otherwise the app's re-bind would silently do nothing and the preview
|
|
1812
|
+
* would never come back.
|
|
1813
|
+
*
|
|
1814
|
+
* Safe against the first-launch path: startMediaMixingServer sets
|
|
1815
|
+
* serverStatus to Starting synchronously, and the constructor's embedded
|
|
1816
|
+
* auto-start runs before any bindPreviewArea, so the first bind never
|
|
1817
|
+
* observes Idle here.
|
|
1818
|
+
*/
|
|
1819
|
+
ensureMediaServerMode(targetMode) {
|
|
1820
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1821
|
+
const isRunning = this.serverStatus === TRTCMediaMixingServerStatus.Started
|
|
1822
|
+
|| this.serverStatus === TRTCMediaMixingServerStatus.Starting;
|
|
1823
|
+
// `Lost` is treated as "needs (re)start" ONLY when the SDK's own auto
|
|
1824
|
+
// recovery is disabled (autoControlServer=false); otherwise it is owned by
|
|
1825
|
+
// recoverMediaMixingServer and must not be touched here (see doc above).
|
|
1826
|
+
const needsStart = this.serverStatus === TRTCMediaMixingServerStatus.Idle
|
|
1827
|
+
|| (this.serverStatus === TRTCMediaMixingServerStatus.Lost && !this.autoControlServer);
|
|
1828
|
+
if (isRunning) {
|
|
1829
|
+
if (this.serverMode !== targetMode) {
|
|
1830
|
+
yield this.stopMediaMixingServer();
|
|
1831
|
+
yield this.startMediaMixingServer('', targetMode);
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
else if (needsStart) {
|
|
1835
|
+
yield this.startMediaMixingServer('', targetMode);
|
|
1836
|
+
}
|
|
1837
|
+
});
|
|
1576
1838
|
}
|
|
1577
1839
|
createWebRenderer(view) {
|
|
1578
1840
|
if (this.view === view) {
|
|
@@ -1603,7 +1865,7 @@ class TRTCMediaMixingManager {
|
|
|
1603
1865
|
});
|
|
1604
1866
|
this.webRenderer.setContentMode(this.previewRenderParams.fillMode);
|
|
1605
1867
|
this.createWebRendererBuffer();
|
|
1606
|
-
this.nodeMediaMixingPlugin.setVideoFrameRenderCallback(this.webRendererCallback); // this.pixelFormat,
|
|
1868
|
+
this.nodeMediaMixingPlugin.setVideoFrameRenderCallback(this.webRendererCallback); // this.pixelFormat,
|
|
1607
1869
|
}
|
|
1608
1870
|
}
|
|
1609
1871
|
destroyWebRenderer() {
|
|
@@ -1611,7 +1873,7 @@ class TRTCMediaMixingManager {
|
|
|
1611
1873
|
this.webRenderer.destroy();
|
|
1612
1874
|
this.webRenderer = null;
|
|
1613
1875
|
}
|
|
1614
|
-
this.nodeMediaMixingPlugin.setVideoFrameRenderCallback(null); // this.pixelFormat,
|
|
1876
|
+
this.nodeMediaMixingPlugin.setVideoFrameRenderCallback(null); // this.pixelFormat,
|
|
1615
1877
|
this.destroyWebRendererBuffer();
|
|
1616
1878
|
}
|
|
1617
1879
|
createWebRendererBuffer() {
|
|
@@ -39,6 +39,13 @@ export declare type TRTCPhoneMirrorParam = {
|
|
|
39
39
|
frameRate: number;
|
|
40
40
|
bitrateKbps: number;
|
|
41
41
|
};
|
|
42
|
+
export declare type TRTCOnlineVideoParam = {
|
|
43
|
+
networkCacheSizeKB: number;
|
|
44
|
+
playoutVolume: number;
|
|
45
|
+
};
|
|
46
|
+
export declare type TRTCVideoFileParam = {
|
|
47
|
+
playoutVolume: number;
|
|
48
|
+
};
|
|
42
49
|
export declare type TRTCMediaSource = {
|
|
43
50
|
sourceType: TRTCMediaSourceType;
|
|
44
51
|
sourceId: string;
|
|
@@ -49,6 +56,10 @@ export declare type TRTCMediaSource = {
|
|
|
49
56
|
rotation?: TRTCVideoRotation;
|
|
50
57
|
fillMode?: TRTCVideoFillMode;
|
|
51
58
|
mirrorType?: TRTCVideoMirrorType;
|
|
59
|
+
camera?: TRTCCameraCaptureParams;
|
|
60
|
+
screen?: TRTCScreenCaptureProperty;
|
|
61
|
+
localVideo?: TRTCVideoFileParam;
|
|
62
|
+
onlineVideo?: TRTCOnlineVideoParam;
|
|
52
63
|
};
|
|
53
64
|
export declare type TRTCMediaMixingEncParam = {
|
|
54
65
|
videoEncoderParams: TRTCVideoEncParam;
|
|
@@ -83,20 +94,10 @@ export declare type TRTCStreamLayout = {
|
|
|
83
94
|
};
|
|
84
95
|
streams?: Array<TRTCStreamInfo>;
|
|
85
96
|
};
|
|
86
|
-
export declare type TRTCOnlineVideoParam = {
|
|
87
|
-
networkCacheSizeKB: number;
|
|
88
|
-
playoutVolume: number;
|
|
89
|
-
};
|
|
90
|
-
export declare type TRTCVideoFileParam = {
|
|
91
|
-
playoutVolume: number;
|
|
92
|
-
};
|
|
93
97
|
export interface ITRTCMediaMixingManager {
|
|
94
98
|
addMediaSource(mediaSource: TRTCMediaSource): Promise<void>;
|
|
95
99
|
removeMediaSource(mediaSource: TRTCMediaSource): Promise<void>;
|
|
96
100
|
updateMediaSource(mediaSource: TRTCMediaSource): Promise<void>;
|
|
97
|
-
setCameraCaptureParam(cameraID: string, param: TRTCCameraCaptureParams): void;
|
|
98
|
-
setPhoneMirrorParam(phoneMirrorSourceId: string, param: TRTCPhoneMirrorParam): void;
|
|
99
|
-
setScreenCaptureProperty(screenWindowID: string, property: TRTCScreenCaptureProperty): void;
|
|
100
101
|
startPublish(): Promise<void>;
|
|
101
102
|
stopPublish(): Promise<void>;
|
|
102
103
|
updatePublishParams(params: TRTCMediaMixingEncParam): Promise<void>;
|
package/liteav/trtc.js
CHANGED
|
@@ -4939,6 +4939,9 @@ class TRTCCloud extends events_1.EventEmitter {
|
|
|
4939
4939
|
setPluginParams(type, options) {
|
|
4940
4940
|
this.logger.log(`setPluginParams params:`, type, options);
|
|
4941
4941
|
this.pluginManager.setPluginParams(type, options);
|
|
4942
|
+
// 记录插件参数,用于本地混流服务崩溃恢复时重放(合并写入,兼容分次只传 pixelFormat 或 enable 的调用)
|
|
4943
|
+
this.paramsStore.pluginParams = this.paramsStore.pluginParams || {};
|
|
4944
|
+
this.paramsStore.pluginParams[type] = Object.assign(Object.assign({}, (this.paramsStore.pluginParams[type] || {})), options);
|
|
4942
4945
|
}
|
|
4943
4946
|
/**
|
|
4944
4947
|
* 添加插件
|
|
@@ -5434,6 +5437,10 @@ class TRTCCloud extends events_1.EventEmitter {
|
|
|
5434
5437
|
try {
|
|
5435
5438
|
const json = JSON.parse(jsonStr);
|
|
5436
5439
|
const { api, params } = json;
|
|
5440
|
+
if (this._isMacPlatform() && api === 'TuikitLog') {
|
|
5441
|
+
this.logger.info(`TuikitLog: ${jsonStr}`);
|
|
5442
|
+
return;
|
|
5443
|
+
}
|
|
5437
5444
|
if (this[api] && typeof this[api] === 'function') {
|
|
5438
5445
|
this[api](params);
|
|
5439
5446
|
}
|
|
@@ -5564,6 +5571,7 @@ class TRTCCloud extends events_1.EventEmitter {
|
|
|
5564
5571
|
nodeTRTCCloud: this.rtcCloud,
|
|
5565
5572
|
trtcParamsStore: this.paramsStore,
|
|
5566
5573
|
autoControlServer: true,
|
|
5574
|
+
pluginManager: this.pluginManager,
|
|
5567
5575
|
});
|
|
5568
5576
|
}
|
|
5569
5577
|
}
|
|
@@ -5613,6 +5621,7 @@ class TRTCCloud extends events_1.EventEmitter {
|
|
|
5613
5621
|
nodeTRTCCloud: this.rtcCloud,
|
|
5614
5622
|
trtcParamsStore: this.paramsStore,
|
|
5615
5623
|
autoControlServer: false,
|
|
5624
|
+
pluginManager: this.pluginManager,
|
|
5616
5625
|
});
|
|
5617
5626
|
this.mediaMixingService = new MediaMixingManager_1.TRTCMediaMixingService(this.mediaMixingManager);
|
|
5618
5627
|
}
|
package/package.json
CHANGED
package/scripts/download.js
CHANGED
|
@@ -111,9 +111,17 @@ async function main(urlDomain) {
|
|
|
111
111
|
await download(downloadUrl, outputDir, downloadOptions);
|
|
112
112
|
signale.success(`Download finished - ${platform}`);
|
|
113
113
|
|
|
114
|
+
// Preserve symlinks when copying on macOS so that .framework bundles
|
|
115
|
+
// retain their canonical Versions/Current -> A symlink structure.
|
|
116
|
+
// Without { dereference: false }, fs-extra resolves symlinks to real
|
|
117
|
+
// files/directories, causing `codesign` to report:
|
|
118
|
+
// "bundle format is ambiguous (could be app or framework)"
|
|
119
|
+
const macCopyOptions = { dereference: false };
|
|
120
|
+
|
|
114
121
|
fs.copySync(
|
|
115
122
|
path.join(outputDir, "./build/Release"),
|
|
116
|
-
path.join(buildDir, "Release")
|
|
123
|
+
path.join(buildDir, "Release"),
|
|
124
|
+
macCopyOptions
|
|
117
125
|
);
|
|
118
126
|
signale.success(`copy success! - ${platform}`);
|
|
119
127
|
|
|
@@ -125,11 +133,13 @@ async function main(urlDomain) {
|
|
|
125
133
|
const arch = archType;
|
|
126
134
|
fs.copySync(
|
|
127
135
|
path.join(outputDir, "./build/Release/trtc_electron_sdk.node"),
|
|
128
|
-
path.join(buildDir, "Release", arch, "trtc_electron_sdk.node")
|
|
136
|
+
path.join(buildDir, "Release", arch, "trtc_electron_sdk.node"),
|
|
137
|
+
macCopyOptions
|
|
129
138
|
);
|
|
130
139
|
fs.copySync(
|
|
131
140
|
path.join(outputDir, "./build/mac-framework", arch),
|
|
132
|
-
path.join(buildDir, "mac-framework", arch)
|
|
141
|
+
path.join(buildDir, "mac-framework", arch),
|
|
142
|
+
macCopyOptions
|
|
133
143
|
);
|
|
134
144
|
signale.success(`copy success! - mac ${arch}`, "\n");
|
|
135
145
|
|
|
@@ -163,7 +173,8 @@ async function main(urlDomain) {
|
|
|
163
173
|
"Release",
|
|
164
174
|
anotherArch,
|
|
165
175
|
"trtc_electron_sdk.node"
|
|
166
|
-
)
|
|
176
|
+
),
|
|
177
|
+
macCopyOptions
|
|
167
178
|
);
|
|
168
179
|
fs.copySync(
|
|
169
180
|
path.join(
|
|
@@ -172,7 +183,8 @@ async function main(urlDomain) {
|
|
|
172
183
|
"/build/mac-framework",
|
|
173
184
|
anotherArch
|
|
174
185
|
),
|
|
175
|
-
path.join(buildDir, "mac-framework", anotherArch)
|
|
186
|
+
path.join(buildDir, "mac-framework", anotherArch),
|
|
187
|
+
macCopyOptions
|
|
176
188
|
);
|
|
177
189
|
signale.success(`copy success! - mac ${anotherArch}`);
|
|
178
190
|
|