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.
@@ -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 {TRTCPhoneMirrorConnectionParam} connectionParam 手机投屏类型媒体源,连接参数
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} TRTCStreamInfo
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 TRTCStreamInfo_HACK_JSDOC = null;
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<TRTCStreamInfo>} userList 非必填,用户视频流布局
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
- yield this.startMediaMixingServer();
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
- if ((_a = this.paramsStore) === null || _a === void 0 ? void 0 : _a.streamLayout) {
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 (((_b = this.trtcParamsStore) === null || _b === void 0 ? void 0 : _b.enterRoomParams) && ((_c = this.trtcParamsStore) === null || _c === void 0 ? void 0 : _c.enterRoomScene)) {
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 ((_d = this.trtcParamsStore) === null || _d === void 0 ? void 0 : _d.localAudioParams) {
1465
- if ((_e = this.trtcParamsStore) === null || _e === void 0 ? void 0 : _e.localAudioParams.audioQuality) {
1466
- this.nodeTRTCCloud.startLocalAudio((_f = this.trtcParamsStore) === null || _f === void 0 ? void 0 : _f.localAudioParams.audioQuality);
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 (((_g = this.trtcParamsStore) === null || _g === void 0 ? void 0 : _g.localAudioParams.isMute) !== undefined) {
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 ((_h = this.trtcParamsStore) === null || _h === void 0 ? void 0 : _h.systemAudioParams) {
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 ((_j = this.trtcParamsStore) === null || _j === void 0 ? void 0 : _j.audioVolumeEvaluationInterval) === 'number') {
1481
- const isEnabled = ((_k = this.trtcParamsStore) === null || _k === void 0 ? void 0 : _k.audioVolumeEvaluationInterval) > 0;
1482
- const interval = ((_l = this.trtcParamsStore) === null || _l === void 0 ? void 0 : _l.audioVolumeEvaluationInterval) > 0 ? (_m = this.trtcParamsStore) === null || _m === void 0 ? void 0 : _m.audioVolumeEvaluationInterval : 0;
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
- previewInNativeWindow(viewOrRegion) {
1501
- return __awaiter(this, void 0, void 0, function* () {
1502
- if (this.serverMode === TRTCMediaMixingServerMode.Embedded && (this.serverStatus === TRTCMediaMixingServerStatus.Started || this.serverStatus === TRTCMediaMixingServerStatus.Starting)) {
1503
- try {
1504
- yield this.stopMediaMixingServer();
1505
- yield this.startMediaMixingServer('', TRTCMediaMixingServerMode.Independent);
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
- catch (err) {
1508
- logger_1.default.error(`${this.logPrefix}previewInNativeWindow startMediaMixingServer failed:`, err);
1509
- throw err;
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
- if (this.serverMode === TRTCMediaMixingServerMode.Independent && (this.serverStatus === TRTCMediaMixingServerStatus.Started || this.serverStatus === TRTCMediaMixingServerStatus.Starting)) {
1538
- try {
1539
- yield this.stopMediaMixingServer();
1540
- yield this.startMediaMixingServer('', TRTCMediaMixingServerMode.Embedded);
1541
- }
1542
- catch (err) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trtc-electron-sdk",
3
- "version": "13.4.801-alpha.0",
3
+ "version": "13.4.802-beta.1",
4
4
  "description": "trtc electron sdk",
5
5
  "main": "./liteav/index.js",
6
6
  "types": "./liteav/index.d.ts",
@@ -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