@rongcloud/plugin-rtc 5.4.6-alpha.1 → 5.4.7-alpha.2

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,13 +1,13 @@
1
1
  /*
2
- * RCRTC - v5.4.6-alpha.1
3
- * CommitId - d109ea1eb1987a80bf3299b86d39859d331d65b8
4
- * Fri Aug 19 2022 11:59:39 GMT+0800 (中国标准时间)
2
+ * RCRTC - v5.4.7-alpha.2
3
+ * CommitId - 1826738708cea2e2c6cc7586713f2c24ab40e665
4
+ * Wed Aug 31 2022 18:33:00 GMT+0800 (China Standard Time)
5
5
  * ©2020 RongCloud, Inc. All rights reserved.
6
6
  */
7
7
  import { Logger, EventEmitter, logger as logger$1, LogSource, isNumber, validate, ErrorCode, HttpMethod, ConnectionStatus, RTCMode, notEmptyString, isObject as isObject$1, isString, RTCJoinType, RTCApiType, isArray, assert, ConversationType, isHttpUrl, isBoolean, isUndefined, RTCIdentityChangeType, VersionManage } from '@rongcloud/engine';
8
8
  export { RTCJoinType } from '@rongcloud/engine';
9
9
 
10
- /******************************************************************************
10
+ /*! *****************************************************************************
11
11
  Copyright (c) Microsoft Corporation.
12
12
 
13
13
  Permission to use, copy, modify, and/or distribute this software for any
@@ -121,6 +121,8 @@ var RCRTCCode;
121
121
  RCRTCCode[RCRTCCode["MAC_IN_ELECTRON_NOT_SUPPORT_SCREEN_SHARE_WITH_AUDIO"] = 53032] = "MAC_IN_ELECTRON_NOT_SUPPORT_SCREEN_SHARE_WITH_AUDIO";
122
122
  /** 获取媒体资源时,无系统权限 */
123
123
  RCRTCCode[RCRTCCode["SYSTEM_PERMISSION_DENIED"] = 53033] = "SYSTEM_PERMISSION_DENIED";
124
+ /** 发布时无有效资源,如 track 已被销毁 */
125
+ RCRTCCode[RCRTCCode["PUBLISH_TRACKS_IS_INVALID"] = 53034] = "PUBLISH_TRACKS_IS_INVALID";
124
126
  })(RCRTCCode || (RCRTCCode = {}));
125
127
 
126
128
  var RCLoggerTag;
@@ -294,19 +296,19 @@ var RCLoggerTag;
294
296
  */
295
297
  RCLoggerTag["L_ABSTRACT_ROOM_DELETE_ROOM_ATTRIBUTE_R"] = "L-abstract_room_delete_room_attribute_R";
296
298
  /**
297
- * 房间推流的任务
299
+ * 房间发布资源的任务
298
300
  */
299
301
  RCLoggerTag["L_ABSTRACT_ROOM_PUBLISH_T"] = "L-abstract_room_publish-T";
300
302
  /**
301
- * 房间推流的结果
303
+ * 房间发布资源结果
302
304
  */
303
305
  RCLoggerTag["L_ABSTRACT_ROOM_PUBLISH_R"] = "L-abstract_room_publish-R";
304
306
  /**
305
- * 房间停止推流的任务
307
+ * 房间取消发布资源的任务
306
308
  */
307
309
  RCLoggerTag["L_ABSTRACT_ROOM_UNPUBLISH_T"] = "L-abstract_room_unpublish-T";
308
310
  /**
309
- * 房间停止推流结果
311
+ * 房间取消发布资源结果
310
312
  */
311
313
  RCLoggerTag["L_ABSTRACT_ROOM_UNPUBLISH_R"] = "L-abstract_room_unpublish-R";
312
314
  /**
@@ -6195,6 +6197,11 @@ var RCResolution;
6195
6197
  RCResolution["W720_H480"] = "W720_H480";
6196
6198
  RCResolution["W1280_H720"] = "W1280_H720";
6197
6199
  RCResolution["W1920_H1080"] = "W1920_H1080";
6200
+ RCResolution["W180_H180"] = "W180_H180";
6201
+ RCResolution["W240_H180"] = "W240_H180";
6202
+ RCResolution["W360_H360"] = "W360_H360";
6203
+ RCResolution["W848_H480"] = "W848_H480";
6204
+ RCResolution["W960_H720"] = "W960_H720";
6198
6205
  })(RCResolution || (RCResolution = {}));
6199
6206
 
6200
6207
  /**
@@ -6219,25 +6226,46 @@ var RCMediaType;
6219
6226
  // export const RongRTCVideoBitrate: { [key: RCResolution]: BitrateConf } = {
6220
6227
  const RongRTCVideoBitrate = {
6221
6228
  [RCResolution.W176_H132]: { width: 176, height: 132, maxBitrate: 150, minBitrate: 80 },
6222
- [RCResolution.W176_H144]: { width: 176, height: 144, maxBitrate: 160, minBitrate: 80 },
6229
+ [RCResolution.W176_H144]: { width: 176, height: 144, maxBitrate: 150, minBitrate: 80 },
6230
+ [RCResolution.W180_H180]: { width: 180, height: 180, maxBitrate: 200, minBitrate: 100 },
6231
+ [RCResolution.W240_H180]: { width: 240, height: 180, maxBitrate: 240, minBitrate: 120 },
6232
+ [RCResolution.W240_H240]: { width: 240, height: 240, maxBitrate: 280, minBitrate: 120 },
6223
6233
  [RCResolution.W256_H144]: { width: 256, height: 144, maxBitrate: 240, minBitrate: 120 },
6224
6234
  [RCResolution.W320_H180]: { width: 320, height: 180, maxBitrate: 280, minBitrate: 120 },
6225
- [RCResolution.W240_H240]: { width: 240, height: 240, maxBitrate: 280, minBitrate: 120 },
6226
6235
  [RCResolution.W320_H240]: { width: 320, height: 240, maxBitrate: 400, minBitrate: 120 },
6236
+ [RCResolution.W360_H360]: { width: 360, height: 360, maxBitrate: 520, minBitrate: 140 },
6227
6237
  [RCResolution.W480_H360]: { width: 480, height: 360, maxBitrate: 650, minBitrate: 150 },
6228
- [RCResolution.W640_H360]: { width: 640, height: 360, maxBitrate: 800, minBitrate: 180 },
6229
6238
  [RCResolution.W480_H480]: { width: 480, height: 480, maxBitrate: 800, minBitrate: 180 },
6239
+ [RCResolution.W640_H360]: { width: 640, height: 360, maxBitrate: 800, minBitrate: 180 },
6230
6240
  [RCResolution.W640_H480]: { width: 640, height: 480, maxBitrate: 900, minBitrate: 200 },
6231
6241
  [RCResolution.W720_H480]: { width: 720, height: 480, maxBitrate: 1000, minBitrate: 200 },
6242
+ [RCResolution.W848_H480]: { width: 848, height: 480, maxBitrate: 1860, minBitrate: 200 },
6243
+ [RCResolution.W960_H720]: { width: 960, height: 720, maxBitrate: 2000, minBitrate: 250 },
6232
6244
  [RCResolution.W1280_H720]: { width: 1280, height: 720, maxBitrate: 2200, minBitrate: 250 },
6233
6245
  [RCResolution.W1920_H1080]: { width: 1920, height: 1080, maxBitrate: 4000, minBitrate: 400 }
6234
6246
  };
6247
+ /**
6248
+ * 分辨率适配
6249
+ * @param {number} resolution
6250
+ * @returns
6251
+ */
6252
+ const resolutionAdapter = (resolution) => {
6253
+ const ResolutionAdapter = {
6254
+ 192: 180,
6255
+ 368: 360,
6256
+ 1088: 1080
6257
+ };
6258
+ return ResolutionAdapter[resolution] ? ResolutionAdapter[resolution] : resolution;
6259
+ };
6235
6260
  /**
6236
6261
  * 向上取最接近的视频分辨率配置
6237
6262
  * @param {number} width
6238
6263
  * @param {number} height
6239
6264
  */
6240
6265
  const getNearestResolution = (width, height) => {
6266
+ // 分辨率适配
6267
+ width = resolutionAdapter(width);
6268
+ height = resolutionAdapter(height);
6241
6269
  // 优先精准匹配
6242
6270
  const conf = RongRTCVideoBitrate[`W${width}_H${height}`];
6243
6271
  if (conf) {
@@ -6403,7 +6431,7 @@ class RCTrack extends EventEmitter {
6403
6431
  }, {
6404
6432
  logSource: LogSource.RTC
6405
6433
  });
6406
- this._setLocalMuted(true);
6434
+ return this._setLocalMuted(true);
6407
6435
  }
6408
6436
  /**
6409
6437
  * 启用
@@ -6416,7 +6444,7 @@ class RCTrack extends EventEmitter {
6416
6444
  }, {
6417
6445
  logSource: LogSource.RTC
6418
6446
  });
6419
- this._setLocalMuted(false);
6447
+ return this._setLocalMuted(false);
6420
6448
  }
6421
6449
  /**
6422
6450
  * 本端是否已禁用该轨道数据
@@ -6611,7 +6639,10 @@ class RCTrack extends EventEmitter {
6611
6639
  logSource: LogSource.RTC
6612
6640
  });
6613
6641
  try {
6614
- (_c = this._element) === null || _c === void 0 ? void 0 : _c.play();
6642
+ yield ((_c = this._element) === null || _c === void 0 ? void 0 : _c.play());
6643
+ if ((options === null || options === void 0 ? void 0 : options.audioDeviceId) && !isVideoTrack) {
6644
+ yield this._element.setSinkId(options.audioDeviceId);
6645
+ }
6615
6646
  }
6616
6647
  catch (error) {
6617
6648
  /**
@@ -6658,9 +6689,9 @@ class RCTrack extends EventEmitter {
6658
6689
  this._element.x5PlaysInline = true;
6659
6690
  this._element.webkitPlaysInline = true;
6660
6691
  }
6661
- if ((options === null || options === void 0 ? void 0 : options.audioDeviceId) && !isVideoTrack) {
6662
- yield this._element.setSinkId(options.audioDeviceId);
6663
- }
6692
+ // if (options?.audioDeviceId && !isVideoTrack) {
6693
+ // await (this._element as any).setSinkId(options.audioDeviceId)
6694
+ // }
6664
6695
  // audio 标签设置音量
6665
6696
  if (!isVideoTrack && ((options === null || options === void 0 ? void 0 : options.volume) || (options === null || options === void 0 ? void 0 : options.volume) === 0)) {
6666
6697
  this._element.volume = (options === null || options === void 0 ? void 0 : options.volume) / 100;
@@ -6713,9 +6744,9 @@ var RCAudioBitrate;
6713
6744
  RCAudioBitrate["MusicHigh"] = "MusicHigh";
6714
6745
  })(RCAudioBitrate || (RCAudioBitrate = {}));
6715
6746
  const getAudioBitrate = {
6716
- [RCAudioBitrate.Music]: { max: 64000, min: 64000 },
6717
- [RCAudioBitrate.MusicHigh]: { max: 128000, min: 128000 },
6718
- [RCAudioBitrate.Speech]: { max: 32000, min: 32000 }
6747
+ [RCAudioBitrate.Music]: { max: 32 * 2, min: 32 * 2 },
6748
+ [RCAudioBitrate.MusicHigh]: { max: 32 * 2 * 2, min: 32 * 2 * 2 },
6749
+ [RCAudioBitrate.Speech]: { max: 32, min: 32 }
6719
6750
  };
6720
6751
  var RCVideoBitrate;
6721
6752
  (function (RCVideoBitrate) {
@@ -6879,6 +6910,10 @@ RC3AnoiseTrack.isOpen = false;
6879
6910
  class RCLocalTrack extends RCTrack {
6880
6911
  constructor(tag, userId, kind, track) {
6881
6912
  super(tag, userId, kind, true);
6913
+ /**
6914
+ * track 是否被销毁
6915
+ */
6916
+ this._isDestroyed = false;
6882
6917
  this._isPublished = false;
6883
6918
  this.__innerSetMediaStreamTrack(track);
6884
6919
  // 监听流结束事件
@@ -6893,17 +6928,22 @@ class RCLocalTrack extends RCTrack {
6893
6928
  * @param bool
6894
6929
  */
6895
6930
  _setLocalMuted(bool) {
6896
- const changed = this._localMuted !== bool;
6897
- super._setLocalMuted(bool);
6898
- // 本端流,remoteMuted 与 localMuted 始终保持一致
6899
- this._remoteMuted = this._localMuted;
6900
- // 派发事件以通知房间内其他成员
6901
- changed && this.emit(RCLocalTrack.__INNER_EVENT_MUTED_CHANGE__, this);
6902
- logger$1.info(RCLoggerTag.L_LOCAL_TRACK_SET_LOCAL_MUTED_O, {
6903
- status: RCLoggerStatus.SUCCESSED,
6904
- bool
6905
- }, {
6906
- logSource: LogSource.RTC
6931
+ return new Promise((resolve, reject) => {
6932
+ const changed = this._localMuted !== bool;
6933
+ super._setLocalMuted(bool);
6934
+ // 本端流,remoteMuted 与 localMuted 始终保持一致
6935
+ this._remoteMuted = this._localMuted;
6936
+ /**
6937
+ * 派发事件以通知房间内其他成员
6938
+ * 本端禁用资源时需等待 signal 的扩散结果
6939
+ */
6940
+ changed && this.emit(RCLocalTrack.__INNER_EVENT_MUTED_CHANGE__, this, resolve);
6941
+ logger$1.info(RCLoggerTag.L_LOCAL_TRACK_SET_LOCAL_MUTED_O, {
6942
+ status: RCLoggerStatus.SUCCESSED,
6943
+ bool
6944
+ }, {
6945
+ logSource: LogSource.RTC
6946
+ });
6907
6947
  });
6908
6948
  }
6909
6949
  __innerSetPublished(bool) {
@@ -6927,6 +6967,7 @@ class RCLocalTrack extends RCTrack {
6927
6967
  destroy() {
6928
6968
  var _a;
6929
6969
  logger.info(`track is destroyed -> trackId: ${this.getTrackId()}`);
6970
+ this._isDestroyed = true;
6930
6971
  (_a = this._msTrack) === null || _a === void 0 ? void 0 : _a.stop();
6931
6972
  super.__innerDestroy();
6932
6973
  this.isAudioTrack() && super.__releaseMediaElement();
@@ -6938,6 +6979,12 @@ class RCLocalTrack extends RCTrack {
6938
6979
  logSource: LogSource.RTC
6939
6980
  });
6940
6981
  }
6982
+ /**
6983
+ * 判断 track 是否被销毁
6984
+ */
6985
+ isDestroyed() {
6986
+ return this._isDestroyed;
6987
+ }
6941
6988
  /**
6942
6989
  * 为本地流设定上行码率,仅视频流有效,音频默认 15 kbps,不支持修改
6943
6990
  * @description 当 `max` 或 `min` 值为 `0` 时,取动态码率计算结果
@@ -6981,7 +7028,7 @@ class RCLocalTrack extends RCTrack {
6981
7028
  }
6982
7029
  else if (((_b = this._msTrack) === null || _b === void 0 ? void 0 : _b.kind) === RCTrackKind.AUDIO) {
6983
7030
  // 音频动态码率
6984
- ({ min, max } = { min: 32000, max: 32000 });
7031
+ ({ min, max } = { min: 32, max: 32 });
6985
7032
  }
6986
7033
  if ((_c = this._bitrateInfo) === null || _c === void 0 ? void 0 : _c.max) {
6987
7034
  start = ((_d = this._bitrateInfo) === null || _d === void 0 ? void 0 : _d.max) * 0.7;
@@ -7153,10 +7200,15 @@ class RCLocalFileAudioTrack extends RCLocalFileTrack {
7153
7200
  this._stopProcess = () => { };
7154
7201
  }
7155
7202
  _setLocalMuted(bool) {
7156
- if (this._resource) {
7157
- this._resource.muted = bool;
7158
- }
7159
- super._setLocalMuted(bool);
7203
+ const _super = Object.create(null, {
7204
+ _setLocalMuted: { get: () => super._setLocalMuted }
7205
+ });
7206
+ return __awaiter(this, void 0, void 0, function* () {
7207
+ if (this._resource) {
7208
+ this._resource.muted = bool;
7209
+ }
7210
+ return _super._setLocalMuted.call(this, bool);
7211
+ });
7160
7212
  }
7161
7213
  play() {
7162
7214
  // 自定义文件中的声音播放只需要修改 video 标签的 muted 属性
@@ -7422,6 +7474,11 @@ const getUUID22 = () => {
7422
7474
  * @returns
7423
7475
  */
7424
7476
  const transResolution = (resolution) => {
7477
+ if (RongRTCVideoBitrate[resolution]) {
7478
+ const { width, height } = RongRTCVideoBitrate[resolution];
7479
+ return { width, height };
7480
+ }
7481
+ // 保留原有逻辑,防止客户有自定义传值解析异常
7425
7482
  const [width, height] = resolution.split('_').map(item => {
7426
7483
  return parseInt(item.replace(/[^\d]/g, ''));
7427
7484
  });
@@ -7878,7 +7935,7 @@ const getCommonHeader = () => ({
7878
7935
  'Content-Type': 'application/json;charset=UTF-8',
7879
7936
  'Cache-Control': 'no-cache',
7880
7937
  ClientType: `web|${browserInfo.browser}|${browserInfo.version}`,
7881
- ClientVersion: "5.4.6-alpha.1",
7938
+ ClientVersion: "5.4.7-alpha.2",
7882
7939
  'Client-Session-Id': getUUID(),
7883
7940
  'Request-Id': Date.now().toString()
7884
7941
  });
@@ -9282,7 +9339,7 @@ class ASdpBuilder {
9282
9339
  if (!/\bmaxaveragebitrate\b/ig.test(sdpAudioBlock)) {
9283
9340
  const audioBitrate = [
9284
9341
  '$1',
9285
- `maxaveragebitrate=${bitrate.max * 1024}`
9342
+ `maxaveragebitrate=${bitrate.max * ASdpBuilder.KBitrate}`
9286
9343
  ];
9287
9344
  sdpAudioBlock = sdpAudioBlock.replace(/(\buseinbandfec=[^\r\n]+)/ig, audioBitrate.join(';'));
9288
9345
  }
@@ -9296,7 +9353,7 @@ class ASdpBuilder {
9296
9353
  */
9297
9354
  addAudioBlineAS(sdpAudioBlock, bitrate) {
9298
9355
  if (!/\bb=AS:\d+\b/ig.test(sdpAudioBlock)) {
9299
- return sdpAudioBlock.replace(/^(m=audio[^\r\n]+)/, `$1\r\nb=AS:${bitrate.max * 1024}`);
9356
+ return sdpAudioBlock.replace(/^(m=audio[^\r\n]+)/, `$1\r\nb=AS:${bitrate.max * ASdpBuilder.KBitrate}`);
9300
9357
  }
9301
9358
  return sdpAudioBlock;
9302
9359
  }
@@ -9376,11 +9433,12 @@ class ASdpBuilder {
9376
9433
  if (!/\bx-google-max-bitrate\b/.test(sdpVideoBlock)) {
9377
9434
  const videoBitrate = [
9378
9435
  '$1',
9379
- `x-google-max-bitrate=${bitrate.max * 1024}`,
9380
- `x-google-min-bitrate=${bitrate.min * 1024}`,
9381
- `x-google-start-bitrate=${bitrate.start || bitrate.max * 1024 * 0.7}`
9436
+ `x-google-max-bitrate=${bitrate.max * ASdpBuilder.KBitrate}`,
9437
+ `x-google-min-bitrate=${bitrate.min * ASdpBuilder.KBitrate}`,
9438
+ `x-google-start-bitrate=${bitrate.start || bitrate.max * ASdpBuilder.KBitrate * 0.7}`
9382
9439
  ];
9383
- sdpVideoBlock = sdpVideoBlock.replace(/(\bprofile-level-id=[^\r\n]+)/ig, videoBitrate.join(';'));
9440
+ // 42e01f 42001f 为 H264 编码
9441
+ sdpVideoBlock = sdpVideoBlock.replace(/(\bprofile-level-id=42[e0]01f\b)/ig, videoBitrate.join(';'));
9384
9442
  }
9385
9443
  return this.addVideoBlineAS(sdpVideoBlock, bitrate);
9386
9444
  }
@@ -9393,7 +9451,7 @@ class ASdpBuilder {
9393
9451
  addVideoBlineAS(sdpVideoBlock, bitrate) {
9394
9452
  // b=AS: 定义本端带宽信息
9395
9453
  if (!/\bb=AS:\d+\b/ig.test(sdpVideoBlock)) {
9396
- return sdpVideoBlock.replace(/^(m=video[^\r\n]+)/, `$1\r\nb=AS:${bitrate.max * 1024}`);
9454
+ return sdpVideoBlock.replace(/^(m=video[^\r\n]+)/, `$1\r\nb=AS:${bitrate.max * ASdpBuilder.KBitrate}`);
9397
9455
  }
9398
9456
  return sdpVideoBlock;
9399
9457
  }
@@ -9443,6 +9501,7 @@ class ASdpBuilder {
9443
9501
  return stream;
9444
9502
  }
9445
9503
  }
9504
+ ASdpBuilder.KBitrate = 1;
9446
9505
 
9447
9506
  var SdpSemantics;
9448
9507
  (function (SdpSemantics) {
@@ -9757,6 +9816,113 @@ class UnifiedPlanSdpBuilder extends ASdpBuilder {
9757
9816
  }
9758
9817
  }
9759
9818
 
9819
+ /* 它是一堆解析 SDP 字符串的静态函数 */
9820
+ class SDPUtils {
9821
+ /* 将 SDP 拆分为多个部分。 */
9822
+ static splitSections(blob) {
9823
+ const parts = blob.split('\nm=');
9824
+ return parts.map((part, index) => (index > 0 ? 'm=' + part : part).trim() + '\r\n');
9825
+ }
9826
+ /**
9827
+ * 它需要一个 SDP 文本块并返回一个仅包含媒体部分的 SDP 文本数组
9828
+ * @param {string} blob - 您要解析的 SDP 字符串。
9829
+ * @returns 字符串数组。
9830
+ */
9831
+ static getMediaSections(blob) {
9832
+ const sections = SDPUtils.splitSections(blob);
9833
+ sections.shift();
9834
+ return sections;
9835
+ }
9836
+ /* 解析 extmap 属性的 SDP 标头。 */
9837
+ static parseExtmap(line) {
9838
+ const parts = line.substr(9).split(' ');
9839
+ return {
9840
+ id: parseInt(parts[0], 10),
9841
+ direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv',
9842
+ uri: parts[1]
9843
+ };
9844
+ }
9845
+ /* 将 SDP 字符串拆分为字符串数组。 */
9846
+ static splitLines(blob) {
9847
+ return blob.trim().split('\n').map(line => line.trim());
9848
+ }
9849
+ /**
9850
+ * 它接受一个媒体部分并返回一个对象,其中包含媒体部分的种类、端口、协议和格式
9851
+ * @param {string} mediaSection - SDP的媒体部分。
9852
+ * @returns 具有以下属性的对象:
9853
+ * kind:媒体的类型(音频、视频等)
9854
+ * 端口:端口号
9855
+ * 协议:使用的协议
9856
+ * fmt:媒体的格式
9857
+ */
9858
+ static parseMLine(mediaSection) {
9859
+ const lines = SDPUtils.splitLines(mediaSection);
9860
+ const parts = lines[0].substr(2).split(' ');
9861
+ return {
9862
+ kind: parts[0],
9863
+ port: parseInt(parts[1], 10),
9864
+ protocol: parts[2],
9865
+ fmt: parts.slice(3).join(' ')
9866
+ };
9867
+ }
9868
+ static matchPrefix(blob, prefix) {
9869
+ return SDPUtils.splitLines(blob).filter(line => line.indexOf(prefix) === 0);
9870
+ }
9871
+ /**
9872
+ * 它从 SDP 媒体部分解析 msid 属性
9873
+ * @param {string} mediaSection - SDP的媒体部分。
9874
+ * @returns 具有两个属性的对象:流和轨道。
9875
+ */
9876
+ static parseMsid(mediaSection) {
9877
+ let parts;
9878
+ const spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:');
9879
+ if (spec.length === 1) {
9880
+ parts = spec[0].substr(7).split(' ');
9881
+ return { stream: parts[0], track: parts[1] };
9882
+ }
9883
+ const planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
9884
+ .map(line => SDPUtils.parseSsrcMedia(line))
9885
+ .filter(msidParts => msidParts.attribute === 'msid');
9886
+ if (planB.length > 0) {
9887
+ if (planB[0].value) {
9888
+ parts = planB[0].value.split(' ');
9889
+ return { stream: parts[0], track: parts[1] };
9890
+ }
9891
+ }
9892
+ return { stream: '', track: '' };
9893
+ }
9894
+ /**
9895
+ * 它接受一个字符串并返回一个对象
9896
+ * @param {string} line - 我们正在解析的 SDP 行。
9897
+ */
9898
+ static parseSsrcMedia(line) {
9899
+ const sp = line.indexOf(' ');
9900
+ const parts = {
9901
+ ssrc: parseInt(line.substr(7, sp - 7), 10)
9902
+ };
9903
+ const colon = line.indexOf(':', sp);
9904
+ if (colon > -1) {
9905
+ parts.attribute = line.substr(sp + 1, colon - sp - 1);
9906
+ parts.value = line.substr(colon + 1);
9907
+ }
9908
+ else {
9909
+ parts.attribute = line.substr(sp + 1);
9910
+ }
9911
+ return parts;
9912
+ }
9913
+ /**
9914
+ * 它从 SDP 的媒体部分返回中间值
9915
+ * @param {string} mediaSection - SDP的媒体部分。
9916
+ * @returns 媒体部分的中间。
9917
+ */
9918
+ static getMid(mediaSection) {
9919
+ const mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0];
9920
+ if (mid) {
9921
+ return mid.substr(6);
9922
+ }
9923
+ }
9924
+ }
9925
+
9760
9926
  class UnifiedPlanStrategy extends ASdpStrategy {
9761
9927
  constructor() {
9762
9928
  super(...arguments);
@@ -9925,12 +10091,36 @@ class UnifiedPlanStrategy extends ASdpStrategy {
9925
10091
  const sdpBuilder = new UnifiedPlanSdpBuilder(sdp);
9926
10092
  for (const msid in this._sendTransceiver) {
9927
10093
  const transceiver = this._sendTransceiver[msid];
9928
- const { direction, mid } = transceiver;
10094
+ const kind = (_a = transceiver.sender.track) === null || _a === void 0 ? void 0 : _a.kind;
10095
+ let { direction, mid } = transceiver;
10096
+ if (!mid) {
10097
+ const sections = SDPUtils.getMediaSections(sdp);
10098
+ sections.forEach(item => {
10099
+ SDPUtils.parseExtmap(item);
10100
+ const { kind: parseKind } = SDPUtils.parseMLine(item);
10101
+ let { stream } = SDPUtils.parseMsid(item);
10102
+ const parseMid = SDPUtils.getMid(item);
10103
+ if (kind === 'video') {
10104
+ if (/tiny$/.test(stream)) {
10105
+ stream = stream.replace(/tiny$/ig, '1_tiny');
10106
+ }
10107
+ else {
10108
+ stream = stream + '_1';
10109
+ }
10110
+ }
10111
+ else {
10112
+ stream = stream + '_0';
10113
+ }
10114
+ // getMid
10115
+ if (stream === msid && kind === parseKind && parseMid) {
10116
+ mid = parseMid;
10117
+ }
10118
+ });
10119
+ }
9929
10120
  if (mid) {
9930
10121
  if (direction === RtpTransceiverDirection.SENDONLY) {
9931
10122
  const localTrack = this._localTracks[msid];
9932
10123
  const bitrate = localTrack === null || localTrack === void 0 ? void 0 : localTrack.getBitrate();
9933
- const kind = (_a = transceiver.sender.track) === null || _a === void 0 ? void 0 : _a.kind;
9934
10124
  if (kind === RCTrackKind.AUDIO && bitrate) {
9935
10125
  sdpBuilder.setAudioBitrateWithMid(bitrate, mid);
9936
10126
  }
@@ -9947,10 +10137,10 @@ class UnifiedPlanStrategy extends ASdpStrategy {
9947
10137
  const transceiver = this._recvTransceiver[msid];
9948
10138
  const { direction, mid } = transceiver;
9949
10139
  if (mid) {
9950
- if (direction === RtpTransceiverDirection.RECVONLY) {
10140
+ if (direction === RtpTransceiverDirection.RECVONLY) ;
10141
+ if (direction === RtpTransceiverDirection.INACTIVE) {
9951
10142
  sdpBuilder.clearnSsrcWithMid(mid, RtpTransceiverDirection.RECVONLY);
9952
10143
  }
9953
- if (direction === RtpTransceiverDirection.INACTIVE) ;
9954
10144
  }
9955
10145
  }
9956
10146
  return sdpBuilder.stringify();
@@ -9958,35 +10148,38 @@ class UnifiedPlanStrategy extends ASdpStrategy {
9958
10148
  // Answer SDP 中添加码率信息
9959
10149
  resetAnswerSdp(sdp) {
9960
10150
  var _a;
10151
+ // return sdp
9961
10152
  const sdpBuilder = new UnifiedPlanSdpBuilder(sdp);
9962
10153
  for (const msid in this._sendTransceiver) {
10154
+ /**
10155
+ * 通过 Sender 获取发布出去的资源
10156
+ * 对于已经发布出去的资源设置码率
10157
+ */
9963
10158
  const transceiver = this._sendTransceiver[msid];
9964
- const { direction, mid } = transceiver;
10159
+ const { mid } = transceiver;
9965
10160
  if (mid) {
9966
- if (direction === RtpTransceiverDirection.SENDONLY) {
9967
- const localTrack = this._localTracks[msid];
9968
- const bitrate = localTrack === null || localTrack === void 0 ? void 0 : localTrack.getBitrate();
9969
- const kind = (_a = transceiver.sender.track) === null || _a === void 0 ? void 0 : _a.kind;
9970
- if (kind === RCTrackKind.AUDIO && bitrate) {
9971
- sdpBuilder.setAudioBitrateWithMid(bitrate, mid);
9972
- }
9973
- if (kind === RCTrackKind.VIDEO && bitrate) {
9974
- sdpBuilder.setVideoBitrateWithMid(bitrate, mid);
9975
- }
10161
+ const localTrack = this._localTracks[msid];
10162
+ const bitrate = localTrack === null || localTrack === void 0 ? void 0 : localTrack.getBitrate();
10163
+ const kind = (_a = transceiver.sender.track) === null || _a === void 0 ? void 0 : _a.kind;
10164
+ // 对于已经发布出去的资源设置码率
10165
+ if (kind === RCTrackKind.AUDIO && bitrate) {
10166
+ sdpBuilder.setAudioBitrateWithMid(bitrate, mid);
9976
10167
  }
9977
- if (direction === RtpTransceiverDirection.INACTIVE) {
9978
- sdpBuilder.clearnSsrcWithMid(mid, RtpTransceiverDirection.INACTIVE);
10168
+ if (kind === RCTrackKind.VIDEO && bitrate) {
10169
+ sdpBuilder.setVideoBitrateWithMid(bitrate, mid);
9979
10170
  }
9980
10171
  }
9981
10172
  }
9982
- for (const msid in this._recvTransceiver) {
9983
- const transceiver = this._recvTransceiver[msid];
9984
- const { direction, mid } = transceiver;
9985
- if (mid) {
9986
- if (direction === RtpTransceiverDirection.RECVONLY) ;
9987
- if (direction === RtpTransceiverDirection.INACTIVE) ;
9988
- }
9989
- }
10173
+ // for (const msid in this._recvTransceiver) {
10174
+ // const transceiver: RTCRtpTransceiver = this._recvTransceiver[msid]
10175
+ // const { direction, mid } = transceiver
10176
+ // if (mid) {
10177
+ // if (direction === RtpTransceiverDirection.RECVONLY) {
10178
+ // }
10179
+ // if (direction === RtpTransceiverDirection.INACTIVE) {
10180
+ // }
10181
+ // }
10182
+ // }
9990
10183
  return sdpBuilder.stringify();
9991
10184
  }
9992
10185
  }
@@ -10248,13 +10441,13 @@ class RCRTCPeerConnection extends EventEmitter {
10248
10441
  getOutboundVideoInfo() {
10249
10442
  return this._sdpStrategy.getOutboundVideoInfo();
10250
10443
  }
10251
- _onLocalTrackMuted(track) {
10444
+ _onLocalTrackMuted(track, resolve) {
10252
10445
  // 修改已发布的小流状态
10253
10446
  const tinyTrack = this.getLocalTrack(`${track.getTrackId()}_tiny`);
10254
10447
  if (tinyTrack) {
10255
10448
  tinyTrack.__innerGetMediaStreamTrack().enabled = !track.isLocalMuted();
10256
10449
  }
10257
- this.emit(RCLocalTrack.__INNER_EVENT_MUTED_CHANGE__, track);
10450
+ this.emit(RCLocalTrack.__INNER_EVENT_MUTED_CHANGE__, track, resolve);
10258
10451
  logger$1.info(RCLoggerTag.L_RTC_PEER_CONNECTION_LOCAL_TRACK_MUTED_O, {
10259
10452
  status: RCLoggerStatus.SUCCESSED,
10260
10453
  trackId: track.getTrackId()
@@ -10389,6 +10582,7 @@ class RCRTCPeerConnection extends EventEmitter {
10389
10582
  */
10390
10583
  __reportR3R4ToPolaris() {
10391
10584
  return __awaiter(this, void 0, void 0, function* () {
10585
+ clearTimeout(this._reportR3R4ToPolarisTimer);
10392
10586
  yield this._sendR3R4Data();
10393
10587
  this._reportR3R4ToPolarisTimer = setTimeout(this.__reportR3R4ToPolaris.bind(this), 2000);
10394
10588
  });
@@ -10629,7 +10823,7 @@ class PolarisReporter {
10629
10823
  * 加入房间
10630
10824
  */
10631
10825
  sendR1() {
10632
- const rtcVersion = "5.4.6-alpha.1";
10826
+ const rtcVersion = "5.4.7-alpha.2";
10633
10827
  const imVersion = this._context.getCoreVersion();
10634
10828
  const platform = 'web';
10635
10829
  const pcName = navigator.platform;
@@ -12389,7 +12583,7 @@ class PublishCommand extends BaseCommand {
12389
12583
  }
12390
12584
  execute(store, invoker) {
12391
12585
  return __awaiter(this, void 0, void 0, function* () {
12392
- const tracks = this.tracks;
12586
+ let tracks = this.tracks;
12393
12587
  const roomId = store.roomId;
12394
12588
  logger$1.info(RCLoggerTag.L_ABSTRACT_ROOM_PUBLISH_T, {
12395
12589
  trackIds: tracks.map(getTrackIdFromAttr)
@@ -12412,6 +12606,23 @@ class PublishCommand extends BaseCommand {
12412
12606
  });
12413
12607
  return { code: RCRTCCode.PARAMS_ERROR };
12414
12608
  }
12609
+ /**
12610
+ * 过滤已被销毁的 track
12611
+ */
12612
+ tracks = tracks.filter((item) => {
12613
+ const { track } = item instanceof RCLocalTrack ? { track: item } : item;
12614
+ const isDestroyed = track.isDestroyed();
12615
+ if (isDestroyed) {
12616
+ logger$1.warn(RCLoggerTag.L_ABSTRACT_ROOM_PUBLISH_R, {
12617
+ status: RCLoggerStatus.FAILED,
12618
+ msg: `track -> ${track.getTrackId()} has beem destroyed`
12619
+ });
12620
+ }
12621
+ return !isDestroyed;
12622
+ });
12623
+ if (!tracks.length) {
12624
+ return { code: RCRTCCode.PUBLISH_TRACKS_IS_INVALID };
12625
+ }
12415
12626
  /**
12416
12627
  * 给创建的所有 peerConnection 添加事件
12417
12628
  */
@@ -12584,6 +12795,16 @@ class UnpublishCommand extends BaseCommand {
12584
12795
  pubTasks.push(this.__unpublish(store, invoker, peerCList[index], tracks));
12585
12796
  }
12586
12797
  const unpubResList = yield Promise.all(pubTasks);
12798
+ // 如果所有资源都被发布过就不再发布消息
12799
+ let unpublistRes = unpubResList.length;
12800
+ unpubResList.forEach(item => {
12801
+ if (item.code === RCRTCCode.SUCCESS && !item.data) {
12802
+ unpublistRes = unpublistRes - 1;
12803
+ }
12804
+ });
12805
+ if (unpublistRes === 0) {
12806
+ return { code: RCRTCCode.SUCCESS };
12807
+ }
12587
12808
  const result = yield this._mergeUnpublishRes(store, unpubResList);
12588
12809
  logger$1.info(RCLoggerTag.L_ABSTRACT_ROOM_UNPUBLISH_R, {
12589
12810
  status: RCLoggerStatus.SUCCESSED,
@@ -12598,9 +12819,14 @@ class UnpublishCommand extends BaseCommand {
12598
12819
  }
12599
12820
 
12600
12821
  class LocalTrackMuteCommand extends BaseCommand {
12601
- constructor(localTrack) {
12822
+ constructor(localTrack,
12823
+ /**
12824
+ * 接收 signal 扩散状态变更的结果
12825
+ */
12826
+ _recvSignalResultFn) {
12602
12827
  super();
12603
12828
  this.localTrack = localTrack;
12829
+ this._recvSignalResultFn = _recvSignalResultFn;
12604
12830
  }
12605
12831
  execute(store, invoker) {
12606
12832
  return __awaiter(this, void 0, void 0, function* () {
@@ -12627,6 +12853,8 @@ class LocalTrackMuteCommand extends BaseCommand {
12627
12853
  }
12628
12854
  }
12629
12855
  const code = yield store.context.setRTCTotalRes(roomId, buildPlusMessage(RCRTCMessageType.MODIFY, plusList), buildTotalURIMessageContent(publishedList), RCRTCMessageType.TOTAL_CONTENT_RESOURCE);
12856
+ // 执行 localTrack.mute 传入的 resolve,并返回 signal 扩散的 code 码
12857
+ this._recvSignalResultFn(code);
12630
12858
  if (code !== ErrorCode.SUCCESS) {
12631
12859
  logger.error('notice `track.enabled` change failed -> code: ' + code);
12632
12860
  }
@@ -13693,9 +13921,9 @@ class RCAbstractRoom extends EventEmitter {
13693
13921
  * 本端流状态修改,需通知房间内其他成员
13694
13922
  * @param localTrack
13695
13923
  */
13696
- _onLocalTrackMuted(localTrack) {
13924
+ _onLocalTrackMuted(localTrack, resolve) {
13697
13925
  return __awaiter(this, void 0, void 0, function* () {
13698
- this._invoker.push(new LocalTrackMuteCommand(localTrack));
13926
+ this._invoker.push(new LocalTrackMuteCommand(localTrack, resolve));
13699
13927
  });
13700
13928
  }
13701
13929
  /**
@@ -19078,9 +19306,9 @@ const installer = {
19078
19306
  logger.error('Please use the https protocol or use `http://localhost` to open the page!');
19079
19307
  return false;
19080
19308
  }
19081
- VersionManage.add('plugin-rtc', "5.4.6-alpha.1");
19082
- if (!VersionManage.validEngine(">=5.3.3-beem-alpha.2 || >=5.3.4")) {
19083
- logger.error(`The current engine version '${VersionManage.getInfo().engine}' error, plugin-rtc required engine version at least '${">=5.3.3-beem-alpha.2 || >=5.3.4"}'.`);
19309
+ VersionManage.add('plugin-rtc', "5.4.7-alpha.2");
19310
+ if (!VersionManage.validEngine("5.3.4 - 5.4.5")) {
19311
+ logger.error(`The current engine version '${VersionManage.getInfo().engine}' error, plugin-rtc required engine version at least '${"5.3.4 - 5.4.5"}'.`);
19084
19312
  return false;
19085
19313
  }
19086
19314
  return true;
@@ -19089,7 +19317,7 @@ const installer = {
19089
19317
  var _a, _b, _c, _d, _e, _f, _g, _h;
19090
19318
  logger.setLogLevel(options.logLevel);
19091
19319
  logger.setLogStdout(options.logStdout);
19092
- logger.warn(`RCRTC Version: ${"5.4.6-alpha.1"}, Commit: ${"d109ea1eb1987a80bf3299b86d39859d331d65b8"}`);
19320
+ logger.warn(`RCRTC Version: ${"5.4.7-alpha.2"}, Commit: ${"1826738708cea2e2c6cc7586713f2c24ab40e665"}`);
19093
19321
  logger.warn(`browserInfo.browser -> ${browserInfo.browser}`);
19094
19322
  logger.warn(`browserInfo.supportsUnifiedPlan -> ${browserInfo.supportsUnifiedPlan}`);
19095
19323
  logger.warn(`browserInfo.version -> ${browserInfo.version}`);