@rongcloud/plugin-rtc 5.1.10-alpha.2 → 5.1.10-enterprise.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.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
- * RCRTC - v5.1.10-alpha.2
3
- * CommitId - 5c3523dd268a25fff2fcbb7d04f6acf3265411d6
4
- * Tue Oct 19 2021 14:37:09 GMT+0800 (China Standard Time)
2
+ * RCRTC - v5.1.10-enterprise.1
3
+ * CommitId - 32f47afe02bd4b5db65ed78dd44330eb84e75059
4
+ * Fri Apr 29 2022 19:04:03 GMT+0800 (China Standard Time)
5
5
  * ©2020 RongCloud, Inc. All rights reserved.
6
6
  */
7
7
  'use strict';
@@ -110,19 +110,9 @@ exports.RCRTCCode = void 0;
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
- /** 加入 RTC 房间 joinTYype 为 1 时,当前有其他端在房间时的应答码 */
114
- RCRTCCode[RCRTCCode["SIGNAL_JOIN_RTC_ROOM_REFUSED"] = 53207] = "SIGNAL_JOIN_RTC_ROOM_REFUSED";
113
+ /** 房间内无主播推 CDN */
114
+ RCRTCCode[RCRTCCode["CDN_RESOURCE_IS_EMPTY"] = 53027] = "CDN_RESOURCE_IS_EMPTY";
115
115
  })(exports.RCRTCCode || (exports.RCRTCCode = {}));
116
- /**
117
- * RTC 信令 Server 返回需处理的错误 Code
118
- */
119
- var RTCSignalCode;
120
- (function (RTCSignalCode) {
121
- /**
122
- * 加入 RTC 房间 joinTYype 为 1 时,当前有其他端在房间时的应答码
123
- */
124
- RTCSignalCode[RTCSignalCode["JOIN_REFUSED"] = 40032] = "JOIN_REFUSED";
125
- })(RTCSignalCode || (RTCSignalCode = {}));
126
116
 
127
117
  class AsyncTaskQueue {
128
118
  constructor() {
@@ -6160,7 +6150,7 @@ const deepCopyResources = (resources) => {
6160
6150
  * @param prevResources 原资源数据
6161
6151
  * @param resources 变更的全量资源
6162
6152
  */
6163
- const diffPublishResources = (prevResources, resources, isReconnect = false) => {
6153
+ const diffPublishResources = (prevResources, resources) => {
6164
6154
  prevResources = prevResources.slice();
6165
6155
  const publishedList = [];
6166
6156
  const unpublishedList = [];
@@ -6169,15 +6159,7 @@ const diffPublishResources = (prevResources, resources, isReconnect = false) =>
6169
6159
  resources.forEach(item => {
6170
6160
  const resId = getTrackId(item);
6171
6161
  // 从当前房间数据中查找相同资源索引
6172
- let index = prevResources.findIndex(value => getTrackId(value) === resId);
6173
- /**
6174
- * 重连计算时,直接通过 uri 来算新增和删减的资源。因为 resources 即是最新资源,不能算资源已重新发布的情况
6175
- * 在断网重连情况下如果使用 trackId 计算 index 会导致己端在断网期间,远端取消发布资源 A(tag:C)又重新发布资源 B(tag:C)时, 无法
6176
- * 计算出取消发布的资源 A,只能算出新发布的资源 B, 导致页面视图无法更新、且订阅成功 B 资源后不抛 onTrackReady
6177
- */
6178
- if (isReconnect) {
6179
- index = prevResources.findIndex(value => value.uri === item.uri);
6180
- }
6162
+ const index = prevResources.findIndex(value => getTrackId(value) === resId);
6181
6163
  if (index === -1) {
6182
6164
  // 新增资源
6183
6165
  publishedList.push(item);
@@ -6297,7 +6279,7 @@ const isNull = (val) => {
6297
6279
  * 公有云连接私有云 SDK 为非法连接
6298
6280
  */
6299
6281
  const isIllegalConnection = (navi) => {
6300
- return navi.type === 1;
6282
+ return !true ;
6301
6283
  };
6302
6284
  /**
6303
6285
  * 获取将要发布的 track 数量
@@ -6320,6 +6302,27 @@ const calcTracksNum = (tracks) => {
6320
6302
  });
6321
6303
  return length;
6322
6304
  };
6305
+ /**
6306
+ * 解析房间数据
6307
+ */
6308
+ const parseRoomData = (data) => {
6309
+ const result = {};
6310
+ const userIds = Object.keys(data.users);
6311
+ userIds.length && userIds.forEach(userId => {
6312
+ const tmp = [];
6313
+ const userData = data.users[userId];
6314
+ if (userData.uris) {
6315
+ try {
6316
+ tmp.push(...JSON.parse(userData.uris));
6317
+ }
6318
+ catch (error) {
6319
+ logger.warn(`invalid user data -> userId: ${userId}, userData: ${userData}`);
6320
+ }
6321
+ }
6322
+ result[userId] = tmp;
6323
+ });
6324
+ return result;
6325
+ };
6323
6326
 
6324
6327
  /**
6325
6328
  * RTC 消息类型常量
@@ -6364,12 +6367,6 @@ var RCRTCMessageType;
6364
6367
  RCRTCMessageType["KICK"] = "RCRTC:kick";
6365
6368
  })(RCRTCMessageType || (RCRTCMessageType = {}));
6366
6369
 
6367
- exports.RCRTCPingResult = void 0;
6368
- (function (RCRTCPingResult) {
6369
- RCRTCPingResult["SUCCESS"] = "Success";
6370
- RCRTCPingResult["FAIL"] = "Fail";
6371
- })(exports.RCRTCPingResult || (exports.RCRTCPingResult = {}));
6372
-
6373
6370
  /**
6374
6371
  * rtcping 间隔
6375
6372
  */
@@ -6406,7 +6403,7 @@ class Pinger {
6406
6403
  });
6407
6404
  }
6408
6405
  _loop() {
6409
- var _a, _b, _c;
6406
+ var _a;
6410
6407
  return __awaiter(this, void 0, void 0, function* () {
6411
6408
  // logger.debug('rtcping send ->')
6412
6409
  const code = yield new Promise(resolve => {
@@ -6423,15 +6420,13 @@ class Pinger {
6423
6420
  if (code === engine.ErrorCode.SUCCESS) {
6424
6421
  // logger.debug('rtcping success <-')
6425
6422
  this._latestTimestamp = now;
6426
- (_a = this.onPingResult) === null || _a === void 0 ? void 0 : _a.call(this, exports.RCRTCPingResult.SUCCESS);
6427
6423
  return;
6428
6424
  }
6429
- (_b = this.onPingResult) === null || _b === void 0 ? void 0 : _b.call(this, exports.RCRTCPingResult.FAIL);
6430
6425
  logger.warn(`rtcping failed -> code: ${code}`);
6431
6426
  // 超出 1 分钟未成功进行 rtcping 操作,或用户已不存在于房间内时,通知客户离线
6432
6427
  if (code === 40003 || now - this._latestTimestamp > 60 * 1000) {
6433
6428
  this.stop();
6434
- (_c = this.onFailed) === null || _c === void 0 ? void 0 : _c.call(this, code === 40003);
6429
+ (_a = this.onFailed) === null || _a === void 0 ? void 0 : _a.call(this, code === 40003);
6435
6430
  }
6436
6431
  });
6437
6432
  }
@@ -6485,7 +6480,7 @@ const handleAudioLevel = (audioLevel, factor = 2) => {
6485
6480
  audioLevel = audioLevel / 32767;
6486
6481
  }
6487
6482
  const rate = 10 ** factor;
6488
- return Math.floor(audioLevel * rate);
6483
+ return Math.ceil(audioLevel * rate);
6489
6484
  };
6490
6485
  /**
6491
6486
  * 计算丢包率
@@ -7003,7 +6998,7 @@ class RTCReportParser$2 extends AbstractStatParser {
7003
6998
  }
7004
6999
  const { trackId } = inboundInfo;
7005
7000
  // inboundInfo 中取不到 audioLevel 时,需从 type 为 track 中取
7006
- const { audioLevel } = inboundInfo || stats[trackId];
7001
+ const audioLevel = inboundInfo.audioLevel || stats[trackId].audioLevel;
7007
7002
  const resourceId = this.getResourceIdByParseSdp(inboundInfo);
7008
7003
  audioLevelList.push({
7009
7004
  trackId: resourceId,
@@ -7692,8 +7687,12 @@ class UnifiedPlanStrategy extends ASdpStrategy {
7692
7687
  removeTracks.length && removeTracks.forEach(item => {
7693
7688
  const trackId = item.getTrackId();
7694
7689
  item.__innerSetMediaStreamTrack(undefined);
7690
+ /**
7691
+ * peerConnection ontrack 回调参数 RTCTrackEvent 对象中 streams 为 [] 时,服务端无资源,不会添加 transceiver
7692
+ * 需兼容无 transceiver 的情况
7693
+ */
7695
7694
  const transceiver = this._recvTransceiver[trackId];
7696
- transceiver.direction = 'inactive';
7695
+ transceiver && (transceiver.direction = 'inactive');
7697
7696
  });
7698
7697
  const addCount = { audio: 0, video: 0 };
7699
7698
  addTracks.length && addTracks.forEach(item => {
@@ -7821,7 +7820,6 @@ class RCRTCPeerConnection extends engine.EventEmitter {
7821
7820
  logger.info(`onconnectionstatechange -> ${this._rtcPeerConn.connectionState}`);
7822
7821
  }
7823
7822
  _onICEConnectionStateChange() {
7824
- var _a, _b;
7825
7823
  logger.info(`oniceconnectionstatechange -> ${this._rtcPeerConn.iceConnectionState}`);
7826
7824
  if (this._rtcPeerConn.iceConnectionState === 'connected') {
7827
7825
  // 开启 peerConnection stats 统计定时器
@@ -7831,20 +7829,21 @@ class RCRTCPeerConnection extends engine.EventEmitter {
7831
7829
  this._reportStatsTimer = setInterval(this._reportHandle.bind(this), 1000);
7832
7830
  }
7833
7831
  // ICE 连接中断后,需要尝试重新走 exchange 流程以恢复
7834
- if (this._rtcPeerConn.iceConnectionState === 'failed' || this._rtcPeerConn.iceConnectionState === 'disconnected') {
7832
+ if (this._rtcPeerConn.iceConnectionState === 'failed') {
7835
7833
  logger.warn('iceconenction state is `failed`, exchange SDP to try again.');
7836
7834
  this._reTryExchange();
7837
7835
  this._reTryExchangeTimer = setInterval(this._reTryExchange, 15 * 1000);
7838
7836
  }
7839
- // ICE 变更通知
7840
- try {
7841
- (_b = (_a = this._reportListener) === null || _a === void 0 ? void 0 : _a.onICEConnectionStateChange) === null || _b === void 0 ? void 0 : _b.call(_a, this._rtcPeerConn.iceConnectionState);
7842
- }
7843
- catch (error) {
7844
- logger.error('onICEConnectionStateChange error', error);
7845
- }
7846
7837
  }
7847
7838
  _onTrackReady(evt) {
7839
+ /**
7840
+ * signal 和 mediaServer 不同步时,signal 有资源,mediaServer 没资源,
7841
+ * 订阅 mediaServer 不存在的资源时,对应 answer sdp 中的通道没有 ssrc,
7842
+ * ontrack 会被触发,但 RTCTrackEvent 对象中的 streams 为 [],需兼容
7843
+ */
7844
+ if (!evt.streams.length) {
7845
+ return;
7846
+ }
7848
7847
  // 更新 transceiver 与 trackId 的订阅关系
7849
7848
  const msid = evt.streams[0].id;
7850
7849
  const track = evt.receiver.track;
@@ -8242,7 +8241,7 @@ class PolarisReporter {
8242
8241
  * 加入房间
8243
8242
  */
8244
8243
  sendR1() {
8245
- const rtcVersion = "5.1.10-alpha.2";
8244
+ const rtcVersion = "5.1.10-enterprise.1";
8246
8245
  const imVersion = this._context.getCoreVersion();
8247
8246
  const platform = 'web';
8248
8247
  const pcName = navigator.platform;
@@ -8378,24 +8377,6 @@ class RCAudioLevelReport {
8378
8377
  }
8379
8378
  }
8380
8379
 
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
- };
8399
8380
  const getTrackIdFromAttr = (track) => {
8400
8381
  if (track instanceof RCTrack) {
8401
8382
  return track.getTrackId();
@@ -8453,11 +8434,10 @@ class RCAbstractRoom {
8453
8434
  /**
8454
8435
  * 观众升级为主播后不会收到全量 uri 消息,需直接触发人员、资源变更
8455
8436
  */
8456
- isUpgrade && this._afterChangedRole(parseRoomData(data));
8437
+ isUpgrade && this._afterChangedRole(data);
8457
8438
  // 开始心跳,心跳失败时主动退出房间
8458
8439
  this._pinger = new Pinger(_roomId, this._roomMode, _context, this._initOptions.pingGap);
8459
8440
  this._pinger.onFailed = this._kickoff.bind(this);
8460
- this._pinger.onPingResult = this._handlePingResult.bind(this);
8461
8441
  this._pinger.start();
8462
8442
  this._polarisReport = new PolarisReporter(this._context, this._runtime, this._roomId, this);
8463
8443
  this._polarisReport.sendR1();
@@ -8482,9 +8462,6 @@ class RCAbstractRoom {
8482
8462
  });
8483
8463
  }
8484
8464
  }
8485
- _handlePingResult(result) {
8486
- this._callAppListener('onPing', result);
8487
- }
8488
8465
  /**
8489
8466
  * 设置房间上行资源的总码率配置
8490
8467
  * @description
@@ -8576,7 +8553,7 @@ class RCAbstractRoom {
8576
8553
  const content = message.content;
8577
8554
  switch (message.messageType) {
8578
8555
  case RCRTCMessageType.KICK:
8579
- this._kickoff(true, content);
8556
+ this._kickoff(true);
8580
8557
  break;
8581
8558
  case RCRTCMessageType.STATE:
8582
8559
  this.msgTaskQueue.push(() => this._stateHandle(content));
@@ -8605,19 +8582,11 @@ class RCAbstractRoom {
8605
8582
  * * 当值为 false 时,说明本端 rtcPing 超时
8606
8583
  * * 当值为 true 时,说明本端收到被踢出房间通知
8607
8584
  */
8608
- _kickoff(byServer, content) {
8585
+ _kickoff(byServer) {
8609
8586
  logger.warn(`onKickOff -> byServer: ${byServer}`);
8610
8587
  this._ntfClearRoomItem();
8611
8588
  this._leaveHandle(!byServer);
8612
- let kickType;
8613
- if (byServer) {
8614
- ((content === null || content === void 0 ? void 0 : content.users) || []).forEach(item => {
8615
- if (item.userId === this._context.getCurrentId()) {
8616
- kickType = item.type;
8617
- }
8618
- });
8619
- }
8620
- this._callAppListener('onKickOff', byServer, kickType);
8589
+ this._callAppListener('onKickOff', byServer);
8621
8590
  }
8622
8591
  _rtcpeerClosed() {
8623
8592
  this._ntfClearRoomItem();
@@ -9198,14 +9167,13 @@ class RCAbstractRoom {
9198
9167
  extend: JSON.stringify({
9199
9168
  resolutionInfo: this._pc.getOutboundVideoInfo()
9200
9169
  }),
9201
- /**
9202
- * 需过滤房间内不存在的资源
9203
- */
9204
9170
  subscribeList: subscribeList.filter((item) => {
9205
- var _a;
9206
9171
  const trackId = item.track.getTrackId();
9207
- const { userId } = helper.parseTrackId(trackId);
9208
- const isInclude = (_a = this._roomResources[userId]) === null || _a === void 0 ? void 0 : _a.filter(item => trackId === `${item.msid}_${item.mediaType}`).length;
9172
+ const { userId } = parseTrackId(trackId);
9173
+ if (!this._roomResources[userId]) {
9174
+ return false;
9175
+ }
9176
+ const isInclude = this._roomResources[userId].filter(item => trackId === `${item.msid}_${item.mediaType}`).length;
9209
9177
  return isInclude;
9210
9178
  }).map(item => ({
9211
9179
  simulcast: item.subTiny ? RCStreamType.TINY : RCStreamType.NORMAL,
@@ -9506,7 +9474,7 @@ class RCAbstractRoom {
9506
9474
  if (result.code !== exports.RCRTCCode.SUCCESS) {
9507
9475
  return { code: result.code };
9508
9476
  }
9509
- const { sdp: answer, resultCode, message } = result.data;
9477
+ const { sdp: answer, resultCode, message, subscribedList } = result.data;
9510
9478
  if (resultCode !== exports.RCRTCCode.SUCCESS) {
9511
9479
  logger.error(`change subscribe list failed: ${resultCode}`);
9512
9480
  return { code: resultCode };
@@ -9516,14 +9484,18 @@ class RCAbstractRoom {
9516
9484
  if (resCode !== exports.RCRTCCode.SUCCESS) {
9517
9485
  return { code: resCode };
9518
9486
  }
9487
+ // 获取真正订阅成功的资源
9488
+ const subSuccessTrackIds = subscribedList === null || subscribedList === void 0 ? void 0 : subscribedList.map(item => `${item.msid}_${item.mediaType}`);
9489
+ const subSuccessList = attrs.filter(item => subSuccessTrackIds === null || subSuccessTrackIds === void 0 ? void 0 : subSuccessTrackIds.includes(item.track.getTrackId()));
9490
+ const failedList = attrs.filter(item => !(subSuccessTrackIds === null || subSuccessTrackIds === void 0 ? void 0 : subSuccessTrackIds.includes(item.track.getTrackId())));
9519
9491
  // 更新 remoteTrack.isSubscribed
9520
9492
  for (const trackId in this._remoteTracks) {
9521
- const subed = attrs.some(item => item.track.getTrackId() === trackId);
9493
+ const subed = subSuccessList.some(item => item.track.getTrackId() === trackId);
9522
9494
  this._remoteTracks[trackId].__innerSetSubscribed(subed);
9523
9495
  }
9524
9496
  // 更新本地订阅关系
9525
- this._subscribedList.splice(0, this._subscribedList.length, ...attrs);
9526
- return { code: exports.RCRTCCode.SUCCESS };
9497
+ this._subscribedList.splice(0, this._subscribedList.length, ...subSuccessList);
9498
+ return failedList.length ? { code: exports.RCRTCCode.SUCCESS, failedList } : { code: exports.RCRTCCode.SUCCESS };
9527
9499
  });
9528
9500
  }
9529
9501
  /**
@@ -9593,14 +9565,14 @@ class RCAbstractRoom {
9593
9565
  joinedUserIds.push(userId);
9594
9566
  // 新增人员发布的资源
9595
9567
  published[userId] = deepCopyResources(roomData[userId]);
9596
- continue;
9568
+ return;
9597
9569
  }
9598
9570
  // 房间缓存中的已发布资源
9599
9571
  const prevResources = this._roomResources[userId];
9600
9572
  // 当前资源
9601
9573
  const nowResources = roomData[userId];
9602
9574
  // 资源比对
9603
- const { publishedList, modifiedList, unpublishedList } = diffPublishResources(prevResources, nowResources, true);
9575
+ const { publishedList, modifiedList, unpublishedList } = diffPublishResources(prevResources, nowResources);
9604
9576
  published[userId] = deepCopyResources(publishedList);
9605
9577
  unpublished[userId] = deepCopyResources(unpublishedList);
9606
9578
  modified[userId] = deepCopyResources(modifiedList);
@@ -9652,6 +9624,7 @@ class RCAbstractRoom {
9652
9624
  rTrack.isAudioTrack() ? this._onAudioMuteChange(rTrack) : this._onVideoMuteChange(rTrack);
9653
9625
  });
9654
9626
  });
9627
+ return { data };
9655
9628
  });
9656
9629
  }
9657
9630
  _onAudioMuteChange(audioTrack) {
@@ -9663,27 +9636,7 @@ class RCAbstractRoom {
9663
9636
  /**
9664
9637
  * 观众切换为主播后直接处理人员变更及资源变更
9665
9638
  */
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
- }
9639
+ _afterChangedRole(data) { }
9687
9640
  /**
9688
9641
  * 主播身份降级,取消己端已发布的所有资源
9689
9642
  */
@@ -9769,9 +9722,14 @@ class RCMCUConfigBuilder {
9769
9722
  /**
9770
9723
  * trackId 有效性验证方法
9771
9724
  */
9772
- _isValidTrackId) {
9725
+ _isValidTrackId,
9726
+ /**
9727
+ * 扩散 cdn_uris
9728
+ */
9729
+ _sendCDNInfoSignal) {
9773
9730
  this._onFlush = _onFlush;
9774
9731
  this._isValidTrackId = _isValidTrackId;
9732
+ this._sendCDNInfoSignal = _sendCDNInfoSignal;
9775
9733
  /**
9776
9734
  * mcu 配置数据,每次向服务器提交全量数据
9777
9735
  */
@@ -10158,24 +10116,62 @@ class RCMCUConfigBuilder {
10158
10116
  * 使已修改的配置生效,在调用该方法前,所有数据只会对本地配置进行修改,不会产生实际效果
10159
10117
  */
10160
10118
  flush() {
10119
+ var _a, _b, _c, _d;
10161
10120
  return __awaiter(this, void 0, void 0, function* () {
10162
10121
  const config = JSON.parse(JSON.stringify(this._values));
10163
10122
  const { code } = yield this._onFlush(config);
10123
+ /**
10124
+ * 合流布局中包含分辨率设置时,需扩散 cdn_uris
10125
+ */
10126
+ 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))) {
10127
+ this._sendCDNInfoSignal();
10128
+ }
10164
10129
  this._values = createMCUConfig();
10165
10130
  return { code };
10166
10131
  });
10167
10132
  }
10168
10133
  }
10169
10134
 
10135
+ var RCInnerCDNModel;
10136
+ (function (RCInnerCDNModel) {
10137
+ // 开启
10138
+ RCInnerCDNModel[RCInnerCDNModel["OPEN"] = 1] = "OPEN";
10139
+ // 停用
10140
+ RCInnerCDNModel[RCInnerCDNModel["STOP"] = 2] = "STOP";
10141
+ })(RCInnerCDNModel || (RCInnerCDNModel = {}));
10142
+
10143
+ var RCInnerCDNBroadcast;
10144
+ (function (RCInnerCDNBroadcast) {
10145
+ // 扩散
10146
+ RCInnerCDNBroadcast[RCInnerCDNBroadcast["SPREAD"] = 0] = "SPREAD";
10147
+ RCInnerCDNBroadcast[RCInnerCDNBroadcast["NO_SPREAD"] = -1] = "NO_SPREAD";
10148
+ })(RCInnerCDNBroadcast || (RCInnerCDNBroadcast = {}));
10149
+
10150
+ var RCInnerCDNPushMode;
10151
+ (function (RCInnerCDNPushMode) {
10152
+ // 自动模式
10153
+ RCInnerCDNPushMode[RCInnerCDNPushMode["AUTOMATIC"] = 0] = "AUTOMATIC";
10154
+ // 手动模式
10155
+ RCInnerCDNPushMode[RCInnerCDNPushMode["MANUAL"] = 1] = "MANUAL";
10156
+ })(RCInnerCDNPushMode || (RCInnerCDNPushMode = {}));
10157
+
10170
10158
  /**
10171
10159
  * 直播房间
10172
10160
  */
10173
10161
  class RCLivingRoom extends RCAbstractRoom {
10174
10162
  constructor(context, runtime, roomId, data, service, initOptions, clientEvent, _livingType, isUpgrage = false) {
10163
+ var _a;
10175
10164
  super(context, runtime, roomId, data, engine.RTCMode.LIVE, service, initOptions, clientEvent, isUpgrage);
10176
10165
  this._livingType = _livingType;
10166
+ /**
10167
+ * cdn_uris 信令扩散数据
10168
+ */
10169
+ this._CDNUris = null;
10170
+ this._CDNEnable = false;
10177
10171
  // 初始化 MCUBuilder
10178
- this._mcuConfigBuilder = new RCMCUConfigBuilder(this._onMCUConfigFlush.bind(this), this._isValidResourceId.bind(this));
10172
+ this._mcuConfigBuilder = new RCMCUConfigBuilder(this._onMCUConfigFlush.bind(this), this._isValidResourceId.bind(this), this._sendCDNInfoSignal.bind(this));
10173
+ const CDNUris = (_a = data.roomInfo.filter((item) => { return item.key === 'cdn_uris'; })[0]) === null || _a === void 0 ? void 0 : _a.value;
10174
+ CDNUris && (this._CDNUris = JSON.parse(CDNUris)[0]);
10179
10175
  }
10180
10176
  getLivingType() {
10181
10177
  return this._livingType;
@@ -10199,16 +10195,214 @@ class RCLivingRoom extends RCAbstractRoom {
10199
10195
  UserId: this._context.getCurrentId(),
10200
10196
  SessionId: this.getSessionId()
10201
10197
  };
10202
- const { code } = yield this._service.setMcuConfig(headers, data);
10198
+ const { code, res } = yield this._service.setMcuConfig(headers, data);
10203
10199
  if (code !== exports.RCRTCCode.SUCCESS) {
10204
10200
  logger.error(`set MCU config failed: ${code}`);
10201
+ return { code };
10205
10202
  }
10206
- logger.debug('set MCU config success');
10207
- return { code };
10203
+ logger.info('set MCU config success');
10204
+ res.pull_url && (this._CDNUris = JSON.parse(res.pull_url));
10205
+ return { code, res };
10208
10206
  });
10209
10207
  }
10208
+ /**
10209
+ * 主播端断线重连后,需更新内存中的 CDN 数据
10210
+ * 判断房间内 CDN 状态是否和内存数据一致,不一致时需通知到客户端
10211
+ */
10210
10212
  __onReconnected() {
10211
- return super.__onReconnected(this._livingType);
10213
+ const _super = Object.create(null, {
10214
+ __onReconnected: { get: () => super.__onReconnected }
10215
+ });
10216
+ var _a, _b;
10217
+ return __awaiter(this, void 0, void 0, function* () {
10218
+ const res = yield _super.__onReconnected.call(this, this._livingType);
10219
+ if (!res || !res.data) {
10220
+ return;
10221
+ }
10222
+ const roomInfo = res.data.roomInfo;
10223
+ const CDNUris = (_a = roomInfo.filter((item) => { return item.key === 'cdn_uris'; })[0]) === null || _a === void 0 ? void 0 : _a.value;
10224
+ if (!CDNUris) {
10225
+ return;
10226
+ }
10227
+ const parseCDNUris = JSON.parse(CDNUris);
10228
+ if (((_b = this._CDNUris) === null || _b === void 0 ? void 0 : _b.enableInnerCDN) !== parseCDNUris.enableInnerCDN) {
10229
+ this._callAppListener('onCDNEnableChange', parseCDNUris.enableInnerCDN);
10230
+ }
10231
+ this._CDNUris = parseCDNUris;
10232
+ });
10233
+ }
10234
+ /**
10235
+ * 开启/停用推 CDN
10236
+ */
10237
+ enableInnerCDN(enable) {
10238
+ return __awaiter(this, void 0, void 0, function* () {
10239
+ if (!engine.isBoolean(enable)) {
10240
+ logger.error('`enable` is invalid');
10241
+ return { code: exports.RCRTCCode.PARAMS_ERROR };
10242
+ }
10243
+ this._CDNEnable = enable;
10244
+ const params = {
10245
+ version: 2,
10246
+ output: {
10247
+ inCDNModel: enable ? RCInnerCDNModel.OPEN : RCInnerCDNModel.STOP
10248
+ }
10249
+ };
10250
+ const { code } = yield this._onMCUConfigFlush(params);
10251
+ if (code !== exports.RCRTCCode.SUCCESS) {
10252
+ logger.error(`enableInnerCDN failed -> code: ${code}`);
10253
+ return { code: exports.RCRTCCode.SIGNAL_ERROR };
10254
+ }
10255
+ // 判断是否需要扩散 cdn_uris 时
10256
+ if (this._CDNUris && (this._CDNUris.broadcast !== RCInnerCDNBroadcast.SPREAD)) {
10257
+ logger.info('enableInnerCDN succeed');
10258
+ return { code: exports.RCRTCCode.SUCCESS };
10259
+ }
10260
+ /**
10261
+ * 扩散 cdn_uris
10262
+ */
10263
+ const { code: sendSingalCode } = yield push(() => __awaiter(this, void 0, void 0, function* () { return this._sendCDNInfoSignal(); }));
10264
+ if (sendSingalCode === exports.RCRTCCode.SUCCESS) {
10265
+ logger.info('enableInnerCDN succeed');
10266
+ return { code: exports.RCRTCCode.SUCCESS };
10267
+ }
10268
+ logger.error(`enableInnerCDN failed -> code: ${sendSingalCode}`);
10269
+ return { code: sendSingalCode };
10270
+ });
10271
+ }
10272
+ /**
10273
+ * 开启、停用 CDN 推资源后发信令
10274
+ */
10275
+ _sendCDNInfoSignal() {
10276
+ return __awaiter(this, void 0, void 0, function* () {
10277
+ this._CDNUris = Object.assign({}, this._CDNUris, { enableInnerCDN: this._CDNEnable });
10278
+ const resCodeArr = yield Promise.all([this._spreadCDNInfo(this._CDNUris), this._setRoomCDNInfo(this._CDNUris)]);
10279
+ const isSuccess = resCodeArr.every((item) => {
10280
+ return item.code === exports.RCRTCCode.SUCCESS;
10281
+ });
10282
+ return isSuccess ? { code: exports.RCRTCCode.SUCCESS } : { code: exports.RCRTCCode.SIGNAL_ERROR };
10283
+ });
10284
+ }
10285
+ /**
10286
+ * 扩散 cdn_uris 资源
10287
+ */
10288
+ _spreadCDNInfo(CDNUris) {
10289
+ return __awaiter(this, void 0, void 0, function* () {
10290
+ const code = yield this._context.setRTCCDNUris(this._roomId, RCRTCMessageType.TOTAL_CONTENT_RESOURCE, JSON.stringify([CDNUris]));
10291
+ if (code !== engine.ErrorCode.SUCCESS) {
10292
+ logger.error(`spreadCDNInfo failed -> code: ${code}`);
10293
+ return { code: exports.RCRTCCode.SIGNAL_ERROR };
10294
+ }
10295
+ logger.info('spreadCDNInfo succeed');
10296
+ return { code: exports.RCRTCCode.SUCCESS };
10297
+ });
10298
+ }
10299
+ /**
10300
+ * 给房间设置 CDN 数据
10301
+ */
10302
+ _setRoomCDNInfo(CDNUris) {
10303
+ return __awaiter(this, void 0, void 0, function* () {
10304
+ const code = yield this._context.setRTCData(this._roomId, 'cdn_uris', JSON.stringify([CDNUris]), true, engine.RTCApiType.ROOM);
10305
+ if (code !== engine.ErrorCode.SUCCESS) {
10306
+ logger.error(`setRoomCDNInfo failed -> code: ${code}`);
10307
+ return { code: exports.RCRTCCode.SIGNAL_ERROR };
10308
+ }
10309
+ logger.info('setRoomCDNInfo succeed');
10310
+ return { code: exports.RCRTCCode.SUCCESS };
10311
+ });
10312
+ }
10313
+ /**
10314
+ * 资源变化时触发
10315
+ * 直播房间需单独处理 cdn_uris
10316
+ */
10317
+ _resourceHandle(content, messageType, userId) {
10318
+ const _super = Object.create(null, {
10319
+ _resourceHandle: { get: () => super._resourceHandle }
10320
+ });
10321
+ var _a;
10322
+ return __awaiter(this, void 0, void 0, function* () {
10323
+ _super._resourceHandle.call(this, content, messageType, userId);
10324
+ if (!content.cdn_uris) {
10325
+ return;
10326
+ }
10327
+ // 给业务层抛 CDN 状态
10328
+ if (((_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.enableInnerCDN) !== content.cdn_uris[0].enableInnerCDN) {
10329
+ this._callAppListener('onCDNEnableChange', !this.__getCDNEnable());
10330
+ }
10331
+ // 更新 _CDNUris
10332
+ this._CDNUris = content.cdn_uris[0];
10333
+ });
10334
+ }
10335
+ /**
10336
+ * 重写父类 _exchangeHandle 方法
10337
+ */
10338
+ _exchangeHandle(body) {
10339
+ var _a, _b, _c;
10340
+ return __awaiter(this, void 0, void 0, function* () {
10341
+ const res = yield this._service.exchange(this._getRTCReqestHeaders(), body);
10342
+ const pullUrl = (_b = (_a = res.data) === null || _a === void 0 ? void 0 : _a.urls) === null || _b === void 0 ? void 0 : _b.pull_url;
10343
+ if (res.code !== exports.RCRTCCode.SUCCESS || !pullUrl) {
10344
+ return res;
10345
+ }
10346
+ /**
10347
+ * 自动模式下:
10348
+ * /exchange 完需根据 broadcast 字端判断是否扩散 cdn_uris 数据,设置房间 cdn_uris 数据
10349
+ */
10350
+ this._CDNUris = JSON.parse(pullUrl);
10351
+ if (((_c = this._CDNUris) === null || _c === void 0 ? void 0 : _c.broadcast) === RCInnerCDNBroadcast.SPREAD) {
10352
+ this._CDNEnable = true;
10353
+ this._sendCDNInfoSignal();
10354
+ }
10355
+ return res;
10356
+ });
10357
+ }
10358
+ /**
10359
+ * 观众切换为主播后直接处理人员变更及资源变更
10360
+ */
10361
+ _afterChangedRole(data) {
10362
+ const parseData = parseRoomData(data);
10363
+ const currentUserId = this._context.getCurrentId();
10364
+ const joinedAnchorList = Object.keys(parseData);
10365
+ // 观众升级主播成功后返回房间实例,才可注册房间事件,需异步抛出
10366
+ setTimeout(() => {
10367
+ var _a, _b, _c;
10368
+ // 通知业务层人员变更
10369
+ const needNoticeUserIds = joinedAnchorList.filter(id => {
10370
+ return id !== currentUserId;
10371
+ });
10372
+ needNoticeUserIds.length > 0 && this._callAppListener('onUserJoin', needNoticeUserIds);
10373
+ // 通知业务层资源变更
10374
+ for (const userId in parseData) {
10375
+ if (userId === currentUserId) {
10376
+ continue;
10377
+ }
10378
+ this._resourceHandle({
10379
+ uris: parseData[userId]
10380
+ }, RCRTCMessageType.TOTAL_CONTENT_RESOURCE, userId);
10381
+ }
10382
+ const CDNUris = (_a = data.roomInfo.filter((item) => { return item.key === 'cdn_uris'; })[0]) === null || _a === void 0 ? void 0 : _a.value;
10383
+ if (!CDNUris) {
10384
+ return;
10385
+ }
10386
+ if (((_b = this._CDNUris) === null || _b === void 0 ? void 0 : _b.push_mode) === RCInnerCDNPushMode.MANUAL) {
10387
+ this._callAppListener('onCDNEnableChange', (_c = this._CDNUris) === null || _c === void 0 ? void 0 : _c.enableInnerCDN);
10388
+ }
10389
+ });
10390
+ }
10391
+ /**
10392
+ * 返回 CDN 是否可用
10393
+ * @returns boolean
10394
+ */
10395
+ __getCDNEnable() {
10396
+ var _a;
10397
+ return (_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.enableInnerCDN;
10398
+ }
10399
+ /**
10400
+ * 返回 CDN 推送模式: 自动 or 手动
10401
+ * @returns boolean
10402
+ */
10403
+ __getCDNPushMode() {
10404
+ var _a;
10405
+ return (_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.push_mode;
10212
10406
  }
10213
10407
  }
10214
10408
 
@@ -10267,7 +10461,7 @@ const getCommonHeader = () => ({
10267
10461
  'Content-Type': 'application/json;charset=UTF-8',
10268
10462
  'Cache-Control': 'no-cache',
10269
10463
  ClientType: `web|${browserInfo.browser}|${browserInfo.version}`,
10270
- ClientVersion: "5.1.10-alpha.2",
10464
+ ClientVersion: "5.1.10-enterprise.1",
10271
10465
  'Client-Session-Id': getUUID(),
10272
10466
  'Request-Id': Date.now().toString()
10273
10467
  });
@@ -10435,7 +10629,25 @@ class RCMediaService {
10435
10629
  if (status === 200) {
10436
10630
  logger.debug(`request success -> Request-Id: ${commonHeader['Request-Id']}`);
10437
10631
  const data = JSON.parse(jsonStr);
10438
- return { code: data.resultCode };
10632
+ return { code: data.resultCode, res: data };
10633
+ }
10634
+ return { code: exports.RCRTCCode.REQUEST_FAILED };
10635
+ });
10636
+ }
10637
+ /**
10638
+ * 房间内观众获取 CDN 资源信息、拉流地址
10639
+ */
10640
+ getCDNResourceInfo(headers, url) {
10641
+ return __awaiter(this, void 0, void 0, function* () {
10642
+ const commonHeader = getCommonHeader();
10643
+ const { status, data: resStr } = yield this._runtime.httpReq({
10644
+ url,
10645
+ headers: Object.assign(Object.assign({}, commonHeader), headers),
10646
+ method: engine.HttpMethod.GET
10647
+ });
10648
+ if (status === 200) {
10649
+ const data = JSON.parse(resStr);
10650
+ return { code: data.resultCode, res: data };
10439
10651
  }
10440
10652
  logger.warn(`request failed -> Request-Id: ${commonHeader['Request-Id']}, status: ${status}, url: ${url}`);
10441
10653
  return { code: exports.RCRTCCode.REQUEST_FAILED };
@@ -10546,9 +10758,7 @@ class RCAudienceClient {
10546
10758
  var _a;
10547
10759
  return __awaiter(this, void 0, void 0, function* () {
10548
10760
  const tracks = [];
10549
- if (isIllegalConnection(this._context.getNaviInfo())) {
10550
- return { code: exports.RCRTCCode.PACKAGE_ENVIRONMENT_ERROR, tracks };
10551
- }
10761
+ if (isIllegalConnection(this._context.getNaviInfo())) ;
10552
10762
  // 客户端主动调用 api 发请求时,清除 ice 断线重连的定时器
10553
10763
  !this._fromRetry && ((_a = this._pc) === null || _a === void 0 ? void 0 : _a.clearReTryExchangeTimer());
10554
10764
  this._fromRetry = false;
@@ -10685,6 +10895,19 @@ class RCAudienceClient {
10685
10895
  }
10686
10896
  }
10687
10897
 
10898
+ exports.RCInnerCDNPullKind = void 0;
10899
+ (function (RCInnerCDNPullKind) {
10900
+ RCInnerCDNPullKind["RTMP"] = "rtmp";
10901
+ RCInnerCDNPullKind["FLV"] = "flv";
10902
+ RCInnerCDNPullKind["HLS"] = "hls";
10903
+ })(exports.RCInnerCDNPullKind || (exports.RCInnerCDNPullKind = {}));
10904
+
10905
+ exports.RCInnerCDNPullIsHttps = void 0;
10906
+ (function (RCInnerCDNPullIsHttps) {
10907
+ RCInnerCDNPullIsHttps[RCInnerCDNPullIsHttps["NOT_HTTPS"] = 0] = "NOT_HTTPS";
10908
+ RCInnerCDNPullIsHttps[RCInnerCDNPullIsHttps["HTTPS"] = 1] = "HTTPS";
10909
+ })(exports.RCInnerCDNPullIsHttps || (exports.RCInnerCDNPullIsHttps = {}));
10910
+
10688
10911
  const tinyConf = Object.assign(Object.assign({}, transResolution(exports.RCResolution.W176_H144)), { frameRate: transFrameRate(exports.RCFrameRate.FPS_15) });
10689
10912
  /**
10690
10913
  * 观众直播房间类
@@ -10693,12 +10916,12 @@ const tinyConf = Object.assign(Object.assign({}, transResolution(exports.RCResol
10693
10916
  * 2、观众订阅、取消订阅资源
10694
10917
  */
10695
10918
  class RCAudienceLivingRoom {
10696
- constructor(_context, _runtime, _initOptions, _roomId, _token, _livingType) {
10919
+ constructor(_context, _runtime, _initOptions, _roomId, _joinResData, _livingType) {
10697
10920
  this._context = _context;
10698
10921
  this._runtime = _runtime;
10699
10922
  this._initOptions = _initOptions;
10700
10923
  this._roomId = _roomId;
10701
- this._token = _token;
10924
+ this._joinResData = _joinResData;
10702
10925
  this._livingType = _livingType;
10703
10926
  this._roomAnchorList = [];
10704
10927
  this._roomRes = {};
@@ -10743,14 +10966,18 @@ class RCAudienceLivingRoom {
10743
10966
  * * key RC_ANCHOR_LIST value: 为主播 ID 集合
10744
10967
  * * key RC_RES_`userId` value: 为主播发布的资源
10745
10968
  * * key RC_RTC_SESSIONID value: sessionId
10969
+ * * key RC_CDN value: CDN 资源数据
10746
10970
  */
10747
10971
  singalDataChange(singalData, roomId) {
10972
+ var _a;
10748
10973
  if (roomId !== this._roomId) {
10749
10974
  logger.warn(`singalDataChange -> not the current room data: data roomId: ${roomId}, current roomId: ${this._roomId}`);
10750
10975
  return;
10751
10976
  }
10752
10977
  logger.debug('singalDataChange -> singalData:', JSON.stringify(singalData || {}));
10753
10978
  const allMcuUris = [];
10979
+ const CDNUrisStr = (_a = singalData.filter((item) => { return item.key === 'RC_CDN'; })[0]) === null || _a === void 0 ? void 0 : _a.value;
10980
+ CDNUrisStr && this._diffCDNUris(JSON.parse(JSON.parse(CDNUrisStr).cdn_uris)[0]);
10754
10981
  singalData.forEach(data => {
10755
10982
  const { key, value, timestamp, uid } = data;
10756
10983
  const isResKey = key.indexOf('RC_RES_') !== -1;
@@ -11104,7 +11331,7 @@ class RCAudienceLivingRoom {
11104
11331
  return {
11105
11332
  'App-Key': this._context.getAppkey(),
11106
11333
  RoomId: userId,
11107
- Token: this._token,
11334
+ Token: this._joinResData.token,
11108
11335
  RoomType: engine.RTCMode.LIVE,
11109
11336
  UserId: userId,
11110
11337
  'Session-Id': this._sessionId
@@ -11182,7 +11409,7 @@ class RCAudienceLivingRoom {
11182
11409
  if (result.code !== exports.RCRTCCode.SUCCESS) {
11183
11410
  return { code: result.code };
11184
11411
  }
11185
- const { sdp: answer, resultCode, message } = result.data;
11412
+ const { sdp: answer, resultCode, message, subscribedList } = result.data;
11186
11413
  if (resultCode !== exports.RCRTCCode.SUCCESS) {
11187
11414
  logger.error('change subscribe list failed:', message, resultCode);
11188
11415
  return { code: resultCode };
@@ -11201,16 +11428,145 @@ class RCAudienceLivingRoom {
11201
11428
  if (resCode !== exports.RCRTCCode.SUCCESS) {
11202
11429
  return { code: resCode };
11203
11430
  }
11431
+ // 获取真正订阅成功的资源
11432
+ const subSuccessTrackIds = subscribedList === null || subscribedList === void 0 ? void 0 : subscribedList.map(item => `${item.msid}_${item.mediaType}`);
11433
+ const subSuccessList = attrs.filter(item => {
11434
+ if (item.track.isMCUTrack()) {
11435
+ const serverTrackInfo = this._roomRes[item.track.getTrackId()];
11436
+ const sdpResourceId = `${serverTrackInfo.msid}_${serverTrackInfo.mediaType}`;
11437
+ return subSuccessTrackIds.includes(sdpResourceId);
11438
+ }
11439
+ return subSuccessTrackIds === null || subSuccessTrackIds === void 0 ? void 0 : subSuccessTrackIds.includes(item.track.getTrackId());
11440
+ });
11441
+ const afterReplaceTrackIds = subSuccessList === null || subSuccessList === void 0 ? void 0 : subSuccessList.map(item => `${item.track.getTrackId()}`);
11442
+ const failedList = attrs.filter(item => !(afterReplaceTrackIds === null || afterReplaceTrackIds === void 0 ? void 0 : afterReplaceTrackIds.includes(item.track.getTrackId())));
11204
11443
  // 更新 remoteTrack.isSubscribed
11205
11444
  for (const trackId in this._remoteTracks) {
11206
- const subed = attrs.some(item => {
11445
+ const subed = subSuccessList.some(item => {
11207
11446
  return item.track.getTrackId() === trackId;
11208
11447
  });
11209
11448
  this._remoteTracks[trackId].__innerSetSubscribed(subed);
11210
11449
  }
11211
11450
  // 更新本地订阅关系
11212
- this._subscribedList.splice(0, this._subscribedList.length, ...attrs);
11213
- return { code: exports.RCRTCCode.SUCCESS };
11451
+ this._subscribedList.splice(0, this._subscribedList.length, ...subSuccessList);
11452
+ return failedList.length ? { code: exports.RCRTCCode.SUCCESS, failedList } : { code: exports.RCRTCCode.SUCCESS };
11453
+ });
11454
+ }
11455
+ /**
11456
+ * 对比 cdn_uris 资源
11457
+ * @param newCDNUris 新的 cdn_uris 数据
11458
+ */
11459
+ _diffCDNUris(newCDNUris) {
11460
+ var _a, _b, _c, _d, _e, _f, _g, _h;
11461
+ return __awaiter(this, void 0, void 0, function* () {
11462
+ /**
11463
+ * CDN 资源减少: 上次 CDNUris 中有 url,变更后无 url
11464
+ */
11465
+ if (((_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.url) && !newCDNUris.url) {
11466
+ this._callAppListener('onCDNInfoDisable');
11467
+ /**
11468
+ * 更新内存中存储的 cdn_uris 数据
11469
+ */
11470
+ this._CDNUris = newCDNUris;
11471
+ return;
11472
+ }
11473
+ /**
11474
+ * CDN 资源新增条件:
11475
+ * 内存中无 CDNUris 或
11476
+ * 上次 CDNUris 无 url,变更后有 url
11477
+ */
11478
+ if (!this._CDNUris || (!((_b = this._CDNUris) === null || _b === void 0 ? void 0 : _b.url) && newCDNUris.url)) {
11479
+ this._callAppListener('onCDNInfoEnable', {
11480
+ resolution: `W${newCDNUris.w}_H${newCDNUris.h}`,
11481
+ fps: newCDNUris.fps
11482
+ });
11483
+ }
11484
+ /**
11485
+ * CDN 资源变更: w、h、fps 其中一项变化
11486
+ */
11487
+ 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));
11488
+ 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));
11489
+ 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));
11490
+ if (isWChange || isHChange || isFpsChange) {
11491
+ this._callAppListener('onCDNInfoChange', {
11492
+ resolution: `W${newCDNUris.w}_H${newCDNUris.h}`,
11493
+ fps: newCDNUris.fps
11494
+ });
11495
+ }
11496
+ /**
11497
+ * 更新内存中存储的 cdn_uris 数据
11498
+ */
11499
+ this._CDNUris = newCDNUris;
11500
+ });
11501
+ }
11502
+ /**
11503
+ * 获取 CDN 资源对应的拉流地址
11504
+ * 首次获取 CDNPlayUrl 时,需传入 url,
11505
+ * 业务层调用时使用内存中 _CDNUris 的 url,无 _CDNUris 时说明观众端未赋值过 _CDNUris
11506
+ * @returns CDNPlayUrl
11507
+ */
11508
+ _getCDNPlayUrl(params, url) {
11509
+ var _a, _b;
11510
+ return __awaiter(this, void 0, void 0, function* () {
11511
+ const { w, h, fps } = params;
11512
+ const kind = this._initOptions.pullInnerCDNProtocol || exports.RCInnerCDNPullKind.FLV;
11513
+ const useHttps = (this._initOptions.pullInnerCDNUseHttps === exports.RCInnerCDNPullIsHttps.NOT_HTTPS) ? exports.RCInnerCDNPullIsHttps.NOT_HTTPS : exports.RCInnerCDNPullIsHttps.HTTPS;
11514
+ /**
11515
+ * 加入房间后拉 KV 数据,数据还未返回时,同步拉 KV 获取 CDN 信息
11516
+ */
11517
+ if (!((_a = this._CDNUris) === null || _a === void 0 ? void 0 : _a.url) && !url) {
11518
+ logger.error(`cdn_uris url is empty, the anchor need to start CDN, code: ${exports.RCRTCCode.CDN_RESOURCE_IS_EMPTY}`);
11519
+ return { code: exports.RCRTCCode.CDN_RESOURCE_IS_EMPTY };
11520
+ }
11521
+ const headers = {
11522
+ 'App-Key': this._context.getAppkey(),
11523
+ Token: this._joinResData.token,
11524
+ RoomId: this.getRoomId(),
11525
+ UserId: this._context.getCurrentId(),
11526
+ SessionId: this.getSessionId()
11527
+ };
11528
+ const paramsArr = [];
11529
+ w && paramsArr.push(`w=${w}`);
11530
+ h && paramsArr.push(`h=${h}`);
11531
+ fps && paramsArr.push(`fps=${fps}`);
11532
+ paramsArr.push(`kind=${kind}`);
11533
+ paramsArr.push(`is_https=${useHttps}`);
11534
+ const paramsStr = paramsArr.join('&');
11535
+ let requestUrl = `${url || ((_b = this._CDNUris) === null || _b === void 0 ? void 0 : _b.url)}?`;
11536
+ paramsStr && (requestUrl += paramsStr);
11537
+ const { code, res } = yield this._service.getCDNResourceInfo(headers, requestUrl);
11538
+ if (code !== exports.RCRTCCode.SUCCESS) {
11539
+ logger.error(`getCDNPlayUrl failed: ${code}`);
11540
+ return { code };
11541
+ }
11542
+ logger.info(`getCDNPlayUrl success: ${res === null || res === void 0 ? void 0 : res.data.pull_url}`);
11543
+ return {
11544
+ code,
11545
+ CDNPlayUrl: res === null || res === void 0 ? void 0 : res.data.pull_url
11546
+ };
11547
+ });
11548
+ }
11549
+ /**
11550
+ * 获取 CDN 资源对应的拉流地址
11551
+ * @returns CDNPlayUrl
11552
+ */
11553
+ getCDNPlayUrl(resolution, fps) {
11554
+ return __awaiter(this, void 0, void 0, function* () {
11555
+ if (resolution && !isValidResolution(resolution)) {
11556
+ logger.error('`resolution` is invalid');
11557
+ return { code: exports.RCRTCCode.PARAMS_ERROR };
11558
+ }
11559
+ if (fps && !isValidFPS(fps)) {
11560
+ logger.error('`fps` is invalid');
11561
+ return { code: exports.RCRTCCode.PARAMS_ERROR };
11562
+ }
11563
+ const { width, height } = resolution ? transResolution(resolution) : { width: null, height: null };
11564
+ const fpsNum = fps ? transFrameRate(fps) : null;
11565
+ const params = {};
11566
+ width && (params.w = width);
11567
+ height && (params.h = height);
11568
+ fpsNum && (params.fps = fpsNum);
11569
+ return this._getCDNPlayUrl(params);
11214
11570
  });
11215
11571
  }
11216
11572
  /**
@@ -11270,6 +11626,8 @@ class RCAudienceLivingRoom {
11270
11626
  this._pc.destroy();
11271
11627
  // 销毁 polarisReport 实例
11272
11628
  this._polarisReport = null;
11629
+ // 清空 onrtcdatachange 事件监听
11630
+ this._context.onrtcdatachange = () => { };
11273
11631
  });
11274
11632
  }
11275
11633
  /**
@@ -11311,7 +11669,12 @@ class RCAudienceLivingRoom {
11311
11669
  * @param tag 参数描述
11312
11670
  */
11313
11671
  registerRoomEventListener(listener) {
11672
+ var _a;
11314
11673
  this._appListener = listener;
11674
+ if (!listener) {
11675
+ return;
11676
+ }
11677
+ ((_a = this._joinResData.kvEntries) === null || _a === void 0 ? void 0 : _a.length) && this.singalDataChange(this._joinResData.kvEntries, this._roomId);
11315
11678
  }
11316
11679
  /**
11317
11680
  * 音量上报
@@ -11444,14 +11807,12 @@ class RCRTCClient {
11444
11807
  * 加入普通音视频房间
11445
11808
  * @param roomId
11446
11809
  */
11447
- joinRTCRoom(roomId, joinType) {
11448
- return push(() => this._joinRTCRoom(roomId, joinType));
11810
+ joinRTCRoom(roomId) {
11811
+ return push(() => this._joinRTCRoom(roomId));
11449
11812
  }
11450
- _joinRTCRoom(roomId, joinType) {
11813
+ _joinRTCRoom(roomId) {
11451
11814
  return __awaiter(this, void 0, void 0, function* () {
11452
- if (isIllegalConnection(this._context.getNaviInfo())) {
11453
- return { code: exports.RCRTCCode.PACKAGE_ENVIRONMENT_ERROR };
11454
- }
11815
+ if (isIllegalConnection(this._context.getNaviInfo())) ;
11455
11816
  if (!engine.validate('roomId', roomId, engine.notEmptyString, true)) {
11456
11817
  return { code: exports.RCRTCCode.PARAMS_ERROR };
11457
11818
  }
@@ -11465,12 +11826,11 @@ class RCRTCClient {
11465
11826
  if (!urls.length) {
11466
11827
  return { code: exports.RCRTCCode.NOT_OPEN_VIDEO_AUDIO_SERVER };
11467
11828
  }
11468
- logger.debug(`joinRoom -> roomId: ${roomId}; joinType: ${joinType || engine.RTCJoinType.KICK}`);
11469
- const { code, data } = yield this._context.joinRTCRoom(roomId, engine.RTCMode.RTC, joinType);
11829
+ logger.debug(`joinRoom -> roomId: ${roomId}`);
11830
+ const { code, data } = yield this._context.joinRTCRoom(roomId, engine.RTCMode.RTC);
11470
11831
  if (code !== engine.ErrorCode.SUCCESS) {
11471
11832
  logger.error(`joinRoom failed -> code: ${code}`);
11472
- const errorCode = code === RTCSignalCode.JOIN_REFUSED ? exports.RCRTCCode.SIGNAL_JOIN_RTC_ROOM_REFUSED : code;
11473
- return { code: errorCode };
11833
+ return { code: code };
11474
11834
  }
11475
11835
  logger.debug(`joinRoom success -> userId: ${this._context.getCurrentId()}, roomId: ${roomId}, data: ${JSON.stringify(data)}`);
11476
11836
  const room = new RCRTCRoom(this._context, this._runtime, roomId, data, this._service, this._options, this._releaseCrtRoomObj.bind(this));
@@ -11488,9 +11848,7 @@ class RCRTCClient {
11488
11848
  }
11489
11849
  _joinLivingRoom(roomId, livingType) {
11490
11850
  return __awaiter(this, void 0, void 0, function* () {
11491
- if (isIllegalConnection(this._context.getNaviInfo())) {
11492
- return { code: exports.RCRTCCode.PACKAGE_ENVIRONMENT_ERROR };
11493
- }
11851
+ if (isIllegalConnection(this._context.getNaviInfo())) ;
11494
11852
  if (!(engine.validate('roomId', roomId, engine.notEmptyString, true) &&
11495
11853
  engine.validate('livingType', livingType, (value) => value === exports.RCLivingType.AUDIO || value === exports.RCLivingType.VIDEO))) {
11496
11854
  return { code: exports.RCRTCCode.PARAMS_ERROR };
@@ -11516,7 +11874,12 @@ class RCRTCClient {
11516
11874
  logger.debug(`JoinRoom success -> userId: ${this._context.getCurrentId()}, roomId: ${roomId}, data: ${JSON.stringify(data)}`);
11517
11875
  const room = new RCLivingRoom(this._context, this._runtime, roomId, data, this._service, this._options, this._releaseCrtRoomObj.bind(this), livingType, false);
11518
11876
  this._crtRoom = room;
11519
- return { room, code: exports.RCRTCCode.SUCCESS, userIds: room.getRemoteUserIds(), tracks: room.getRemoteTracks() };
11877
+ const joinLivingResData = { room, code: exports.RCRTCCode.SUCCESS, userIds: room.getRemoteUserIds(), tracks: room.getRemoteTracks() };
11878
+ // 手动模式时,用户加入房间,需返回 CDN 开关状态
11879
+ if (room.__getCDNPushMode() === RCInnerCDNPushMode.MANUAL) {
11880
+ Object.assign(joinLivingResData, { CDNEnable: room.__getCDNEnable() });
11881
+ }
11882
+ return joinLivingResData;
11520
11883
  });
11521
11884
  }
11522
11885
  /**
@@ -11867,9 +12230,7 @@ class RCRTCClient {
11867
12230
  */
11868
12231
  joinLivingRoomAsAudience(roomId, livingType) {
11869
12232
  return __awaiter(this, void 0, void 0, function* () {
11870
- if (isIllegalConnection(this._context.getNaviInfo())) {
11871
- return { code: exports.RCRTCCode.PACKAGE_ENVIRONMENT_ERROR };
11872
- }
12233
+ if (isIllegalConnection(this._context.getNaviInfo())) ;
11873
12234
  if (!(engine.validate('roomId', roomId, engine.notEmptyString, true) &&
11874
12235
  engine.validate('livingType', livingType, (value) => value === exports.RCLivingType.AUDIO || value === exports.RCLivingType.VIDEO))) {
11875
12236
  return { code: exports.RCRTCCode.PARAMS_ERROR };
@@ -11887,7 +12248,8 @@ class RCRTCClient {
11887
12248
  logger.error('audienceJoinLivingRoomError:', code);
11888
12249
  return { code: exports.RCRTCCode.SIGNAL_AUDIENCE_JOIN_ROOM_FAILED };
11889
12250
  }
11890
- const room = new RCAudienceLivingRoom(this._context, this._runtime, this._options, roomId, data.token, livingType);
12251
+ logger.info(`joinLivingRoomAsAudience success, room data: ${JSON.stringify(data)}`);
12252
+ const room = new RCAudienceLivingRoom(this._context, this._runtime, this._options, roomId, data, livingType);
11891
12253
  this._crtAudienceLivingRoom = room;
11892
12254
  return { room, code: exports.RCRTCCode.SUCCESS };
11893
12255
  });
@@ -11958,8 +12320,8 @@ class RCRTCClient {
11958
12320
  logger.error('change room identity error', code);
11959
12321
  return { code: exports.RCRTCCode.SIGNAL_ROOM_CHANGE_IDENTITY_FAILED };
11960
12322
  }
11961
- const { token } = data;
11962
- const crtRoom = new RCAudienceLivingRoom(this._context, this._runtime, this._options, room._roomId, token, room.getLivingType());
12323
+ logger.info(`downgradeToAudienceRoom success, room data: ${JSON.stringify(data)}`);
12324
+ const crtRoom = new RCAudienceLivingRoom(this._context, this._runtime, this._options, room._roomId, data, room.getLivingType());
11963
12325
  this._crtAudienceLivingRoom = crtRoom;
11964
12326
  // 主播房间内存数据清除及停止 Signal 房间心跳
11965
12327
  this._crtRoom.__destroy(false);
@@ -11968,38 +12330,8 @@ class RCRTCClient {
11968
12330
  return { room: crtRoom, code: exports.RCRTCCode.SUCCESS };
11969
12331
  });
11970
12332
  }
11971
- /**
11972
- * 获取在房间内用户信息
11973
- * 当前仅能查自己
11974
- * @since version 5.1.5
11975
- */
11976
- getJoinedUserInfo(userId) {
11977
- 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);
11982
- if (code !== engine.ErrorCode.SUCCESS) {
11983
- logger.error('getJoinedUserInfo error', code);
11984
- return { code: exports.RCRTCCode.SIGNAL_ROOM_CHANGE_IDENTITY_FAILED };
11985
- }
11986
- return { code: exports.RCRTCCode.SUCCESS, data };
11987
- });
11988
- }
11989
12333
  }
11990
12334
 
11991
- exports.RCKickReason = void 0;
11992
- (function (RCKickReason) {
11993
- /**
11994
- * Server 主动踢(掉 Server API 踢出)
11995
- */
11996
- RCKickReason[RCKickReason["SERVER_KICK"] = 1] = "SERVER_KICK";
11997
- /**
11998
- * 其他设备登陆后,本端被踢
11999
- */
12000
- RCKickReason[RCKickReason["OTHER_KICK"] = 2] = "OTHER_KICK";
12001
- })(exports.RCKickReason || (exports.RCKickReason = {}));
12002
-
12003
12335
  /**
12004
12336
  * 获取 Microphone 列表
12005
12337
  */
@@ -12047,7 +12379,7 @@ const installer = {
12047
12379
  setup(context, runtime, options = {}) {
12048
12380
  logger.setLogLevel(options.logLevel);
12049
12381
  logger.setLogStdout(options.logStdout);
12050
- logger.warn(`RCRTC Version: ${"5.1.10-alpha.2"}, Commit: ${"5c3523dd268a25fff2fcbb7d04f6acf3265411d6"}`);
12382
+ logger.warn(`RCRTC Version: ${"5.1.10-enterprise.1"}, Commit: ${"32f47afe02bd4b5db65ed78dd44330eb84e75059"}`);
12051
12383
  logger.warn(`browserInfo.browser -> ${browserInfo.browser}`);
12052
12384
  logger.warn(`browserInfo.supportsUnifiedPlan -> ${browserInfo.supportsUnifiedPlan}`);
12053
12385
  logger.warn(`browserInfo.version -> ${browserInfo.version}`);
@@ -12083,10 +12415,6 @@ const helper = {
12083
12415
  ifSupportScreenShare
12084
12416
  };
12085
12417
 
12086
- Object.defineProperty(exports, 'RTCJoinType', {
12087
- enumerable: true,
12088
- get: function () { return engine.RTCJoinType; }
12089
- });
12090
12418
  exports.RCAbstractRoom = RCAbstractRoom;
12091
12419
  exports.RCAudienceClient = RCAudienceClient;
12092
12420
  exports.RCAudienceLivingRoom = RCAudienceLivingRoom;