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