@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.d.ts +367 -95
- package/dist/index.esm.js +585 -127
- package/dist/index.js +583 -125
- package/dist/index.umd.js +583 -125
- package/package.json +3 -3
package/dist/index.esm.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* RCRTC - v5.
|
|
3
|
-
* CommitId -
|
|
4
|
-
*
|
|
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"] =
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
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(
|
|
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]
|
|
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 (
|
|
8854
|
+
if (allLeft.length) {
|
|
8764
8855
|
const tracks = [];
|
|
8765
8856
|
const userIds = [];
|
|
8766
|
-
|
|
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
|
-
|
|
8783
|
-
|
|
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 } =
|
|
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.
|
|
10204
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
//
|
|
10917
|
+
// 直播观众订阅的是合流后的数据,并不存在流的归属问题,此处直接以虚拟生成的合流 id 替代 userId
|
|
10581
10918
|
const mcuId = `rc_mcu_${Date.now()}`;
|
|
10582
10919
|
const tag = 'RongCloudRTC';
|
|
10583
|
-
this._subTracks.length
|
|
10584
|
-
|
|
10585
|
-
|
|
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,
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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: (
|
|
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
|
-
|
|
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
|
-
|
|
11959
|
-
const crtRoom = new RCAudienceLivingRoom(this._context, this._runtime, this._options, room._roomId,
|
|
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
|
-
|
|
12456
|
+
getJoinedRoomInfo() {
|
|
11974
12457
|
return __awaiter(this, void 0, void 0, function* () {
|
|
11975
|
-
|
|
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.
|
|
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 };
|