@rongcloud/plugin-rtc 5.1.10-alpha.3 → 5.2.2-alpha.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/dist/index.umd.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
- * RCRTC - v5.1.10-alpha.3
3
- * CommitId - 799cc871ab8fce4eb595d368ebaa84664d101f6f
4
- * Thu Oct 21 2021 10:04:21 GMT+0800 (China Standard Time)
2
+ * RCRTC - v5.2.2-alpha.1
3
+ * CommitId - de4f9bc28bbee35d2d5f206a68144c89c098573f
4
+ * Mon Nov 22 2021 10:51:42 GMT+0800 (China Standard Time)
5
5
  * ©2020 RongCloud, Inc. All rights reserved.
6
6
  */
7
7
  (function (global, factory) {
@@ -110,8 +110,12 @@
110
110
  RCRTCCode[RCRTCCode["PACKAGE_ENVIRONMENT_ERROR"] = 53025] = "PACKAGE_ENVIRONMENT_ERROR";
111
111
  /** 单个用户发布资源超过限制 ( MediaServer 限制最多 10 个 track ) */
112
112
  RCRTCCode[RCRTCCode["PUBLISH_TRACK_LIMIT_EXCEEDED"] = 53026] = "PUBLISH_TRACK_LIMIT_EXCEEDED";
113
+ /** 房间内无主播推 CDN */
114
+ RCRTCCode[RCRTCCode["CDN_RESOURCE_IS_EMPTY"] = 53027] = "CDN_RESOURCE_IS_EMPTY";
113
115
  /** 加入 RTC 房间 joinTYype 为 1 时,当前有其他端在房间时的应答码 */
114
- RCRTCCode[RCRTCCode["SIGNAL_JOIN_RTC_ROOM_REFUSED"] = 53207] = "SIGNAL_JOIN_RTC_ROOM_REFUSED";
116
+ RCRTCCode[RCRTCCode["SIGNAL_JOIN_RTC_ROOM_REFUSED"] = 53028] = "SIGNAL_JOIN_RTC_ROOM_REFUSED";
117
+ /** 设置音频输出设备时,无权限使用请求的设备 */
118
+ RCRTCCode[RCRTCCode["NO_PERMISSION_TO_USE_REQUESTED_DEVICE"] = 53029] = "NO_PERMISSION_TO_USE_REQUESTED_DEVICE";
115
119
  })(exports.RCRTCCode || (exports.RCRTCCode = {}));
116
120
  /**
117
121
  * RTC 信令 Server 返回需处理的错误 Code
@@ -5656,6 +5660,33 @@
5656
5660
  return rate;
5657
5661
  };
5658
5662
 
5663
+ /**
5664
+ * 获取 Microphone 列表
5665
+ */
5666
+ const getMicrophones = () => __awaiter(void 0, void 0, void 0, function* () {
5667
+ const mediaDivices = yield navigator.mediaDevices.enumerateDevices();
5668
+ return mediaDivices.filter(item => item.kind === 'audioinput');
5669
+ });
5670
+ /**
5671
+ * 获取摄像头设备列表
5672
+ */
5673
+ const getCameras = () => __awaiter(void 0, void 0, void 0, function* () {
5674
+ const mediaDevices = yield navigator.mediaDevices.enumerateDevices();
5675
+ return mediaDevices.filter(item => item.kind === 'videoinput');
5676
+ });
5677
+ /**
5678
+ * 获取扬声器设备列表
5679
+ */
5680
+ const getSpeakers = () => __awaiter(void 0, void 0, void 0, function* () {
5681
+ const mediaDevices = yield navigator.mediaDevices.enumerateDevices();
5682
+ return mediaDevices.filter(item => item.kind === 'audiooutput');
5683
+ });
5684
+ const device = {
5685
+ getCameras,
5686
+ getMicrophones,
5687
+ getSpeakers
5688
+ };
5689
+
5659
5690
  class RCTrack extends engine.EventEmitter {
5660
5691
  constructor(_tag, _userId, _kind, _isLocalTrack, _roomId) {
5661
5692
  super();
@@ -5793,6 +5824,17 @@
5793
5824
  logger.warn('the valid range of options.volume is 0-100, the value of volume has been set 100');
5794
5825
  }
5795
5826
  }
5827
+ if (options === null || options === void 0 ? void 0 : options.audioDeviceId) {
5828
+ /**
5829
+ * 检测传入的 audioDeviceId 是否有效
5830
+ */
5831
+ const deviceIds = (yield device.getSpeakers()).map((item) => { return item.deviceId; });
5832
+ const isValid = deviceIds.includes(options.audioDeviceId);
5833
+ if (!isValid) {
5834
+ logger.error(`the options.audioDeviceId is invalid --> ${options.audioDeviceId}`);
5835
+ return { code: exports.RCRTCCode.PARAMS_ERROR };
5836
+ }
5837
+ }
5796
5838
  const isVideoTrack = this.isVideoTrack();
5797
5839
  // video 播放必须传递一个 HTMLVideoElement 实例作为 video track 的播放组件
5798
5840
  if (isVideoTrack && (!element || !(element instanceof HTMLVideoElement))) {
@@ -5856,9 +5898,21 @@
5856
5898
  this._element.volume = (options === null || options === void 0 ? void 0 : options.volume) / 100;
5857
5899
  }
5858
5900
  try {
5859
- this._element.play();
5901
+ if ((options === null || options === void 0 ? void 0 : options.audioDeviceId) && !isVideoTrack) {
5902
+ yield this._element.setSinkId(options.audioDeviceId);
5903
+ }
5904
+ else {
5905
+ this._element.play();
5906
+ }
5860
5907
  }
5861
5908
  catch (error) {
5909
+ /**
5910
+ * 检测是否有设置音频输出设备的权限
5911
+ */
5912
+ if (error.message === 'No permission to use requested device') {
5913
+ logger.error(`setSinkId failed -> ${error.message}`);
5914
+ return { code: exports.RCRTCCode.NO_PERMISSION_TO_USE_REQUESTED_DEVICE };
5915
+ }
5862
5916
  logger.error(error);
5863
5917
  return { code: exports.RCRTCCode.TRACK_PLAY_ERROR };
5864
5918
  }
@@ -6320,6 +6374,27 @@
6320
6374
  });
6321
6375
  return length;
6322
6376
  };
6377
+ /**
6378
+ * 解析房间数据
6379
+ */
6380
+ const parseRoomData = (data) => {
6381
+ const result = {};
6382
+ const userIds = Object.keys(data.users);
6383
+ userIds.length && userIds.forEach(userId => {
6384
+ const tmp = [];
6385
+ const userData = data.users[userId];
6386
+ if (userData.uris) {
6387
+ try {
6388
+ tmp.push(...JSON.parse(userData.uris));
6389
+ }
6390
+ catch (error) {
6391
+ logger.warn(`invalid user data -> userId: ${userId}, userData: ${userData}`);
6392
+ }
6393
+ }
6394
+ result[userId] = tmp;
6395
+ });
6396
+ return result;
6397
+ };
6323
6398
 
6324
6399
  /**
6325
6400
  * RTC 消息类型常量
@@ -8242,7 +8317,7 @@
8242
8317
  * 加入房间
8243
8318
  */
8244
8319
  sendR1() {
8245
- const rtcVersion = "5.1.10-alpha.3";
8320
+ const rtcVersion = "5.2.2-alpha.1";
8246
8321
  const imVersion = this._context.getCoreVersion();
8247
8322
  const platform = 'web';
8248
8323
  const pcName = navigator.platform;
@@ -8378,24 +8453,21 @@
8378
8453
  }
8379
8454
  }
8380
8455
 
8381
- const parseRoomData = (data) => {
8382
- const result = {};
8383
- const userIds = Object.keys(data.users);
8384
- userIds.length && userIds.forEach(userId => {
8385
- const tmp = [];
8386
- const userData = data.users[userId];
8387
- if (userData.uris) {
8388
- try {
8389
- tmp.push(...JSON.parse(userData.uris));
8390
- }
8391
- catch (error) {
8392
- logger.warn(`invalid user data -> userId: ${userId}, userData: ${userData}`);
8393
- }
8394
- }
8395
- result[userId] = tmp;
8396
- });
8397
- return result;
8398
- };
8456
+ /**
8457
+ * 直播角色
8458
+ */
8459
+ exports.RCRTCLiveRole = void 0;
8460
+ (function (RCRTCLiveRole) {
8461
+ /**
8462
+ * 主播
8463
+ */
8464
+ RCRTCLiveRole[RCRTCLiveRole["ANCHOR"] = 1] = "ANCHOR";
8465
+ /**
8466
+ * 观众
8467
+ */
8468
+ RCRTCLiveRole[RCRTCLiveRole["AUDIENCE"] = 2] = "AUDIENCE";
8469
+ })(exports.RCRTCLiveRole || (exports.RCRTCLiveRole = {}));
8470
+
8399
8471
  const getTrackIdFromAttr = (track) => {
8400
8472
  if (track instanceof RCTrack) {
8401
8473
  return track.getTrackId();
@@ -8453,7 +8525,7 @@
8453
8525
  /**
8454
8526
  * 观众升级为主播后不会收到全量 uri 消息,需直接触发人员、资源变更
8455
8527
  */
8456
- isUpgrade && this._afterChangedRole(parseRoomData(data));
8528
+ isUpgrade && this._afterChangedRole(data);
8457
8529
  // 开始心跳,心跳失败时主动退出房间
8458
8530
  this._pinger = new Pinger(_roomId, this._roomMode, _context, this._initOptions.pingGap);
8459
8531
  this._pinger.onFailed = this._kickoff.bind(this);
@@ -8743,30 +8815,49 @@
8743
8815
  * @param content
8744
8816
  */
8745
8817
  _stateHandle(content) {
8818
+ var _a;
8746
8819
  return __awaiter(this, void 0, void 0, function* () {
8747
8820
  const { users } = content;
8748
8821
  if (users.length === 0) {
8749
8822
  return;
8750
8823
  }
8824
+ /**
8825
+ * 主动加入房间
8826
+ */
8751
8827
  const joined = [];
8828
+ /**
8829
+ * 主动退出房间
8830
+ */
8752
8831
  const left = [];
8832
+ /**
8833
+ * 观众升级为主播加入房间
8834
+ */
8835
+ const upgrade = [];
8836
+ /**
8837
+ * 主播降级为观众退出房间
8838
+ */
8839
+ const downgrade = [];
8753
8840
  users.forEach(item => {
8754
8841
  if (+item.state === 0) {
8755
8842
  logger.debug(`user joined -> ${item.userId}`);
8756
8843
  // 对端 im 重连之后调加入房间信令获取最新数据,服务会给本端下发“对端加入房间”的消息,本端内存已包含对端人员,所以需过滤掉
8757
- !this._roomResources[item.userId] && joined.push(item.userId);
8844
+ if (!this._roomResources[item.userId]) {
8845
+ item.switchRoleType ? upgrade.push(item.userId) : joined.push(item.userId);
8846
+ }
8758
8847
  this._roomResources[item.userId] = this._roomResources[item.userId] || [];
8759
8848
  }
8760
8849
  else {
8761
8850
  logger.debug(`user left -> ${item.userId}`);
8762
- left.push(item.userId);
8851
+ item.switchRoleType ? downgrade.push(item.userId) : left.push(item.userId);
8763
8852
  }
8764
8853
  });
8854
+ const allJoined = [...joined, ...upgrade];
8855
+ const allLeft = [...left, ...downgrade];
8765
8856
  // 用户离开房间时,自动退订对方资源
8766
- if (left.length > 0) {
8857
+ if (allLeft.length) {
8767
8858
  const tracks = [];
8768
8859
  const userIds = [];
8769
- left.forEach(userId => {
8860
+ allLeft.forEach(userId => {
8770
8861
  tracks.push(...this.getRemoteTracksByUserId(userId));
8771
8862
  // 先暂存待删用户,因当前异步队列中可能存在等待中的待处理任务,需要当前房间数据状态
8772
8863
  // delete this._roomResources[userId]
@@ -8781,9 +8872,23 @@
8781
8872
  userIds.forEach(userId => delete this._roomResources[userId]);
8782
8873
  }
8783
8874
  }
8784
- // 通知业务层
8785
- joined.length > 0 && this._callAppListener('onUserJoin', joined);
8786
- left.length > 0 && this._callAppListener('onUserLeave', left);
8875
+ /**
8876
+ * 通知业务层
8877
+ * onSwitchRole 监听时,按 switchRole 分“角色切换、加入房间、退出房间”抛出
8878
+ */
8879
+ if ((_a = this._appListener) === null || _a === void 0 ? void 0 : _a.onSwitchRole) {
8880
+ upgrade.length && upgrade.forEach(userId => this._callAppListener('onSwitchRole', userId, exports.RCRTCLiveRole.ANCHOR));
8881
+ downgrade.length && downgrade.forEach(userId => this._callAppListener('onSwitchRole', userId, exports.RCRTCLiveRole.AUDIENCE));
8882
+ joined.length && this._callAppListener('onUserJoin', joined);
8883
+ left.length && this._callAppListener('onUserLeave', left);
8884
+ return;
8885
+ }
8886
+ /**
8887
+ * 通知业务层
8888
+ * 无 onSwitchRole 监听时,统一按“加入房间、退出房间”抛出
8889
+ */
8890
+ allJoined.length && this._callAppListener('onUserJoin', allJoined);
8891
+ allLeft.length && this._callAppListener('onUserLeave', allLeft);
8787
8892
  });
8788
8893
  }
8789
8894
  /**
@@ -9204,7 +9309,7 @@
9204
9309
  subscribeList: subscribeList.filter((item) => {
9205
9310
  var _a;
9206
9311
  const trackId = item.track.getTrackId();
9207
- const { userId } = helper.parseTrackId(trackId);
9312
+ const { userId } = parseTrackId(trackId);
9208
9313
  const isInclude = (_a = this._roomResources[userId]) === null || _a === void 0 ? void 0 : _a.filter(item => trackId === `${item.msid}_${item.mediaType}`).length;
9209
9314
  return isInclude;
9210
9315
  }).map(item => ({
@@ -9652,6 +9757,7 @@
9652
9757
  rTrack.isAudioTrack() ? this._onAudioMuteChange(rTrack) : this._onVideoMuteChange(rTrack);
9653
9758
  });
9654
9759
  });
9760
+ return { data };
9655
9761
  });
9656
9762
  }
9657
9763
  _onAudioMuteChange(audioTrack) {
@@ -9663,35 +9769,7 @@
9663
9769
  /**
9664
9770
  * 观众切换为主播后直接处理人员变更及资源变更
9665
9771
  */
9666
- _afterChangedRole(data) {
9667
- const currentUserId = this._context.getCurrentId();
9668
- const joinedAnchorList = Object.keys(data);
9669
- // 观众升级主播成功后返回房间实例,才可注册房间事件,需异步抛出
9670
- setTimeout(() => {
9671
- // 通知业务层人员变更
9672
- const needNoticeUserIds = joinedAnchorList.filter(id => {
9673
- return id !== currentUserId;
9674
- });
9675
- needNoticeUserIds.length > 0 && this._callAppListener('onUserJoin', needNoticeUserIds);
9676
- // 通知业务层资源变更
9677
- for (const userId in data) {
9678
- if (userId === currentUserId) {
9679
- continue;
9680
- }
9681
- this.msgTaskQueue.push(() => this._resourceHandle({
9682
- uris: data[userId]
9683
- }, RCRTCMessageType.TOTAL_CONTENT_RESOURCE, userId));
9684
- }
9685
- });
9686
- }
9687
- /**
9688
- * 主播身份降级,取消己端已发布的所有资源
9689
- */
9690
- __unpublishToSingal() {
9691
- const crtUserId = this._context.getCurrentId();
9692
- const unpublishList = this._roomResources[crtUserId];
9693
- return this._context.setRTCTotalRes(this._roomId, buildPlusMessage(RCRTCMessageType.UNPUBLISH, unpublishList), buildTotalURIMessageContent([]), RCRTCMessageType.TOTAL_CONTENT_RESOURCE);
9694
- }
9772
+ _afterChangedRole(data) { }
9695
9773
  /**
9696
9774
  * 销毁远端资源
9697
9775
  */
@@ -9769,9 +9847,14 @@
9769
9847
  /**
9770
9848
  * trackId 有效性验证方法
9771
9849
  */
9772
- _isValidTrackId) {
9850
+ _isValidTrackId,
9851
+ /**
9852
+ * 扩散 cdn_uris
9853
+ */
9854
+ _sendCDNInfoSignal) {
9773
9855
  this._onFlush = _onFlush;
9774
9856
  this._isValidTrackId = _isValidTrackId;
9857
+ this._sendCDNInfoSignal = _sendCDNInfoSignal;
9775
9858
  /**
9776
9859
  * mcu 配置数据,每次向服务器提交全量数据
9777
9860
  */
@@ -10158,24 +10241,62 @@
10158
10241
  * 使已修改的配置生效,在调用该方法前,所有数据只会对本地配置进行修改,不会产生实际效果
10159
10242
  */
10160
10243
  flush() {
10244
+ var _a, _b, _c, _d;
10161
10245
  return __awaiter(this, void 0, void 0, function* () {
10162
10246
  const config = JSON.parse(JSON.stringify(this._values));
10163
10247
  const { code } = yield this._onFlush(config);
10248
+ /**
10249
+ * 合流布局中包含分辨率设置时,需扩散 cdn_uris
10250
+ */
10251
+ if (code === exports.RCRTCCode.SUCCESS && (((_b = (_a = this._values.output) === null || _a === void 0 ? void 0 : _a.video.normal) === null || _b === void 0 ? void 0 : _b.width) || ((_d = (_c = this._values.output) === null || _c === void 0 ? void 0 : _c.video.normal) === null || _d === void 0 ? void 0 : _d.fps))) {
10252
+ this._sendCDNInfoSignal();
10253
+ }
10164
10254
  this._values = createMCUConfig();
10165
10255
  return { code };
10166
10256
  });
10167
10257
  }
10168
10258
  }
10169
10259
 
10260
+ var RCInnerCDNModel;
10261
+ (function (RCInnerCDNModel) {
10262
+ // 开启
10263
+ RCInnerCDNModel[RCInnerCDNModel["OPEN"] = 1] = "OPEN";
10264
+ // 停用
10265
+ RCInnerCDNModel[RCInnerCDNModel["STOP"] = 2] = "STOP";
10266
+ })(RCInnerCDNModel || (RCInnerCDNModel = {}));
10267
+
10268
+ var RCInnerCDNBroadcast;
10269
+ (function (RCInnerCDNBroadcast) {
10270
+ // 扩散
10271
+ RCInnerCDNBroadcast[RCInnerCDNBroadcast["SPREAD"] = 0] = "SPREAD";
10272
+ RCInnerCDNBroadcast[RCInnerCDNBroadcast["NO_SPREAD"] = -1] = "NO_SPREAD";
10273
+ })(RCInnerCDNBroadcast || (RCInnerCDNBroadcast = {}));
10274
+
10275
+ var RCInnerCDNPushMode;
10276
+ (function (RCInnerCDNPushMode) {
10277
+ // 自动模式
10278
+ RCInnerCDNPushMode[RCInnerCDNPushMode["AUTOMATIC"] = 0] = "AUTOMATIC";
10279
+ // 手动模式
10280
+ RCInnerCDNPushMode[RCInnerCDNPushMode["MANUAL"] = 1] = "MANUAL";
10281
+ })(RCInnerCDNPushMode || (RCInnerCDNPushMode = {}));
10282
+
10170
10283
  /**
10171
10284
  * 直播房间
10172
10285
  */
10173
10286
  class RCLivingRoom extends RCAbstractRoom {
10174
10287
  constructor(context, runtime, roomId, data, service, initOptions, clientEvent, _livingType, isUpgrage = false) {
10288
+ var _a;
10175
10289
  super(context, runtime, roomId, data, engine.RTCMode.LIVE, service, initOptions, clientEvent, isUpgrage);
10176
10290
  this._livingType = _livingType;
10291
+ /**
10292
+ * cdn_uris 信令扩散数据
10293
+ */
10294
+ this._CDNUris = null;
10295
+ this._CDNEnable = false;
10177
10296
  // 初始化 MCUBuilder
10178
- this._mcuConfigBuilder = new RCMCUConfigBuilder(this._onMCUConfigFlush.bind(this), this._isValidResourceId.bind(this));
10297
+ this._mcuConfigBuilder = new RCMCUConfigBuilder(this._onMCUConfigFlush.bind(this), this._isValidResourceId.bind(this), this._sendCDNInfoSignal.bind(this));
10298
+ const CDNUris = (_a = data.roomInfo.filter((item) => { return item.key === 'cdn_uris'; })[0]) === null || _a === void 0 ? void 0 : _a.value;
10299
+ CDNUris && (this._CDNUris = JSON.parse(CDNUris)[0]);
10179
10300
  }
10180
10301
  getLivingType() {
10181
10302
  return this._livingType;
@@ -10199,16 +10320,214 @@
10199
10320
  UserId: this._context.getCurrentId(),
10200
10321
  SessionId: this.getSessionId()
10201
10322
  };
10202
- const { code } = yield this._service.setMcuConfig(headers, data);
10323
+ const { code, res } = yield this._service.setMcuConfig(headers, data);
10203
10324
  if (code !== exports.RCRTCCode.SUCCESS) {
10204
10325
  logger.error(`set MCU config failed: ${code}`);
10326
+ return { code };
10205
10327
  }
10206
- logger.debug('set MCU config success');
10207
- return { code };
10328
+ logger.info('set MCU config success');
10329
+ res.pull_url && (this._CDNUris = JSON.parse(res.pull_url));
10330
+ return { code, res };
10208
10331
  });
10209
10332
  }
10333
+ /**
10334
+ * 主播端断线重连后,需更新内存中的 CDN 数据
10335
+ * 判断房间内 CDN 状态是否和内存数据一致,不一致时需通知到客户端
10336
+ */
10210
10337
  __onReconnected() {
10211
- return super.__onReconnected(this._livingType);
10338
+ const _super = Object.create(null, {
10339
+ __onReconnected: { get: () => super.__onReconnected }
10340
+ });
10341
+ var _a, _b;
10342
+ return __awaiter(this, void 0, void 0, function* () {
10343
+ const res = yield _super.__onReconnected.call(this, this._livingType);
10344
+ if (!res || !res.data) {
10345
+ return;
10346
+ }
10347
+ const roomInfo = res.data.roomInfo;
10348
+ const CDNUris = (_a = roomInfo.filter((item) => { return item.key === 'cdn_uris'; })[0]) === null || _a === void 0 ? void 0 : _a.value;
10349
+ if (!CDNUris) {
10350
+ return;
10351
+ }
10352
+ const parseCDNUris = JSON.parse(CDNUris);
10353
+ if (((_b = this._CDNUris) === null || _b === void 0 ? void 0 : _b.enableInnerCDN) !== parseCDNUris.enableInnerCDN) {
10354
+ this._callAppListener('onCDNEnableChange', parseCDNUris.enableInnerCDN);
10355
+ }
10356
+ this._CDNUris = parseCDNUris;
10357
+ });
10358
+ }
10359
+ /**
10360
+ * 开启/停用推 CDN
10361
+ */
10362
+ enableInnerCDN(enable) {
10363
+ return __awaiter(this, void 0, void 0, function* () {
10364
+ if (!engine.isBoolean(enable)) {
10365
+ logger.error('`enable` is invalid');
10366
+ return { code: exports.RCRTCCode.PARAMS_ERROR };
10367
+ }
10368
+ this._CDNEnable = enable;
10369
+ const params = {
10370
+ version: 2,
10371
+ output: {
10372
+ inCDNModel: enable ? RCInnerCDNModel.OPEN : RCInnerCDNModel.STOP
10373
+ }
10374
+ };
10375
+ const { code } = yield this._onMCUConfigFlush(params);
10376
+ if (code !== exports.RCRTCCode.SUCCESS) {
10377
+ logger.error(`enableInnerCDN failed -> code: ${code}`);
10378
+ return { code: exports.RCRTCCode.SIGNAL_ERROR };
10379
+ }
10380
+ // 判断是否需要扩散 cdn_uris 时
10381
+ if (this._CDNUris && (this._CDNUris.broadcast !== RCInnerCDNBroadcast.SPREAD)) {
10382
+ logger.info('enableInnerCDN succeed');
10383
+ return { code: exports.RCRTCCode.SUCCESS };
10384
+ }
10385
+ /**
10386
+ * 扩散 cdn_uris
10387
+ */
10388
+ const { code: sendSingalCode } = yield push(() => __awaiter(this, void 0, void 0, function* () { return this._sendCDNInfoSignal(); }));
10389
+ if (sendSingalCode === exports.RCRTCCode.SUCCESS) {
10390
+ logger.info('enableInnerCDN succeed');
10391
+ return { code: exports.RCRTCCode.SUCCESS };
10392
+ }
10393
+ logger.error(`enableInnerCDN failed -> code: ${sendSingalCode}`);
10394
+ return { code: sendSingalCode };
10395
+ });
10396
+ }
10397
+ /**
10398
+ * 开启、停用 CDN 推资源后发信令
10399
+ */
10400
+ _sendCDNInfoSignal() {
10401
+ return __awaiter(this, void 0, void 0, function* () {
10402
+ this._CDNUris = Object.assign({}, this._CDNUris, { enableInnerCDN: this._CDNEnable });
10403
+ const resCodeArr = yield Promise.all([this._spreadCDNInfo(this._CDNUris), this._setRoomCDNInfo(this._CDNUris)]);
10404
+ const isSuccess = resCodeArr.every((item) => {
10405
+ return item.code === exports.RCRTCCode.SUCCESS;
10406
+ });
10407
+ return isSuccess ? { code: exports.RCRTCCode.SUCCESS } : { code: exports.RCRTCCode.SIGNAL_ERROR };
10408
+ });
10409
+ }
10410
+ /**
10411
+ * 扩散 cdn_uris 资源
10412
+ */
10413
+ _spreadCDNInfo(CDNUris) {
10414
+ return __awaiter(this, void 0, void 0, function* () {
10415
+ const code = yield this._context.setRTCCDNUris(this._roomId, RCRTCMessageType.TOTAL_CONTENT_RESOURCE, JSON.stringify([CDNUris]));
10416
+ if (code !== engine.ErrorCode.SUCCESS) {
10417
+ logger.error(`spreadCDNInfo failed -> code: ${code}`);
10418
+ return { code: exports.RCRTCCode.SIGNAL_ERROR };
10419
+ }
10420
+ logger.info('spreadCDNInfo succeed');
10421
+ return { code: exports.RCRTCCode.SUCCESS };
10422
+ });
10423
+ }
10424
+ /**
10425
+ * 给房间设置 CDN 数据
10426
+ */
10427
+ _setRoomCDNInfo(CDNUris) {
10428
+ return __awaiter(this, void 0, void 0, function* () {
10429
+ const code = yield this._context.setRTCData(this._roomId, 'cdn_uris', JSON.stringify([CDNUris]), true, engine.RTCApiType.ROOM);
10430
+ if (code !== engine.ErrorCode.SUCCESS) {
10431
+ logger.error(`setRoomCDNInfo failed -> code: ${code}`);
10432
+ return { code: exports.RCRTCCode.SIGNAL_ERROR };
10433
+ }
10434
+ logger.info('setRoomCDNInfo succeed');
10435
+ return { code: exports.RCRTCCode.SUCCESS };
10436
+ });
10437
+ }
10438
+ /**
10439
+ * 资源变化时触发
10440
+ * 直播房间需单独处理 cdn_uris
10441
+ */
10442
+ _resourceHandle(content, messageType, userId) {
10443
+ const _super = Object.create(null, {
10444
+ _resourceHandle: { get: () => super._resourceHandle }
10445
+ });
10446
+ var _a;
10447
+ return __awaiter(this, void 0, void 0, function* () {
10448
+ _super._resourceHandle.call(this, content, messageType, userId);
10449
+ if (!content.cdn_uris) {
10450
+ return;
10451
+ }
10452
+ // 给业务层抛 CDN 状态
10453
+ if (((_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.enableInnerCDN) !== content.cdn_uris[0].enableInnerCDN) {
10454
+ this._callAppListener('onCDNEnableChange', !this.__getCDNEnable());
10455
+ }
10456
+ // 更新 _CDNUris
10457
+ this._CDNUris = content.cdn_uris[0];
10458
+ });
10459
+ }
10460
+ /**
10461
+ * 重写父类 _exchangeHandle 方法
10462
+ */
10463
+ _exchangeHandle(body) {
10464
+ var _a, _b, _c;
10465
+ return __awaiter(this, void 0, void 0, function* () {
10466
+ const res = yield this._service.exchange(this._getRTCReqestHeaders(), body);
10467
+ const pullUrl = (_b = (_a = res.data) === null || _a === void 0 ? void 0 : _a.urls) === null || _b === void 0 ? void 0 : _b.pull_url;
10468
+ if (res.code !== exports.RCRTCCode.SUCCESS || !pullUrl) {
10469
+ return res;
10470
+ }
10471
+ /**
10472
+ * 自动模式下:
10473
+ * /exchange 完需根据 broadcast 字端判断是否扩散 cdn_uris 数据,设置房间 cdn_uris 数据
10474
+ */
10475
+ this._CDNUris = JSON.parse(pullUrl);
10476
+ if (((_c = this._CDNUris) === null || _c === void 0 ? void 0 : _c.broadcast) === RCInnerCDNBroadcast.SPREAD) {
10477
+ this._CDNEnable = true;
10478
+ this._sendCDNInfoSignal();
10479
+ }
10480
+ return res;
10481
+ });
10482
+ }
10483
+ /**
10484
+ * 观众切换为主播后直接处理人员变更及资源变更
10485
+ */
10486
+ _afterChangedRole(data) {
10487
+ const parseData = parseRoomData(data);
10488
+ const currentUserId = this._context.getCurrentId();
10489
+ const joinedAnchorList = Object.keys(parseData);
10490
+ // 观众升级主播成功后返回房间实例,才可注册房间事件,需异步抛出
10491
+ setTimeout(() => {
10492
+ var _a, _b, _c;
10493
+ // 通知业务层人员变更
10494
+ const needNoticeUserIds = joinedAnchorList.filter(id => {
10495
+ return id !== currentUserId;
10496
+ });
10497
+ needNoticeUserIds.length > 0 && this._callAppListener('onUserJoin', needNoticeUserIds);
10498
+ // 通知业务层资源变更
10499
+ for (const userId in parseData) {
10500
+ if (userId === currentUserId) {
10501
+ continue;
10502
+ }
10503
+ this._resourceHandle({
10504
+ uris: parseData[userId]
10505
+ }, RCRTCMessageType.TOTAL_CONTENT_RESOURCE, userId);
10506
+ }
10507
+ const CDNUris = (_a = data.roomInfo.filter((item) => { return item.key === 'cdn_uris'; })[0]) === null || _a === void 0 ? void 0 : _a.value;
10508
+ if (!CDNUris) {
10509
+ return;
10510
+ }
10511
+ if (((_b = this._CDNUris) === null || _b === void 0 ? void 0 : _b.push_mode) === RCInnerCDNPushMode.MANUAL) {
10512
+ this._callAppListener('onCDNEnableChange', (_c = this._CDNUris) === null || _c === void 0 ? void 0 : _c.enableInnerCDN);
10513
+ }
10514
+ });
10515
+ }
10516
+ /**
10517
+ * 返回 CDN 是否可用
10518
+ * @returns boolean
10519
+ */
10520
+ __getCDNEnable() {
10521
+ var _a;
10522
+ return (_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.enableInnerCDN;
10523
+ }
10524
+ /**
10525
+ * 返回 CDN 推送模式: 自动 or 手动
10526
+ * @returns boolean
10527
+ */
10528
+ __getCDNPushMode() {
10529
+ var _a;
10530
+ return (_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.push_mode;
10212
10531
  }
10213
10532
  }
10214
10533
 
@@ -10267,7 +10586,7 @@
10267
10586
  'Content-Type': 'application/json;charset=UTF-8',
10268
10587
  'Cache-Control': 'no-cache',
10269
10588
  ClientType: `web|${browserInfo.browser}|${browserInfo.version}`,
10270
- ClientVersion: "5.1.10-alpha.3",
10589
+ ClientVersion: "5.2.2-alpha.1",
10271
10590
  'Client-Session-Id': getUUID(),
10272
10591
  'Request-Id': Date.now().toString()
10273
10592
  });
@@ -10435,7 +10754,25 @@
10435
10754
  if (status === 200) {
10436
10755
  logger.debug(`request success -> Request-Id: ${commonHeader['Request-Id']}`);
10437
10756
  const data = JSON.parse(jsonStr);
10438
- return { code: data.resultCode };
10757
+ return { code: data.resultCode, res: data };
10758
+ }
10759
+ return { code: exports.RCRTCCode.REQUEST_FAILED };
10760
+ });
10761
+ }
10762
+ /**
10763
+ * 房间内观众获取 CDN 资源信息、拉流地址
10764
+ */
10765
+ getCDNResourceInfo(headers, url) {
10766
+ return __awaiter(this, void 0, void 0, function* () {
10767
+ const commonHeader = getCommonHeader();
10768
+ const { status, data: resStr } = yield this._runtime.httpReq({
10769
+ url,
10770
+ headers: Object.assign(Object.assign({}, commonHeader), headers),
10771
+ method: engine.HttpMethod.GET
10772
+ });
10773
+ if (status === 200) {
10774
+ const data = JSON.parse(resStr);
10775
+ return { code: data.resultCode, res: data };
10439
10776
  }
10440
10777
  logger.warn(`request failed -> Request-Id: ${commonHeader['Request-Id']}, status: ${status}, url: ${url}`);
10441
10778
  return { code: exports.RCRTCCode.REQUEST_FAILED };
@@ -10580,12 +10917,15 @@
10580
10917
  if (code !== exports.RCRTCCode.SUCCESS) {
10581
10918
  return { code, tracks };
10582
10919
  }
10583
- // 直观观众订阅的是合流后的数据,并不存在流的归属问题,此处直接以虚拟生成的合流 id 替代 userId
10920
+ // 直播观众订阅的是合流后的数据,并不存在流的归属问题,此处直接以虚拟生成的合流 id 替代 userId
10584
10921
  const mcuId = `rc_mcu_${Date.now()}`;
10585
10922
  const tag = 'RongCloudRTC';
10586
- this._subTracks.length = 0;
10587
- this._subTracks.push(new RCRemoteAudioTrack(tag, mcuId), new RCRemoteVideoTrack(tag, mcuId));
10588
- this._pc.updateSubRemoteTracks(this._subTracks.slice());
10923
+ if (this._subTracks.length === 0) {
10924
+ // 观众端单次只能订阅一个 liveUrl, 订阅后再次重复订阅只是修改订阅参数
10925
+ // 重复订阅后之前订阅的流可直接根据参数变动,无需重新添加 transceiver
10926
+ this._subTracks.push(new RCRemoteAudioTrack(tag, mcuId), new RCRemoteVideoTrack(tag, mcuId));
10927
+ this._pc.updateSubRemoteTracks(this._subTracks.slice());
10928
+ }
10589
10929
  const offer = yield this._pc.createOffer(true);
10590
10930
  const body = {
10591
10931
  sdp: offer,
@@ -10685,6 +11025,19 @@
10685
11025
  }
10686
11026
  }
10687
11027
 
11028
+ exports.RCInnerCDNPullKind = void 0;
11029
+ (function (RCInnerCDNPullKind) {
11030
+ RCInnerCDNPullKind["RTMP"] = "rtmp";
11031
+ RCInnerCDNPullKind["FLV"] = "flv";
11032
+ RCInnerCDNPullKind["HLS"] = "hls";
11033
+ })(exports.RCInnerCDNPullKind || (exports.RCInnerCDNPullKind = {}));
11034
+
11035
+ exports.RCInnerCDNPullIsHttps = void 0;
11036
+ (function (RCInnerCDNPullIsHttps) {
11037
+ RCInnerCDNPullIsHttps[RCInnerCDNPullIsHttps["NOT_HTTPS"] = 0] = "NOT_HTTPS";
11038
+ RCInnerCDNPullIsHttps[RCInnerCDNPullIsHttps["HTTPS"] = 1] = "HTTPS";
11039
+ })(exports.RCInnerCDNPullIsHttps || (exports.RCInnerCDNPullIsHttps = {}));
11040
+
10688
11041
  const tinyConf = Object.assign(Object.assign({}, transResolution(exports.RCResolution.W176_H144)), { frameRate: transFrameRate(exports.RCFrameRate.FPS_15) });
10689
11042
  /**
10690
11043
  * 观众直播房间类
@@ -10693,12 +11046,12 @@
10693
11046
  * 2、观众订阅、取消订阅资源
10694
11047
  */
10695
11048
  class RCAudienceLivingRoom {
10696
- constructor(_context, _runtime, _initOptions, _roomId, _token, _livingType) {
11049
+ constructor(_context, _runtime, _initOptions, _roomId, _joinResData, _livingType) {
10697
11050
  this._context = _context;
10698
11051
  this._runtime = _runtime;
10699
11052
  this._initOptions = _initOptions;
10700
11053
  this._roomId = _roomId;
10701
- this._token = _token;
11054
+ this._joinResData = _joinResData;
10702
11055
  this._livingType = _livingType;
10703
11056
  this._roomAnchorList = [];
10704
11057
  this._roomRes = {};
@@ -10743,14 +11096,18 @@
10743
11096
  * * key RC_ANCHOR_LIST value: 为主播 ID 集合
10744
11097
  * * key RC_RES_`userId` value: 为主播发布的资源
10745
11098
  * * key RC_RTC_SESSIONID value: sessionId
11099
+ * * key RC_CDN value: CDN 资源数据
10746
11100
  */
10747
11101
  singalDataChange(singalData, roomId) {
11102
+ var _a;
10748
11103
  if (roomId !== this._roomId) {
10749
11104
  logger.warn(`singalDataChange -> not the current room data: data roomId: ${roomId}, current roomId: ${this._roomId}`);
10750
11105
  return;
10751
11106
  }
10752
11107
  logger.debug('singalDataChange -> singalData:', JSON.stringify(singalData || {}));
10753
11108
  const allMcuUris = [];
11109
+ const CDNUrisStr = (_a = singalData.filter((item) => { return item.key === 'RC_CDN'; })[0]) === null || _a === void 0 ? void 0 : _a.value;
11110
+ CDNUrisStr && this._diffCDNUris(JSON.parse(JSON.parse(CDNUrisStr).cdn_uris)[0]);
10754
11111
  singalData.forEach(data => {
10755
11112
  const { key, value, timestamp, uid } = data;
10756
11113
  const isResKey = key.indexOf('RC_RES_') !== -1;
@@ -11104,7 +11461,7 @@
11104
11461
  return {
11105
11462
  'App-Key': this._context.getAppkey(),
11106
11463
  RoomId: userId,
11107
- Token: this._token,
11464
+ Token: this._joinResData.token,
11108
11465
  RoomType: engine.RTCMode.LIVE,
11109
11466
  UserId: userId,
11110
11467
  'Session-Id': this._sessionId
@@ -11213,6 +11570,123 @@
11213
11570
  return { code: exports.RCRTCCode.SUCCESS };
11214
11571
  });
11215
11572
  }
11573
+ /**
11574
+ * 对比 cdn_uris 资源
11575
+ * @param newCDNUris 新的 cdn_uris 数据
11576
+ */
11577
+ _diffCDNUris(newCDNUris) {
11578
+ var _a, _b, _c, _d, _e, _f, _g, _h;
11579
+ return __awaiter(this, void 0, void 0, function* () {
11580
+ /**
11581
+ * CDN 资源减少: 上次 CDNUris 中有 url,变更后无 url
11582
+ */
11583
+ if (((_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.url) && !newCDNUris.url) {
11584
+ this._callAppListener('onCDNInfoDisable');
11585
+ /**
11586
+ * 更新内存中存储的 cdn_uris 数据
11587
+ */
11588
+ this._CDNUris = newCDNUris;
11589
+ return;
11590
+ }
11591
+ /**
11592
+ * CDN 资源新增条件:
11593
+ * 内存中无 CDNUris 或
11594
+ * 上次 CDNUris 无 url,变更后有 url
11595
+ */
11596
+ if (!this._CDNUris || (!((_b = this._CDNUris) === null || _b === void 0 ? void 0 : _b.url) && newCDNUris.url)) {
11597
+ this._callAppListener('onCDNInfoEnable', {
11598
+ resolution: `W${newCDNUris.w}_H${newCDNUris.h}`,
11599
+ fps: newCDNUris.fps
11600
+ });
11601
+ }
11602
+ /**
11603
+ * CDN 资源变更: w、h、fps 其中一项变化
11604
+ */
11605
+ const isWChange = (((_c = this._CDNUris) === null || _c === void 0 ? void 0 : _c.w) && newCDNUris.w && (((_d = this._CDNUris) === null || _d === void 0 ? void 0 : _d.w) !== newCDNUris.w));
11606
+ const isHChange = (((_e = this._CDNUris) === null || _e === void 0 ? void 0 : _e.h) && newCDNUris.h && (((_f = this._CDNUris) === null || _f === void 0 ? void 0 : _f.h) !== newCDNUris.h));
11607
+ const isFpsChange = (((_g = this._CDNUris) === null || _g === void 0 ? void 0 : _g.fps) && newCDNUris.fps && (((_h = this._CDNUris) === null || _h === void 0 ? void 0 : _h.fps) !== newCDNUris.fps));
11608
+ if (isWChange || isHChange || isFpsChange) {
11609
+ this._callAppListener('onCDNInfoChange', {
11610
+ resolution: `W${newCDNUris.w}_H${newCDNUris.h}`,
11611
+ fps: newCDNUris.fps
11612
+ });
11613
+ }
11614
+ /**
11615
+ * 更新内存中存储的 cdn_uris 数据
11616
+ */
11617
+ this._CDNUris = newCDNUris;
11618
+ });
11619
+ }
11620
+ /**
11621
+ * 获取 CDN 资源对应的拉流地址
11622
+ * 首次获取 CDNPlayUrl 时,需传入 url,
11623
+ * 业务层调用时使用内存中 _CDNUris 的 url,无 _CDNUris 时说明观众端未赋值过 _CDNUris
11624
+ * @returns CDNPlayUrl
11625
+ */
11626
+ _getCDNPlayUrl(params, url) {
11627
+ var _a, _b;
11628
+ return __awaiter(this, void 0, void 0, function* () {
11629
+ const { w, h, fps } = params;
11630
+ const kind = this._initOptions.pullInnerCDNProtocol || exports.RCInnerCDNPullKind.FLV;
11631
+ const useHttps = (this._initOptions.pullInnerCDNUseHttps === exports.RCInnerCDNPullIsHttps.NOT_HTTPS) ? exports.RCInnerCDNPullIsHttps.NOT_HTTPS : exports.RCInnerCDNPullIsHttps.HTTPS;
11632
+ /**
11633
+ * 加入房间后拉 KV 数据,数据还未返回时,同步拉 KV 获取 CDN 信息
11634
+ */
11635
+ if (!((_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.url) && !url) {
11636
+ logger.error(`cdn_uris url is empty, the anchor need to start CDN, code: ${exports.RCRTCCode.CDN_RESOURCE_IS_EMPTY}`);
11637
+ return { code: exports.RCRTCCode.CDN_RESOURCE_IS_EMPTY };
11638
+ }
11639
+ const headers = {
11640
+ 'App-Key': this._context.getAppkey(),
11641
+ Token: this._joinResData.token,
11642
+ RoomId: this.getRoomId(),
11643
+ UserId: this._context.getCurrentId(),
11644
+ SessionId: this.getSessionId()
11645
+ };
11646
+ const paramsArr = [];
11647
+ w && paramsArr.push(`w=${w}`);
11648
+ h && paramsArr.push(`h=${h}`);
11649
+ fps && paramsArr.push(`fps=${fps}`);
11650
+ paramsArr.push(`kind=${kind}`);
11651
+ paramsArr.push(`is_https=${useHttps}`);
11652
+ const paramsStr = paramsArr.join('&');
11653
+ let requestUrl = `${url || ((_b = this._CDNUris) === null || _b === void 0 ? void 0 : _b.url)}?`;
11654
+ paramsStr && (requestUrl += paramsStr);
11655
+ const { code, res } = yield this._service.getCDNResourceInfo(headers, requestUrl);
11656
+ if (code !== exports.RCRTCCode.SUCCESS) {
11657
+ logger.error(`getCDNPlayUrl failed: ${code}`);
11658
+ return { code };
11659
+ }
11660
+ logger.info(`getCDNPlayUrl success: ${res === null || res === void 0 ? void 0 : res.data.pull_url}`);
11661
+ return {
11662
+ code,
11663
+ CDNPlayUrl: res === null || res === void 0 ? void 0 : res.data.pull_url
11664
+ };
11665
+ });
11666
+ }
11667
+ /**
11668
+ * 获取 CDN 资源对应的拉流地址
11669
+ * @returns CDNPlayUrl
11670
+ */
11671
+ getCDNPlayUrl(resolution, fps) {
11672
+ return __awaiter(this, void 0, void 0, function* () {
11673
+ if (resolution && !isValidResolution(resolution)) {
11674
+ logger.error('`resolution` is invalid');
11675
+ return { code: exports.RCRTCCode.PARAMS_ERROR };
11676
+ }
11677
+ if (fps && !isValidFPS(fps)) {
11678
+ logger.error('`fps` is invalid');
11679
+ return { code: exports.RCRTCCode.PARAMS_ERROR };
11680
+ }
11681
+ const { width, height } = resolution ? transResolution(resolution) : { width: null, height: null };
11682
+ const fpsNum = fps ? transFrameRate(fps) : null;
11683
+ const params = {};
11684
+ width && (params.w = width);
11685
+ height && (params.h = height);
11686
+ fpsNum && (params.fps = fpsNum);
11687
+ return this._getCDNPlayUrl(params);
11688
+ });
11689
+ }
11216
11690
  /**
11217
11691
  * 订阅资源
11218
11692
  * @param tracks
@@ -11270,6 +11744,8 @@
11270
11744
  this._pc.destroy();
11271
11745
  // 销毁 polarisReport 实例
11272
11746
  this._polarisReport = null;
11747
+ // 清空 onrtcdatachange 事件监听
11748
+ this._context.onrtcdatachange = () => { };
11273
11749
  });
11274
11750
  }
11275
11751
  /**
@@ -11311,7 +11787,12 @@
11311
11787
  * @param tag 参数描述
11312
11788
  */
11313
11789
  registerRoomEventListener(listener) {
11790
+ var _a;
11314
11791
  this._appListener = listener;
11792
+ if (!listener) {
11793
+ return;
11794
+ }
11795
+ ((_a = this._joinResData.kvEntries) === null || _a === void 0 ? void 0 : _a.length) && this.singalDataChange(this._joinResData.kvEntries, this._roomId);
11315
11796
  }
11316
11797
  /**
11317
11798
  * 音量上报
@@ -11516,7 +11997,12 @@
11516
11997
  logger.debug(`JoinRoom success -> userId: ${this._context.getCurrentId()}, roomId: ${roomId}, data: ${JSON.stringify(data)}`);
11517
11998
  const room = new RCLivingRoom(this._context, this._runtime, roomId, data, this._service, this._options, this._releaseCrtRoomObj.bind(this), livingType, false);
11518
11999
  this._crtRoom = room;
11519
- return { room, code: exports.RCRTCCode.SUCCESS, userIds: room.getRemoteUserIds(), tracks: room.getRemoteTracks() };
12000
+ const joinLivingResData = { room, code: exports.RCRTCCode.SUCCESS, userIds: room.getRemoteUserIds(), tracks: room.getRemoteTracks() };
12001
+ // 手动模式时,用户加入房间,需返回 CDN 开关状态
12002
+ if (room.__getCDNPushMode() === RCInnerCDNPushMode.MANUAL) {
12003
+ Object.assign(joinLivingResData, { CDNEnable: room.__getCDNEnable() });
12004
+ }
12005
+ return joinLivingResData;
11520
12006
  });
11521
12007
  }
11522
12008
  /**
@@ -11627,7 +12113,8 @@
11627
12113
  deviceId: options === null || options === void 0 ? void 0 : options.cameraId,
11628
12114
  frameRate: transFrameRate((options === null || options === void 0 ? void 0 : options.frameRate) || exports.RCFrameRate.FPS_15),
11629
12115
  width,
11630
- height
12116
+ height,
12117
+ facingMode: options === null || options === void 0 ? void 0 : options.faceMode
11631
12118
  }
11632
12119
  });
11633
12120
  if (code !== exports.RCRTCCode.SUCCESS) {
@@ -11645,7 +12132,7 @@
11645
12132
  * @returns
11646
12133
  */
11647
12134
  createMicrophoneAndCameraTracks(tag = 'RongCloudRTC', options) {
11648
- var _a, _b, _c, _d, _e;
12135
+ var _a, _b, _c, _d, _e, _f;
11649
12136
  return __awaiter(this, void 0, void 0, function* () {
11650
12137
  const tracks = [];
11651
12138
  if (!isValidTag(tag)) {
@@ -11662,9 +12149,10 @@
11662
12149
  deviceId: (_b = options === null || options === void 0 ? void 0 : options.video) === null || _b === void 0 ? void 0 : _b.cameraId,
11663
12150
  frameRate: transFrameRate(((_c = options === null || options === void 0 ? void 0 : options.video) === null || _c === void 0 ? void 0 : _c.frameRate) || exports.RCFrameRate.FPS_15),
11664
12151
  width,
11665
- height
12152
+ height,
12153
+ facingMode: (_d = options === null || options === void 0 ? void 0 : options.video) === null || _d === void 0 ? void 0 : _d.faceMode
11666
12154
  },
11667
- audio: { deviceId: (_d = options === null || options === void 0 ? void 0 : options.audio) === null || _d === void 0 ? void 0 : _d.micphoneId, sampleRate: (_e = options === null || options === void 0 ? void 0 : options.audio) === null || _e === void 0 ? void 0 : _e.sampleRate }
12155
+ audio: { deviceId: (_e = options === null || options === void 0 ? void 0 : options.audio) === null || _e === void 0 ? void 0 : _e.micphoneId, sampleRate: (_f = options === null || options === void 0 ? void 0 : options.audio) === null || _f === void 0 ? void 0 : _f.sampleRate }
11668
12156
  });
11669
12157
  if (code !== exports.RCRTCCode.SUCCESS) {
11670
12158
  return { code, tracks };
@@ -11887,7 +12375,8 @@
11887
12375
  logger.error('audienceJoinLivingRoomError:', code);
11888
12376
  return { code: exports.RCRTCCode.SIGNAL_AUDIENCE_JOIN_ROOM_FAILED };
11889
12377
  }
11890
- const room = new RCAudienceLivingRoom(this._context, this._runtime, this._options, roomId, data.token, livingType);
12378
+ logger.info(`joinLivingRoomAsAudience success, room data: ${JSON.stringify(data)}`);
12379
+ const room = new RCAudienceLivingRoom(this._context, this._runtime, this._options, roomId, data, livingType);
11891
12380
  this._crtAudienceLivingRoom = room;
11892
12381
  return { room, code: exports.RCRTCCode.SUCCESS };
11893
12382
  });
@@ -11948,18 +12437,13 @@
11948
12437
  if (this._crtAudienceLivingRoom) {
11949
12438
  return { code: exports.RCRTCCode.REPERT_JOIN_ROOM };
11950
12439
  }
11951
- const singalCode = yield room.__unpublishToSingal();
11952
- if (singalCode !== engine.ErrorCode.SUCCESS) {
11953
- logger.error('change room identity setAllUris error', singalCode);
11954
- return { code: exports.RCRTCCode.SIGNAL_ERROR };
11955
- }
11956
12440
  const { code, data } = yield this._context.rtcIdentityChange(room._roomId, engine.RTCIdentityChangeType.AnchorToViewer, room.getLivingType());
11957
12441
  if (code !== engine.ErrorCode.SUCCESS) {
11958
12442
  logger.error('change room identity error', code);
11959
12443
  return { code: exports.RCRTCCode.SIGNAL_ROOM_CHANGE_IDENTITY_FAILED };
11960
12444
  }
11961
- const { token } = data;
11962
- const crtRoom = new RCAudienceLivingRoom(this._context, this._runtime, this._options, room._roomId, token, room.getLivingType());
12445
+ logger.info(`downgradeToAudienceRoom success, room data: ${JSON.stringify(data)}`);
12446
+ const crtRoom = new RCAudienceLivingRoom(this._context, this._runtime, this._options, room._roomId, data, room.getLivingType());
11963
12447
  this._crtAudienceLivingRoom = crtRoom;
11964
12448
  // 主播房间内存数据清除及停止 Signal 房间心跳
11965
12449
  this._crtRoom.__destroy(false);
@@ -11970,15 +12454,11 @@
11970
12454
  }
11971
12455
  /**
11972
12456
  * 获取在房间内用户信息
11973
- * 当前仅能查自己
11974
- * @since version 5.1.5
12457
+ * @since version 5.2.1
11975
12458
  */
11976
- getJoinedUserInfo(userId) {
12459
+ getJoinedRoomInfo() {
11977
12460
  return __awaiter(this, void 0, void 0, function* () {
11978
- if (!engine.validate('userId', userId, engine.notEmptyString, true)) {
11979
- return { code: exports.RCRTCCode.PARAMS_ERROR };
11980
- }
11981
- const { code, data } = yield this._context.getRTCJoinedUserInfo(userId);
12461
+ const { code, data } = yield this._context.getRTCJoinedUserInfo(this._context.getCurrentId());
11982
12462
  if (code !== engine.ErrorCode.SUCCESS) {
11983
12463
  logger.error('getJoinedUserInfo error', code);
11984
12464
  return { code: exports.RCRTCCode.SIGNAL_ROOM_CHANGE_IDENTITY_FAILED };
@@ -12000,33 +12480,6 @@
12000
12480
  RCKickReason[RCKickReason["OTHER_KICK"] = 2] = "OTHER_KICK";
12001
12481
  })(exports.RCKickReason || (exports.RCKickReason = {}));
12002
12482
 
12003
- /**
12004
- * 获取 Microphone 列表
12005
- */
12006
- const getMicrophones = () => __awaiter(void 0, void 0, void 0, function* () {
12007
- const mediaDivices = yield navigator.mediaDevices.enumerateDevices();
12008
- return mediaDivices.filter(item => item.kind === 'audioinput');
12009
- });
12010
- /**
12011
- * 获取摄像头设备列表
12012
- */
12013
- const getCameras = () => __awaiter(void 0, void 0, void 0, function* () {
12014
- const mediaDevices = yield navigator.mediaDevices.enumerateDevices();
12015
- return mediaDevices.filter(item => item.kind === 'videoinput');
12016
- });
12017
- /**
12018
- * 获取扬声器设备列表
12019
- */
12020
- const getSpeakers = () => __awaiter(void 0, void 0, void 0, function* () {
12021
- const mediaDevices = yield navigator.mediaDevices.enumerateDevices();
12022
- return mediaDevices.filter(item => item.kind === 'audiooutput');
12023
- });
12024
- const device = {
12025
- getCameras,
12026
- getMicrophones,
12027
- getSpeakers
12028
- };
12029
-
12030
12483
  /**
12031
12484
  * RTC 插件生成器
12032
12485
  * @public
@@ -12042,12 +12495,17 @@
12042
12495
  logger.error('Please use the https protocol or use `http://localhost` to open the page!');
12043
12496
  return false;
12044
12497
  }
12498
+ engine.VersionManage.add('plugin-rtc', "5.2.2-alpha.1");
12499
+ if (!engine.VersionManage.validEngine("~4.5.1")) {
12500
+ logger.error(`The current engine version '${engine.VersionManage.getInfo().engine}' error, plugin-rtc required engine version at least '${"~4.5.1"}'.`);
12501
+ return false;
12502
+ }
12045
12503
  return true;
12046
12504
  },
12047
12505
  setup(context, runtime, options = {}) {
12048
12506
  logger.setLogLevel(options.logLevel);
12049
12507
  logger.setLogStdout(options.logStdout);
12050
- logger.warn(`RCRTC Version: ${"5.1.10-alpha.3"}, Commit: ${"799cc871ab8fce4eb595d368ebaa84664d101f6f"}`);
12508
+ logger.warn(`RCRTC Version: ${"5.2.2-alpha.1"}, Commit: ${"de4f9bc28bbee35d2d5f206a68144c89c098573f"}`);
12051
12509
  logger.warn(`browserInfo.browser -> ${browserInfo.browser}`);
12052
12510
  logger.warn(`browserInfo.supportsUnifiedPlan -> ${browserInfo.supportsUnifiedPlan}`);
12053
12511
  logger.warn(`browserInfo.version -> ${browserInfo.version}`);