@rongcloud/plugin-rtc 5.2.2-alpha.1 → 5.2.4-beem.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.esm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
- * RCRTC - v5.2.2-alpha.1
3
- * CommitId - de4f9bc28bbee35d2d5f206a68144c89c098573f
4
- * Mon Nov 22 2021 10:51:42 GMT+0800 (China Standard Time)
2
+ * RCRTC - v5.2.4-beem.1
3
+ * CommitId - d026964c6715be7805a3e5c8addd64d4008d17bd
4
+ * Thu May 12 2022 18:57:27 GMT+0800 (China Standard Time)
5
5
  * ©2020 RongCloud, Inc. All rights reserved.
6
6
  */
7
7
  import { Logger, EventEmitter, isNumber, ErrorCode, ConnectionStatus, assert, ConversationType, RTCApiType, validate, isArray, RTCMode, isHttpUrl, isBoolean, HttpMethod, isString, notEmptyString, RTCJoinType, RTCIdentityChangeType, VersionManage } from '@rongcloud/engine';
@@ -5600,6 +5600,25 @@ var RCResolution;
5600
5600
  RCResolution["W1920_H1080"] = "W1920_H1080";
5601
5601
  })(RCResolution || (RCResolution = {}));
5602
5602
 
5603
+ /**
5604
+ * 媒体资源类型
5605
+ */
5606
+ var RCMediaType;
5607
+ (function (RCMediaType) {
5608
+ /**
5609
+ * 音频流
5610
+ */
5611
+ RCMediaType[RCMediaType["AUDIO_ONLY"] = 0] = "AUDIO_ONLY";
5612
+ /**
5613
+ * 视频流
5614
+ */
5615
+ RCMediaType[RCMediaType["VIDEO_ONLY"] = 1] = "VIDEO_ONLY";
5616
+ /**
5617
+ * 音视频混合流,只在 web 端存在混合流的情况
5618
+ */
5619
+ RCMediaType[RCMediaType["AUDIO_VIDEO"] = 2] = "AUDIO_VIDEO";
5620
+ })(RCMediaType || (RCMediaType = {}));
5621
+
5603
5622
  const RongRTCVideoBitrate = {
5604
5623
  [RCResolution.W176_H132]: { width: 176, height: 132, maxBitrate: 150, minBitrate: 80 },
5605
5624
  [RCResolution.W176_H144]: { width: 176, height: 144, maxBitrate: 160, minBitrate: 80 },
@@ -6118,6 +6137,40 @@ class RCCameraVideoTrack extends RCLocalVideoTrack {
6118
6137
  class RCScreenVideoTrack extends RCLocalVideoTrack {
6119
6138
  }
6120
6139
 
6140
+ class RCRemoteTrack extends RCTrack {
6141
+ constructor(tag, userId, kind, roomId) {
6142
+ super(tag, userId, kind, false, roomId);
6143
+ this._isSubscribed = false;
6144
+ }
6145
+ /**
6146
+ * 根据房间数据更新状态
6147
+ * @param value
6148
+ */
6149
+ __innerSetRemoteMuted(bool) {
6150
+ this._remoteMuted = bool;
6151
+ }
6152
+ __innerSetSubscribed(bool) {
6153
+ this._isSubscribed = bool;
6154
+ }
6155
+ /**
6156
+ * 查看是否已订阅了该远端资源
6157
+ * @returns
6158
+ */
6159
+ isSubscribed() {
6160
+ return this._isSubscribed;
6161
+ }
6162
+ }
6163
+ class RCRemoteAudioTrack extends RCRemoteTrack {
6164
+ constructor(tag, userId, roomId) {
6165
+ super(tag, userId, 'audio', roomId);
6166
+ }
6167
+ }
6168
+ class RCRemoteVideoTrack extends RCRemoteTrack {
6169
+ constructor(tag, userId, roomId) {
6170
+ super(tag, userId, 'video', roomId);
6171
+ }
6172
+ }
6173
+
6121
6174
  /**
6122
6175
  * 构建增量消息内容
6123
6176
  * @param objectname 消息名
@@ -6392,6 +6445,79 @@ const parseRoomData = (data) => {
6392
6445
  });
6393
6446
  return result;
6394
6447
  };
6448
+ /**
6449
+ * 解析观众加房间 kv 数据
6450
+ * 远端无人员时,kvEntries 的 key 不包含 RC_ANCHOR_LIST
6451
+ * 远端无资源时,key 不包含 RC_RES_、RC_CDN
6452
+ * 远端有资源、无 CDN 资源时,key 不包含 RC_CDN
6453
+ */
6454
+ const parseAudienceRoomData = (roomId, kvEntries) => {
6455
+ const sessionId = kvEntries.filter((kvItem) => {
6456
+ return kvItem.key === 'RC_RTC_SESSIONID';
6457
+ })[0].value;
6458
+ /**
6459
+ * 房间内远端人员
6460
+ */
6461
+ const remoteUserIds = kvEntries.filter((kvItem) => {
6462
+ return kvItem.key === 'RC_ANCHOR_LIST';
6463
+ }).map((kvItem) => JSON.parse(kvItem.value || '[]'))[0];
6464
+ /**
6465
+ * 远端 RTC、MUC 资源
6466
+ */
6467
+ const remoteRes = kvEntries.filter((kvItem) => {
6468
+ return kvItem.key.includes('RC_RES_');
6469
+ }).map((kvItem) => JSON.parse(kvItem.value || '{}'));
6470
+ /**
6471
+ * 远端 MUC 资源
6472
+ */
6473
+ const remoteMUCUris = remoteRes.length ? JSON.parse(remoteRes[0].mcu_uris || '[]') : [];
6474
+ /**
6475
+ * 远端 MUC tracks
6476
+ */
6477
+ const remoteMCUTracks = [];
6478
+ remoteMUCUris.forEach((uri) => {
6479
+ const { mediaType, tag } = uri;
6480
+ const track = mediaType === RCMediaType.AUDIO_ONLY ? new RCRemoteAudioTrack(tag, '', roomId) : new RCRemoteVideoTrack(tag, '', roomId);
6481
+ remoteMCUTracks.push(track);
6482
+ });
6483
+ /**
6484
+ * 远端 RTC 资源
6485
+ */
6486
+ const remoteRTCUris = [];
6487
+ /**
6488
+ * 远端 RTC tracks
6489
+ */
6490
+ const remoteRTCTracks = [];
6491
+ remoteRes.forEach((res) => {
6492
+ const RTCUris = JSON.parse(res.uris || '[]');
6493
+ remoteRTCUris.push(...RTCUris);
6494
+ RTCUris.forEach((uri) => {
6495
+ const { mediaType, tag, msid } = uri;
6496
+ const userId = msid.split('_')[0];
6497
+ const track = mediaType === RCMediaType.AUDIO_ONLY ? new RCRemoteAudioTrack(tag, userId) : new RCRemoteVideoTrack(tag, userId);
6498
+ remoteRTCTracks.push(track);
6499
+ });
6500
+ });
6501
+ /**
6502
+ * 房间内 CDN 信息
6503
+ */
6504
+ const CDNUris = kvEntries.filter((kvItem) => {
6505
+ return kvItem.key === 'RC_CDN';
6506
+ }).map((kvItem) => {
6507
+ const CDNUriStr = JSON.parse(kvItem.value || '[]');
6508
+ return JSON.parse(CDNUriStr.cdn_uris)[0];
6509
+ })[0];
6510
+ return {
6511
+ sessionId,
6512
+ remoteUserIds: remoteUserIds || [],
6513
+ remoteRTCUris,
6514
+ remoteMUCUris,
6515
+ remoteRTCTracks,
6516
+ remoteMCUTracks,
6517
+ remoteTracks: [...remoteRTCTracks, ...remoteMCUTracks],
6518
+ CDNUris: CDNUris || {}
6519
+ };
6520
+ };
6395
6521
 
6396
6522
  /**
6397
6523
  * RTC 消息类型常量
@@ -6557,7 +6683,7 @@ const handleAudioLevel = (audioLevel, factor = 2) => {
6557
6683
  audioLevel = audioLevel / 32767;
6558
6684
  }
6559
6685
  const rate = 10 ** factor;
6560
- return Math.floor(audioLevel * rate);
6686
+ return Math.ceil(audioLevel * rate);
6561
6687
  };
6562
6688
  /**
6563
6689
  * 计算丢包率
@@ -6599,25 +6725,6 @@ const senderHasRemoteData = (sender) => {
6599
6725
  return true;
6600
6726
  };
6601
6727
 
6602
- /**
6603
- * 媒体资源类型
6604
- */
6605
- var RCMediaType;
6606
- (function (RCMediaType) {
6607
- /**
6608
- * 音频流
6609
- */
6610
- RCMediaType[RCMediaType["AUDIO_ONLY"] = 0] = "AUDIO_ONLY";
6611
- /**
6612
- * 视频流
6613
- */
6614
- RCMediaType[RCMediaType["VIDEO_ONLY"] = 1] = "VIDEO_ONLY";
6615
- /**
6616
- * 音视频混合流,只在 web 端存在混合流的情况
6617
- */
6618
- RCMediaType[RCMediaType["AUDIO_VIDEO"] = 2] = "AUDIO_VIDEO";
6619
- })(RCMediaType || (RCMediaType = {}));
6620
-
6621
6728
  class AbstractStatParser {
6622
6729
  constructor(_rtcPeerConn, _sdpSemantics) {
6623
6730
  this._rtcPeerConn = _rtcPeerConn;
@@ -7075,7 +7182,7 @@ class RTCReportParser$2 extends AbstractStatParser {
7075
7182
  }
7076
7183
  const { trackId } = inboundInfo;
7077
7184
  // inboundInfo 中取不到 audioLevel 时,需从 type 为 track 中取
7078
- const { audioLevel } = inboundInfo || stats[trackId];
7185
+ const audioLevel = inboundInfo.audioLevel || stats[trackId].audioLevel;
7079
7186
  const resourceId = this.getResourceIdByParseSdp(inboundInfo);
7080
7187
  audioLevelList.push({
7081
7188
  trackId: resourceId,
@@ -7488,6 +7595,7 @@ class ASdpStrategy {
7488
7595
  */
7489
7596
  static setSdpSemantics(sdpSemantics) {
7490
7597
  const { browser, version, supportsUnifiedPlan } = browserInfo;
7598
+ logger.debug(`sdpSemantics, browser: ${browser}, version: ${version}, supportsUnifiedPlan: ${supportsUnifiedPlan}`);
7491
7599
  // 在明确不支持 unified-plan 的版本中使用 plan-b
7492
7600
  if (!supportsUnifiedPlan) {
7493
7601
  this._sdpSemantics = 'plan-b';
@@ -7764,8 +7872,12 @@ class UnifiedPlanStrategy extends ASdpStrategy {
7764
7872
  removeTracks.length && removeTracks.forEach(item => {
7765
7873
  const trackId = item.getTrackId();
7766
7874
  item.__innerSetMediaStreamTrack(undefined);
7875
+ /**
7876
+ * peerConnection ontrack 回调参数 RTCTrackEvent 对象中 streams 为 [] 时,服务端无资源,不会添加 transceiver
7877
+ * 需兼容无 transceiver 的情况
7878
+ */
7767
7879
  const transceiver = this._recvTransceiver[trackId];
7768
- transceiver.direction = 'inactive';
7880
+ transceiver && (transceiver.direction = 'inactive');
7769
7881
  });
7770
7882
  const addCount = { audio: 0, video: 0 };
7771
7883
  addTracks.length && addTracks.forEach(item => {
@@ -7917,6 +8029,14 @@ class RCRTCPeerConnection extends EventEmitter {
7917
8029
  }
7918
8030
  }
7919
8031
  _onTrackReady(evt) {
8032
+ /**
8033
+ * signal 和 mediaServer 不同步时,signal 有资源,mediaServer 没资源,
8034
+ * 订阅 mediaServer 不存在的资源时,对应 answer sdp 中的通道没有 ssrc,
8035
+ * ontrack 会被触发,但 RTCTrackEvent 对象中的 streams 为 [],需兼容
8036
+ */
8037
+ if (!evt.streams.length) {
8038
+ return;
8039
+ }
7920
8040
  // 更新 transceiver 与 trackId 的订阅关系
7921
8041
  const msid = evt.streams[0].id;
7922
8042
  const track = evt.receiver.track;
@@ -7933,13 +8053,13 @@ class RCRTCPeerConnection extends EventEmitter {
7933
8053
  return __awaiter(this, void 0, void 0, function* () {
7934
8054
  const offer = yield this._sdpStrategy.createOffer(iceRestart);
7935
8055
  // logger.debug(`sdpDemantics -> ${offer.semantics}`)
7936
- // logger.debug(`offer -> ${JSON.stringify(offer.sdp)}`)
8056
+ logger.debug(`offer -> ${JSON.stringify(offer.sdp)}`);
7937
8057
  return offer;
7938
8058
  });
7939
8059
  }
7940
8060
  setRemoteAnswer(answer) {
7941
8061
  return __awaiter(this, void 0, void 0, function* () {
7942
- // logger.debug(`answer -> ${JSON.stringify(answer)}`)
8062
+ logger.debug(`answer -> ${JSON.stringify(answer)}`);
7943
8063
  return this._sdpStrategy.setRemoteAnswer(answer);
7944
8064
  });
7945
8065
  }
@@ -8314,7 +8434,7 @@ class PolarisReporter {
8314
8434
  * 加入房间
8315
8435
  */
8316
8436
  sendR1() {
8317
- const rtcVersion = "5.2.2-alpha.1";
8437
+ const rtcVersion = "5.2.4-beem.1";
8318
8438
  const imVersion = this._context.getCoreVersion();
8319
8439
  const platform = 'web';
8320
8440
  const pcName = navigator.platform;
@@ -8336,40 +8456,6 @@ class PolarisReporter {
8336
8456
  }
8337
8457
  }
8338
8458
 
8339
- class RCRemoteTrack extends RCTrack {
8340
- constructor(tag, userId, kind, roomId) {
8341
- super(tag, userId, kind, false, roomId);
8342
- this._isSubscribed = false;
8343
- }
8344
- /**
8345
- * 根据房间数据更新状态
8346
- * @param value
8347
- */
8348
- __innerSetRemoteMuted(bool) {
8349
- this._remoteMuted = bool;
8350
- }
8351
- __innerSetSubscribed(bool) {
8352
- this._isSubscribed = bool;
8353
- }
8354
- /**
8355
- * 查看是否已订阅了该远端资源
8356
- * @returns
8357
- */
8358
- isSubscribed() {
8359
- return this._isSubscribed;
8360
- }
8361
- }
8362
- class RCRemoteAudioTrack extends RCRemoteTrack {
8363
- constructor(tag, userId, roomId) {
8364
- super(tag, userId, 'audio', roomId);
8365
- }
8366
- }
8367
- class RCRemoteVideoTrack extends RCRemoteTrack {
8368
- constructor(tag, userId, roomId) {
8369
- super(tag, userId, 'video', roomId);
8370
- }
8371
- }
8372
-
8373
8459
  /**
8374
8460
  * 北极星上报 R2 参数
8375
8461
  */
@@ -8678,15 +8764,18 @@ class RCAbstractRoom {
8678
8764
  logger.warn(`onKickOff -> byServer: ${byServer}`);
8679
8765
  this._ntfClearRoomItem();
8680
8766
  this._leaveHandle(!byServer);
8767
+ // 扩展字段,备注用户为什么被踢出房间
8768
+ let kickExtra;
8681
8769
  let kickType;
8682
8770
  if (byServer) {
8683
8771
  ((content === null || content === void 0 ? void 0 : content.users) || []).forEach(item => {
8684
8772
  if (item.userId === this._context.getCurrentId()) {
8685
8773
  kickType = item.type;
8774
+ kickExtra = item.kickExtra;
8686
8775
  }
8687
8776
  });
8688
8777
  }
8689
- this._callAppListener('onKickOff', byServer, kickType);
8778
+ this._callAppListener('onKickOff', byServer, kickType, kickExtra);
8690
8779
  }
8691
8780
  _rtcpeerClosed() {
8692
8781
  this._ntfClearRoomItem();
@@ -8707,7 +8796,8 @@ class RCAbstractRoom {
8707
8796
  return;
8708
8797
  }
8709
8798
  const { uris, ignore } = content;
8710
- if (ignore) {
8799
+ // 内置 CDN 为自动时,先收到 cdn_uris,无 uris 时,不用再对比资源
8800
+ if (ignore || !uris) {
8711
8801
  return;
8712
8802
  }
8713
8803
  const publishedList = [];
@@ -9300,14 +9390,13 @@ class RCAbstractRoom {
9300
9390
  extend: JSON.stringify({
9301
9391
  resolutionInfo: this._pc.getOutboundVideoInfo()
9302
9392
  }),
9303
- /**
9304
- * 需过滤房间内不存在的资源
9305
- */
9306
9393
  subscribeList: subscribeList.filter((item) => {
9307
- var _a;
9308
9394
  const trackId = item.track.getTrackId();
9309
9395
  const { userId } = parseTrackId(trackId);
9310
- const isInclude = (_a = this._roomResources[userId]) === null || _a === void 0 ? void 0 : _a.filter(item => trackId === `${item.msid}_${item.mediaType}`).length;
9396
+ if (!this._roomResources[userId]) {
9397
+ return false;
9398
+ }
9399
+ const isInclude = this._roomResources[userId].filter(item => trackId === `${item.msid}_${item.mediaType}`).length;
9311
9400
  return isInclude;
9312
9401
  }).map(item => ({
9313
9402
  simulcast: item.subTiny ? RCStreamType.TINY : RCStreamType.NORMAL,
@@ -9608,7 +9697,7 @@ class RCAbstractRoom {
9608
9697
  if (result.code !== RCRTCCode.SUCCESS) {
9609
9698
  return { code: result.code };
9610
9699
  }
9611
- const { sdp: answer, resultCode, message } = result.data;
9700
+ const { sdp: answer, resultCode, message, subscribedList } = result.data;
9612
9701
  if (resultCode !== RCRTCCode.SUCCESS) {
9613
9702
  logger.error(`change subscribe list failed: ${resultCode}`);
9614
9703
  return { code: resultCode };
@@ -9618,14 +9707,18 @@ class RCAbstractRoom {
9618
9707
  if (resCode !== RCRTCCode.SUCCESS) {
9619
9708
  return { code: resCode };
9620
9709
  }
9710
+ // 获取真正订阅成功的资源
9711
+ const subSuccessTrackIds = subscribedList === null || subscribedList === void 0 ? void 0 : subscribedList.map(item => `${item.msid}_${item.mediaType}`);
9712
+ const subSuccessList = attrs.filter(item => subSuccessTrackIds === null || subSuccessTrackIds === void 0 ? void 0 : subSuccessTrackIds.includes(item.track.getTrackId()));
9713
+ const failedList = attrs.filter(item => !(subSuccessTrackIds === null || subSuccessTrackIds === void 0 ? void 0 : subSuccessTrackIds.includes(item.track.getTrackId())));
9621
9714
  // 更新 remoteTrack.isSubscribed
9622
9715
  for (const trackId in this._remoteTracks) {
9623
- const subed = attrs.some(item => item.track.getTrackId() === trackId);
9716
+ const subed = subSuccessList.some(item => item.track.getTrackId() === trackId);
9624
9717
  this._remoteTracks[trackId].__innerSetSubscribed(subed);
9625
9718
  }
9626
9719
  // 更新本地订阅关系
9627
- this._subscribedList.splice(0, this._subscribedList.length, ...attrs);
9628
- return { code: RCRTCCode.SUCCESS };
9720
+ this._subscribedList.splice(0, this._subscribedList.length, ...subSuccessList);
9721
+ return failedList.length ? { code: RCRTCCode.SUCCESS, failedList } : { code: RCRTCCode.SUCCESS };
9629
9722
  });
9630
9723
  }
9631
9724
  /**
@@ -10583,7 +10676,7 @@ const getCommonHeader = () => ({
10583
10676
  'Content-Type': 'application/json;charset=UTF-8',
10584
10677
  'Cache-Control': 'no-cache',
10585
10678
  ClientType: `web|${browserInfo.browser}|${browserInfo.version}`,
10586
- ClientVersion: "5.2.2-alpha.1",
10679
+ ClientVersion: "5.2.4-beem.1",
10587
10680
  'Client-Session-Id': getUUID(),
10588
10681
  'Request-Id': Date.now().toString()
10589
10682
  });
@@ -11050,14 +11143,28 @@ class RCAudienceLivingRoom {
11050
11143
  this._roomId = _roomId;
11051
11144
  this._joinResData = _joinResData;
11052
11145
  this._livingType = _livingType;
11146
+ /**
11147
+ * 主播列表
11148
+ */
11053
11149
  this._roomAnchorList = [];
11150
+ /**
11151
+ * 合流、分流资源
11152
+ */
11054
11153
  this._roomRes = {};
11154
+ /**
11155
+ * 主播分流资源
11156
+ */
11055
11157
  this._roomAnchorRes = {};
11158
+ /**
11159
+ * 合流、分流 remoteTracks
11160
+ */
11056
11161
  this._remoteTracks = {};
11057
11162
  this._appListener = null;
11058
11163
  this._subscribedList = [];
11059
11164
  this._sessionId = '';
11060
11165
  this._destroyed = false;
11166
+ // 解析服务返回的 KV 数据,并赋值房间内数据
11167
+ this._setInitData();
11061
11168
  this._service = new RCMediaService(this._runtime, this._context, this._initOptions.mediaServer, this._initOptions.timeout);
11062
11169
  // 北极星数据
11063
11170
  this._polarisReport = new PolarisReporter(this._context, this._runtime, this._roomId, this, PolarisRole.Audience);
@@ -11079,6 +11186,54 @@ class RCAudienceLivingRoom {
11079
11186
  // 房间主播加入|离开房间、发布|取消发布资源变更监听
11080
11187
  this._context.onrtcdatachange = this.singalDataChange.bind(this);
11081
11188
  }
11189
+ /**
11190
+ * 解析服务端返回的 KV 数据,赋值 room 内数据
11191
+ */
11192
+ _setInitData() {
11193
+ const { sessionId, remoteUserIds, remoteRTCUris, remoteMUCUris, remoteTracks, CDNUris } = parseAudienceRoomData(this._roomId, this._joinResData.kvEntries);
11194
+ /**
11195
+ * session 赋值
11196
+ */
11197
+ this._sessionId = sessionId;
11198
+ /**
11199
+ * 主播列表赋值
11200
+ */
11201
+ this._roomAnchorList = remoteUserIds;
11202
+ /**
11203
+ * RTC、MCU tracks 赋值
11204
+ */
11205
+ remoteTracks.forEach((track) => {
11206
+ this._remoteTracks[track.getTrackId()] = track;
11207
+ });
11208
+ /**
11209
+ * _CDNUris 赋值
11210
+ */
11211
+ this._CDNUris = CDNUris;
11212
+ /**
11213
+ * 房间内 RTC 资源赋值
11214
+ */
11215
+ remoteRTCUris.forEach((uri) => {
11216
+ const userId = uri.msid.split('_')[0];
11217
+ if (this._roomAnchorRes[userId]) {
11218
+ this._roomAnchorRes[userId].push(uri);
11219
+ }
11220
+ else {
11221
+ this._roomAnchorRes[userId] = [uri];
11222
+ }
11223
+ });
11224
+ /**
11225
+ * 房间内 RTC、MCU 资源赋值
11226
+ */
11227
+ remoteMUCUris.forEach((uri) => {
11228
+ const { mediaType, tag } = uri;
11229
+ const trackId = [this._roomId, tag, mediaType].join('_');
11230
+ this._roomRes[trackId] = uri;
11231
+ });
11232
+ remoteRTCUris.forEach((uri) => {
11233
+ const trackId = getTrackId(uri);
11234
+ this._roomRes[trackId] = uri;
11235
+ });
11236
+ }
11082
11237
  _assertRoomDestroyed() {
11083
11238
  if (this._destroyed) {
11084
11239
  const msg = 'This room has been destroyed. Please use `RCRTCClient.joinLivingRoomAsAudience` to catch another instance.';
@@ -11128,9 +11283,6 @@ class RCAudienceLivingRoom {
11128
11283
  this._handleLeftedAnchor(leftUserIds);
11129
11284
  }
11130
11285
  }
11131
- if (key === 'RC_RTC_SESSIONID') {
11132
- this._sessionId = value;
11133
- }
11134
11286
  });
11135
11287
  // 处理直播间 MCU 合流资源资源
11136
11288
  this._diffRoomResource(allMcuUris);
@@ -11536,7 +11688,7 @@ class RCAudienceLivingRoom {
11536
11688
  if (result.code !== RCRTCCode.SUCCESS) {
11537
11689
  return { code: result.code };
11538
11690
  }
11539
- const { sdp: answer, resultCode, message } = result.data;
11691
+ const { sdp: answer, resultCode, message, subscribedList } = result.data;
11540
11692
  if (resultCode !== RCRTCCode.SUCCESS) {
11541
11693
  logger.error('change subscribe list failed:', message, resultCode);
11542
11694
  return { code: resultCode };
@@ -11555,16 +11707,28 @@ class RCAudienceLivingRoom {
11555
11707
  if (resCode !== RCRTCCode.SUCCESS) {
11556
11708
  return { code: resCode };
11557
11709
  }
11710
+ // 获取真正订阅成功的资源
11711
+ const subSuccessTrackIds = subscribedList === null || subscribedList === void 0 ? void 0 : subscribedList.map(item => `${item.msid}_${item.mediaType}`);
11712
+ const subSuccessList = attrs.filter(item => {
11713
+ if (item.track.isMCUTrack()) {
11714
+ const serverTrackInfo = this._roomRes[item.track.getTrackId()];
11715
+ const sdpResourceId = `${serverTrackInfo.msid}_${serverTrackInfo.mediaType}`;
11716
+ return subSuccessTrackIds.includes(sdpResourceId);
11717
+ }
11718
+ return subSuccessTrackIds === null || subSuccessTrackIds === void 0 ? void 0 : subSuccessTrackIds.includes(item.track.getTrackId());
11719
+ });
11720
+ const afterReplaceTrackIds = subSuccessList === null || subSuccessList === void 0 ? void 0 : subSuccessList.map(item => `${item.track.getTrackId()}`);
11721
+ const failedList = attrs.filter(item => !(afterReplaceTrackIds === null || afterReplaceTrackIds === void 0 ? void 0 : afterReplaceTrackIds.includes(item.track.getTrackId())));
11558
11722
  // 更新 remoteTrack.isSubscribed
11559
11723
  for (const trackId in this._remoteTracks) {
11560
- const subed = attrs.some(item => {
11724
+ const subed = subSuccessList.some(item => {
11561
11725
  return item.track.getTrackId() === trackId;
11562
11726
  });
11563
11727
  this._remoteTracks[trackId].__innerSetSubscribed(subed);
11564
11728
  }
11565
11729
  // 更新本地订阅关系
11566
- this._subscribedList.splice(0, this._subscribedList.length, ...attrs);
11567
- return { code: RCRTCCode.SUCCESS };
11730
+ this._subscribedList.splice(0, this._subscribedList.length, ...subSuccessList);
11731
+ return failedList.length ? { code: RCRTCCode.SUCCESS, failedList } : { code: RCRTCCode.SUCCESS };
11568
11732
  });
11569
11733
  }
11570
11734
  /**
@@ -11572,12 +11736,11 @@ class RCAudienceLivingRoom {
11572
11736
  * @param newCDNUris 新的 cdn_uris 数据
11573
11737
  */
11574
11738
  _diffCDNUris(newCDNUris) {
11575
- var _a, _b, _c, _d, _e, _f, _g, _h;
11576
11739
  return __awaiter(this, void 0, void 0, function* () {
11577
11740
  /**
11578
11741
  * CDN 资源减少: 上次 CDNUris 中有 url,变更后无 url
11579
11742
  */
11580
- if (((_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.url) && !newCDNUris.url) {
11743
+ if (this._CDNUris.url && !newCDNUris.url) {
11581
11744
  this._callAppListener('onCDNInfoDisable');
11582
11745
  /**
11583
11746
  * 更新内存中存储的 cdn_uris 数据
@@ -11590,22 +11753,22 @@ class RCAudienceLivingRoom {
11590
11753
  * 内存中无 CDNUris 或
11591
11754
  * 上次 CDNUris 无 url,变更后有 url
11592
11755
  */
11593
- if (!this._CDNUris || (!((_b = this._CDNUris) === null || _b === void 0 ? void 0 : _b.url) && newCDNUris.url)) {
11756
+ if (!this._CDNUris || (!this._CDNUris.url && newCDNUris.url)) {
11594
11757
  this._callAppListener('onCDNInfoEnable', {
11595
11758
  resolution: `W${newCDNUris.w}_H${newCDNUris.h}`,
11596
- fps: newCDNUris.fps
11759
+ fps: `FPS_${newCDNUris.fps}`
11597
11760
  });
11598
11761
  }
11599
11762
  /**
11600
11763
  * CDN 资源变更: w、h、fps 其中一项变化
11601
11764
  */
11602
- 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));
11603
- 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));
11604
- 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));
11765
+ const isWChange = (this._CDNUris.w && newCDNUris.w && (this._CDNUris.w !== newCDNUris.w));
11766
+ const isHChange = (this._CDNUris.h && newCDNUris.h && (this._CDNUris.h !== newCDNUris.h));
11767
+ const isFpsChange = (this._CDNUris.fps && newCDNUris.fps && (this._CDNUris.fps !== newCDNUris.fps));
11605
11768
  if (isWChange || isHChange || isFpsChange) {
11606
11769
  this._callAppListener('onCDNInfoChange', {
11607
11770
  resolution: `W${newCDNUris.w}_H${newCDNUris.h}`,
11608
- fps: newCDNUris.fps
11771
+ fps: `FPS_${newCDNUris.fps}`
11609
11772
  });
11610
11773
  }
11611
11774
  /**
@@ -11616,21 +11779,16 @@ class RCAudienceLivingRoom {
11616
11779
  }
11617
11780
  /**
11618
11781
  * 获取 CDN 资源对应的拉流地址
11619
- * 首次获取 CDNPlayUrl 时,需传入 url,
11620
- * 业务层调用时使用内存中 _CDNUris 的 url,无 _CDNUris 时说明观众端未赋值过 _CDNUris
11782
+ * _CDNUris url 时,说明未开启 CDN 推送
11621
11783
  * @returns CDNPlayUrl
11622
11784
  */
11623
- _getCDNPlayUrl(params, url) {
11624
- var _a, _b;
11785
+ _getCDNPlayUrl(params) {
11625
11786
  return __awaiter(this, void 0, void 0, function* () {
11626
11787
  const { w, h, fps } = params;
11627
11788
  const kind = this._initOptions.pullInnerCDNProtocol || RCInnerCDNPullKind.FLV;
11628
11789
  const useHttps = (this._initOptions.pullInnerCDNUseHttps === RCInnerCDNPullIsHttps.NOT_HTTPS) ? RCInnerCDNPullIsHttps.NOT_HTTPS : RCInnerCDNPullIsHttps.HTTPS;
11629
- /**
11630
- * 加入房间后拉 KV 数据,数据还未返回时,同步拉 KV 获取 CDN 信息
11631
- */
11632
- if (!((_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.url) && !url) {
11633
- logger.error(`cdn_uris url is empty, the anchor need to start CDN, code: ${RCRTCCode.CDN_RESOURCE_IS_EMPTY}`);
11790
+ if (!this._CDNUris.url) {
11791
+ logger.error(`cdn_uris url is empty, the anchor need to open or push CDN, code: ${RCRTCCode.CDN_RESOURCE_IS_EMPTY}`);
11634
11792
  return { code: RCRTCCode.CDN_RESOURCE_IS_EMPTY };
11635
11793
  }
11636
11794
  const headers = {
@@ -11647,7 +11805,7 @@ class RCAudienceLivingRoom {
11647
11805
  paramsArr.push(`kind=${kind}`);
11648
11806
  paramsArr.push(`is_https=${useHttps}`);
11649
11807
  const paramsStr = paramsArr.join('&');
11650
- let requestUrl = `${url || ((_b = this._CDNUris) === null || _b === void 0 ? void 0 : _b.url)}?`;
11808
+ let requestUrl = `${this._CDNUris.url}?`;
11651
11809
  paramsStr && (requestUrl += paramsStr);
11652
11810
  const { code, res } = yield this._service.getCDNResourceInfo(headers, requestUrl);
11653
11811
  if (code !== RCRTCCode.SUCCESS) {
@@ -11784,12 +11942,7 @@ class RCAudienceLivingRoom {
11784
11942
  * @param tag 参数描述
11785
11943
  */
11786
11944
  registerRoomEventListener(listener) {
11787
- var _a;
11788
11945
  this._appListener = listener;
11789
- if (!listener) {
11790
- return;
11791
- }
11792
- ((_a = this._joinResData.kvEntries) === null || _a === void 0 ? void 0 : _a.length) && this.singalDataChange(this._joinResData.kvEntries, this._roomId);
11793
11946
  }
11794
11947
  /**
11795
11948
  * 音量上报
@@ -11870,6 +12023,44 @@ class RCAudienceLivingRoom {
11870
12023
  });
11871
12024
  return [...mcuTracks, ...tracks];
11872
12025
  }
12026
+ /**
12027
+ * 获取远端 RTC tracks
12028
+ */
12029
+ getRemoteRTCTracks() {
12030
+ const tracks = [];
12031
+ for (const trackId in this._remoteTracks) {
12032
+ const track = this._remoteTracks[trackId];
12033
+ if (!track.isMCUTrack()) {
12034
+ tracks.push(track);
12035
+ }
12036
+ }
12037
+ return tracks;
12038
+ }
12039
+ /**
12040
+ * 获取远端 MCU tracks
12041
+ */
12042
+ getRemoteMCUTracks() {
12043
+ const tracks = [];
12044
+ for (const trackId in this._remoteTracks) {
12045
+ const track = this._remoteTracks[trackId];
12046
+ if (track.isMCUTrack()) {
12047
+ tracks.push(track);
12048
+ }
12049
+ }
12050
+ return tracks;
12051
+ }
12052
+ /**
12053
+ * 获取房间内 CDN 信息
12054
+ */
12055
+ getCDNInfo() {
12056
+ return this._CDNUris.w ? {
12057
+ resolution: `W${this._CDNUris.w}_H${this._CDNUris.h}`,
12058
+ fps: `FPS_${this._CDNUris.fps}`,
12059
+ CDNEnable: this._CDNUris.enableInnerCDN
12060
+ } : {
12061
+ CDNEnable: false
12062
+ };
12063
+ }
11873
12064
  }
11874
12065
 
11875
12066
  const getTracksWithOptions = (stream, options) => {
@@ -11921,11 +12112,15 @@ class RCRTCClient {
11921
12112
  /**
11922
12113
  * 加入普通音视频房间
11923
12114
  * @param roomId
12115
+ * @param joinType 多端处理方式
12116
+ * @param outerUserDatas 业务层设置人员属性
12117
+ * @param useMutilPeerC
12118
+ * @param roomType 加入房间的类型 默认参数 RTCMode.RTC
11924
12119
  */
11925
- joinRTCRoom(roomId, joinType) {
11926
- return push(() => this._joinRTCRoom(roomId, joinType));
12120
+ joinRTCRoom(roomId, joinType, outerUserDatas, useMutilPeerC, roomType = RTCMode.RTC) {
12121
+ return push(() => this._joinRTCRoom(roomId, joinType, outerUserDatas, useMutilPeerC, roomType));
11927
12122
  }
11928
- _joinRTCRoom(roomId, joinType) {
12123
+ _joinRTCRoom(roomId, joinType, outerUserDatas, useMutilPeerC, roomType = RTCMode.RTC) {
11929
12124
  return __awaiter(this, void 0, void 0, function* () {
11930
12125
  if (isIllegalConnection(this._context.getNaviInfo())) {
11931
12126
  return { code: RCRTCCode.PACKAGE_ENVIRONMENT_ERROR };
@@ -11933,6 +12128,9 @@ class RCRTCClient {
11933
12128
  if (!validate('roomId', roomId, notEmptyString, true)) {
11934
12129
  return { code: RCRTCCode.PARAMS_ERROR };
11935
12130
  }
12131
+ if (!validate('roomType', roomType, (value) => RTCMode[value] !== undefined)) {
12132
+ return { code: RCRTCCode.PARAMS_ERROR };
12133
+ }
11936
12134
  if (this._crtRoom) {
11937
12135
  return { code: RCRTCCode.REPERT_JOIN_ROOM };
11938
12136
  }
@@ -11943,8 +12141,8 @@ class RCRTCClient {
11943
12141
  if (!urls.length) {
11944
12142
  return { code: RCRTCCode.NOT_OPEN_VIDEO_AUDIO_SERVER };
11945
12143
  }
11946
- logger.debug(`joinRoom -> roomId: ${roomId}; joinType: ${joinType || RTCJoinType.KICK}`);
11947
- const { code, data } = yield this._context.joinRTCRoom(roomId, RTCMode.RTC, undefined, joinType);
12144
+ logger.debug(`joinRoom -> roomId: ${roomId}; joinType: ${joinType || RTCJoinType.KICK} roomType: ${roomType}`);
12145
+ const { code, data } = yield this._context.joinRTCRoom(roomId, roomType, undefined, joinType);
11948
12146
  if (code !== ErrorCode.SUCCESS) {
11949
12147
  logger.error(`joinRoom failed -> code: ${code}`);
11950
12148
  const errorCode = code === RTCSignalCode.JOIN_REFUSED ? RCRTCCode.SIGNAL_JOIN_RTC_ROOM_REFUSED : code;
@@ -12375,7 +12573,14 @@ class RCRTCClient {
12375
12573
  logger.info(`joinLivingRoomAsAudience success, room data: ${JSON.stringify(data)}`);
12376
12574
  const room = new RCAudienceLivingRoom(this._context, this._runtime, this._options, roomId, data, livingType);
12377
12575
  this._crtAudienceLivingRoom = room;
12378
- return { room, code: RCRTCCode.SUCCESS };
12576
+ return {
12577
+ room,
12578
+ code: RCRTCCode.SUCCESS,
12579
+ userIds: room.getRemoteUserIds(),
12580
+ RTCTracks: room.getRemoteRTCTracks(),
12581
+ MCUTracks: room.getRemoteMCUTracks(),
12582
+ CDNUris: room.getCDNInfo()
12583
+ };
12379
12584
  });
12380
12585
  }
12381
12586
  /**
@@ -12446,7 +12651,14 @@ class RCRTCClient {
12446
12651
  this._crtRoom.__destroy(false);
12447
12652
  // 重置主播房间
12448
12653
  this._crtRoom = null;
12449
- return { room: crtRoom, code: RCRTCCode.SUCCESS };
12654
+ return {
12655
+ room: crtRoom,
12656
+ code: RCRTCCode.SUCCESS,
12657
+ userIds: crtRoom.getRemoteUserIds(),
12658
+ RTCTracks: crtRoom.getRemoteRTCTracks(),
12659
+ MCUTracks: crtRoom.getRemoteMCUTracks(),
12660
+ CDNUris: crtRoom.getCDNInfo()
12661
+ };
12450
12662
  });
12451
12663
  }
12452
12664
  /**
@@ -12492,9 +12704,9 @@ const installer = {
12492
12704
  logger.error('Please use the https protocol or use `http://localhost` to open the page!');
12493
12705
  return false;
12494
12706
  }
12495
- VersionManage.add('plugin-rtc', "5.2.2-alpha.1");
12496
- if (!VersionManage.validEngine("~4.5.1")) {
12497
- logger.error(`The current engine version '${VersionManage.getInfo().engine}' error, plugin-rtc required engine version at least '${"~4.5.1"}'.`);
12707
+ VersionManage.add('plugin-rtc', "5.2.4-beem.1");
12708
+ if (!VersionManage.validEngine("4.6.0-beem.5")) {
12709
+ logger.error(`The current engine version '${VersionManage.getInfo().engine}' error, plugin-rtc required engine version at least '${"4.6.0-beem.5"}'.`);
12498
12710
  return false;
12499
12711
  }
12500
12712
  return true;
@@ -12502,7 +12714,7 @@ const installer = {
12502
12714
  setup(context, runtime, options = {}) {
12503
12715
  logger.setLogLevel(options.logLevel);
12504
12716
  logger.setLogStdout(options.logStdout);
12505
- logger.warn(`RCRTC Version: ${"5.2.2-alpha.1"}, Commit: ${"de4f9bc28bbee35d2d5f206a68144c89c098573f"}`);
12717
+ logger.warn(`RCRTC Version: ${"5.2.4-beem.1"}, Commit: ${"d026964c6715be7805a3e5c8addd64d4008d17bd"}`);
12506
12718
  logger.warn(`browserInfo.browser -> ${browserInfo.browser}`);
12507
12719
  logger.warn(`browserInfo.supportsUnifiedPlan -> ${browserInfo.supportsUnifiedPlan}`);
12508
12720
  logger.warn(`browserInfo.version -> ${browserInfo.version}`);