@flashphoner/websdk 2.0.238 → 2.0.239

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flashphoner/websdk",
3
- "version": "2.0.238",
3
+ "version": "2.0.239",
4
4
  "description": "Official Flashphoner WebCallServer WebSDK package",
5
5
  "main": "./src/flashphoner-core.js",
6
6
  "types": "./src/flashphoner-core.d.ts",
@@ -1,35 +1,46 @@
1
1
  'use strict';
2
2
 
3
3
  const { v1: uuid_v1 } = require('uuid');
4
- var constants = require("./constants");
5
- var util = require('./util');
6
- var LoggerObject = require('./util').logger;
4
+ const constants = require("./constants");
5
+ const util = require('./util');
6
+ const LoggerObject = require('./util').logger;
7
+ const Promise = require('promise-polyfill');
8
+ const KalmanFilter = require('kalmanjs');
9
+ const browserDetails = require('webrtc-adapter').default.browserDetails;
10
+ const LOG_PREFIX = "core";
7
11
  var coreLogger;
8
12
  var loggerConf = {push: false, severity: "INFO"};
9
- var Promise = require('promise-polyfill');
10
- var KalmanFilter = require('kalmanjs');
11
- var browserDetails = require('webrtc-adapter').default.browserDetails;
12
- var LOG_PREFIX = "core";
13
13
  var isUsingTemasysPlugin = false;
14
14
 
15
15
  /**
16
16
  * @namespace Flashphoner
17
17
  */
18
18
 
19
- var SESSION_STATUS = constants.SESSION_STATUS;
20
- var STREAM_EVENT = constants.STREAM_EVENT;
21
- var STREAM_EVENT_TYPE = constants.STREAM_EVENT_TYPE;
22
- var STREAM_STATUS = constants.STREAM_STATUS;
23
- var CALL_STATUS = constants.CALL_STATUS;
24
- var TRANSPORT_TYPE = constants.TRANSPORT_TYPE;
25
- var CONNECTION_QUALITY = constants.CONNECTION_QUALITY;
26
- var ERROR_INFO = constants.ERROR_INFO;
27
- var VIDEO_RATE_GOOD_QUALITY_PERCENT_DIFFERENCE = 20;
28
- var VIDEO_RATE_BAD_QUALITY_PERCENT_DIFFERENCE = 50;
29
- var LOW_VIDEO_RATE_THRESHOLD_BAD_PERFECT = 50000;
30
- var LOW_VIDEO_RATE_BAD_QUALITY_PERCENT_DIFFERENCE = 150;
31
- var OUTBOUND_VIDEO_RATE = "outboundVideoRate";
32
- var INBOUND_VIDEO_RATE = "inboundVideoRate";
19
+ const SESSION_STATUS = constants.SESSION_STATUS;
20
+ const STREAM_EVENT = constants.STREAM_EVENT;
21
+ const STREAM_EVENT_TYPE = constants.STREAM_EVENT_TYPE;
22
+ const STREAM_STATUS = constants.STREAM_STATUS;
23
+ const CALL_STATUS = constants.CALL_STATUS;
24
+ const CONNECTION_QUALITY = constants.CONNECTION_QUALITY;
25
+ const ERROR_INFO = constants.ERROR_INFO;
26
+ const VIDEO_RATE_GOOD_QUALITY_PERCENT_DIFFERENCE = 20;
27
+ const VIDEO_RATE_BAD_QUALITY_PERCENT_DIFFERENCE = 50;
28
+ const LOW_VIDEO_RATE_THRESHOLD_BAD_PERFECT = 50000;
29
+ const LOW_VIDEO_RATE_BAD_QUALITY_PERCENT_DIFFERENCE = 150;
30
+ const OUTBOUND_VIDEO_RATE = "outboundVideoRate";
31
+ const INBOUND_VIDEO_RATE = "inboundVideoRate";
32
+ const CONSTRAINT_AUDIO = "audio";
33
+ const CONSTRAINT_AUDIO_STEREO = "stereo";
34
+ const CONSTRAINT_AUDIO_BITRATE = "bitrate";
35
+ const CONSTRAINT_AUDIO_FEC = "fec";
36
+ const CONSTRAINT_AUDIO_OUTPUT_ID = "outputId";
37
+ const CONSTRAINT_VIDEO = "video";
38
+ const CONSTRAINT_VIDEO_BITRATE = "video.bitrate";
39
+ const CONSTRAINT_VIDEO_MIN_BITRATE = "video.minBitrate";
40
+ const CONSTRAINT_VIDEO_MAX_BITRATE = "video.maxBitrate";
41
+ const CONSTRAINT_VIDEO_QUALITY = "video.quality";
42
+ const CONSTRAINT_VIDEO_WIDTH = "video.width";
43
+ const CONSTRAINT_VIDEO_HEIGHT = "video.height";
33
44
  var MediaProvider = {};
34
45
  var sessions = {};
35
46
  var initialized = false;
@@ -866,9 +877,9 @@ var createSession = function (options) {
866
877
  }
867
878
 
868
879
  var audioOutputId;
869
- var audioProperty = getConstraintsProperty(constraints, "audio", undefined);
880
+ var audioProperty = getConstraintsProperty(constraints, CONSTRAINT_AUDIO, undefined);
870
881
  if (typeof audioProperty === 'object') {
871
- audioOutputId = getConstraintsProperty(audioProperty, "outputId", 0);
882
+ audioOutputId = getConstraintsProperty(audioProperty, CONSTRAINT_AUDIO_OUTPUT_ID, 0);
872
883
  }
873
884
 
874
885
  var stripCodecs = options.stripCodecs || [];
@@ -885,6 +896,10 @@ var createSession = function (options) {
885
896
  var sipHeaders = options.sipHeaders;
886
897
  var videoContentHint = options.videoContentHint;
887
898
  var useControls = options.useControls;
899
+
900
+ var minBitrate = getConstraintsProperty(constraints, CONSTRAINT_VIDEO_MIN_BITRATE, 0);
901
+ var maxBitrate = getConstraintsProperty(constraints, CONSTRAINT_VIDEO_MAX_BITRATE, 0);
902
+
888
903
  /**
889
904
  * Represents sip call.
890
905
  *
@@ -921,8 +936,9 @@ var createSession = function (options) {
921
936
  //set remote sdp
922
937
  if (sdp && sdp !== '') {
923
938
  sdp = sdpHookHandler(sdp, sdpHook);
924
- mediaConnection.setRemoteSdp(sdp, hasTransferredCall, id_).then(function () {
925
- });
939
+ // Adjust publishing bitrate #WCS-4013
940
+ sdp = util.setPublishingBitrate(sdp, mediaConnection, minBitrate, maxBitrate);
941
+ mediaConnection.setRemoteSdp(sdp, hasTransferredCall, id_).then(function () {});
926
942
  return;
927
943
  }
928
944
  var event = callInfo.status;
@@ -1084,6 +1100,8 @@ var createSession = function (options) {
1084
1100
  status_ = CALL_STATUS.PENDING;
1085
1101
  var sdp;
1086
1102
  var sdpHook = answerOptions.sdpHook;
1103
+ var minBitrate = getConstraintsProperty(constraints, CONSTRAINT_VIDEO_MIN_BITRATE, 0);
1104
+ var maxBitrate = getConstraintsProperty(constraints, CONSTRAINT_VIDEO_MAX_BITRATE, 0);
1087
1105
  sipSDP = answerOptions.sipSDP;
1088
1106
  sipHeaders = answerOptions.sipHeaders;
1089
1107
  if (!remoteSdpCache[id_]) {
@@ -1091,6 +1109,8 @@ var createSession = function (options) {
1091
1109
  throw new Error("No remote sdp available");
1092
1110
  } else {
1093
1111
  sdp = sdpHookHandler(remoteSdpCache[id_], sdpHook);
1112
+ // Adjust publishing bitrate #WCS-4013
1113
+ sdp = util.setPublishingBitrate(sdp, null, minBitrate, maxBitrate);
1094
1114
  delete remoteSdpCache[id_];
1095
1115
  }
1096
1116
  if (util.SDP.matchPrefix(sdp, "m=video").length == 0) {
@@ -1124,6 +1144,8 @@ var createSession = function (options) {
1124
1144
  useControls: useControls
1125
1145
  }).then(function (newConnection) {
1126
1146
  mediaConnection = newConnection;
1147
+ // Set publishing bitrate via sender encodings if SDP feature is not supported
1148
+ mediaConnection.setPublishingBitrate(minBitrate, maxBitrate);
1127
1149
  return mediaConnection.setRemoteSdp(sdp);
1128
1150
  }).then(function () {
1129
1151
  return mediaConnection.createAnswer({
@@ -1651,15 +1673,15 @@ var createSession = function (options) {
1651
1673
  // Receive media
1652
1674
  var receiveAudio;
1653
1675
  var audioOutputId;
1654
- var audioProperty = getConstraintsProperty(constraints, "audio", undefined);
1676
+ var audioProperty = getConstraintsProperty(constraints, CONSTRAINT_AUDIO, undefined);
1655
1677
  if (typeof audioProperty === 'boolean') {
1656
1678
  receiveAudio = audioProperty;
1657
1679
  } else if (typeof audioProperty === 'object') {
1658
1680
  receiveAudio = true;
1659
- var _stereo = getConstraintsProperty(audioProperty, "stereo", 0);
1660
- var _bitrate = getConstraintsProperty(audioProperty, "bitrate", 0);
1661
- var _fec = getConstraintsProperty(audioProperty, "fec", 0);
1662
- audioOutputId = getConstraintsProperty(audioProperty, "outputId", 0);
1681
+ var _stereo = getConstraintsProperty(audioProperty, CONSTRAINT_AUDIO_STEREO, 0);
1682
+ var _bitrate = getConstraintsProperty(audioProperty, CONSTRAINT_AUDIO_BITRATE, 0);
1683
+ var _fec = getConstraintsProperty(audioProperty, CONSTRAINT_AUDIO_FEC, 0);
1684
+ audioOutputId = getConstraintsProperty(audioProperty, CONSTRAINT_AUDIO_OUTPUT_ID, 0);
1663
1685
  var _codecOptions = "";
1664
1686
  if (_bitrate) _codecOptions += "maxaveragebitrate=" + _bitrate + ";";
1665
1687
  if (_stereo) _codecOptions += "stereo=1;sprop-stereo=1;";
@@ -1668,7 +1690,7 @@ var createSession = function (options) {
1668
1690
  receiveAudio = (typeof options.receiveAudio !== 'undefined') ? options.receiveAudio : true;
1669
1691
  }
1670
1692
  var receiveVideo;
1671
- var videoProperty = getConstraintsProperty(constraints, "video", undefined);
1693
+ var videoProperty = getConstraintsProperty(constraints, CONSTRAINT_VIDEO, undefined);
1672
1694
  if (typeof videoProperty === 'boolean') {
1673
1695
  receiveVideo = videoProperty;
1674
1696
  } else if (typeof videoProperty === 'object') {
@@ -1677,16 +1699,16 @@ var createSession = function (options) {
1677
1699
  receiveVideo = (typeof options.receiveVideo !== 'undefined') ? options.receiveVideo : true;
1678
1700
  }
1679
1701
  // Bitrate
1680
- var bitrate = getConstraintsProperty(constraints, "video.bitrate", 0);
1681
- var minBitrate = getConstraintsProperty(constraints, "video.minBitrate", 0);
1682
- var maxBitrate = getConstraintsProperty(constraints, "video.maxBitrate", 0);
1702
+ var bitrate = getConstraintsProperty(constraints, CONSTRAINT_VIDEO_BITRATE, 0);
1703
+ var minBitrate = getConstraintsProperty(constraints, CONSTRAINT_VIDEO_MIN_BITRATE, 0);
1704
+ var maxBitrate = getConstraintsProperty(constraints, CONSTRAINT_VIDEO_MAX_BITRATE, 0);
1683
1705
 
1684
1706
  // Quality
1685
- var quality = getConstraintsProperty(constraints, "video.quality", 0);
1707
+ var quality = getConstraintsProperty(constraints, CONSTRAINT_VIDEO_QUALITY, 0);
1686
1708
  if (quality > 100) quality = 100;
1687
1709
  // Play resolution
1688
- var playWidth = (typeof options.playWidth !== 'undefined') ? options.playWidth : getConstraintsProperty(constraints, "video.width", 0);
1689
- var playHeight = (typeof options.playHeight !== 'undefined') ? options.playHeight : getConstraintsProperty(constraints, "video.height", 0);
1710
+ var playWidth = (typeof options.playWidth !== 'undefined') ? options.playWidth : getConstraintsProperty(constraints, CONSTRAINT_VIDEO_WIDTH, 0);
1711
+ var playHeight = (typeof options.playHeight !== 'undefined') ? options.playHeight : getConstraintsProperty(constraints, CONSTRAINT_VIDEO_HEIGHT, 0);
1690
1712
  var stripCodecs = options.stripCodecs || [];
1691
1713
  var resolution = {};
1692
1714
 
@@ -1747,8 +1769,9 @@ var createSession = function (options) {
1747
1769
  var _sdp = sdp;
1748
1770
  if (_codecOptions) _sdp = util.SDP.writeFmtp(sdp, _codecOptions, "opus");
1749
1771
  _sdp = sdpHookHandler(_sdp, sdpHook);
1750
- mediaConnection.setRemoteSdp(_sdp).then(function () {
1751
- });
1772
+ // Adjust publishing bitrate #WCS-4013
1773
+ _sdp = util.setPublishingBitrate(_sdp, mediaConnection, minBitrate, maxBitrate);
1774
+ mediaConnection.setRemoteSdp(_sdp).then(function () {});
1752
1775
  return;
1753
1776
  }
1754
1777
 
package/src/util.js CHANGED
@@ -173,6 +173,61 @@ const SDP = {
173
173
  }
174
174
  }
175
175
  return result;
176
+ },
177
+ setPublishingBitrate: function (sdp, minBitrate, maxBitrate) {
178
+ if(sdp && (minBitrate || maxBitrate)) {
179
+ let sdpArray = sdp.split("\n");
180
+ let i;
181
+ let rtpmap = -1, codec = "";
182
+ let matches;
183
+ let bitrateString = "";
184
+ for (i = 0; i < sdpArray.length; i++) {
185
+ if (sdpArray[i].startsWith("a=rtpmap")) {
186
+ matches = sdpArray[i].match("a=rtpmap:(.+) (.+)/.*");
187
+ if (matches && matches.length > 2) {
188
+ rtpmap = parseInt(matches[1], 10);
189
+ codec = matches[2];
190
+ }
191
+ } else {
192
+ if (codec === "H264" || codec === "VP8") {
193
+ if (sdpArray[i].startsWith("a=fmtp:" + rtpmap)) {
194
+ bitrateString = this.getBitrateString(sdpArray[i], minBitrate, maxBitrate);
195
+ if (bitrateString) {
196
+ sdpArray[i] += ";" + bitrateString;
197
+ }
198
+ } else {
199
+ bitrateString = this.getBitrateString("", minBitrate, maxBitrate);
200
+ if (bitrateString) {
201
+ sdpArray[i] = "a=fmtp:" + rtpmap + " " + bitrateString + "\r\n" + sdpArray[i];
202
+ }
203
+ }
204
+ codec = "";
205
+ rtpmap = -1;
206
+ }
207
+ }
208
+ }
209
+ let newSDP = "";
210
+ for (i = 0; i < sdpArray.length; i++) {
211
+ if (sdpArray[i] != "") {
212
+ newSDP += sdpArray[i] + "\n";
213
+ }
214
+ }
215
+ return newSDP;
216
+ }
217
+ return sdp;
218
+ },
219
+ getBitrateString: function (string, minBitrate, maxBitrate) {
220
+ let bitrateString = "";
221
+ if (minBitrate && string.indexOf("x-google-min-bitrate") == -1) {
222
+ bitrateString += "x-google-min-bitrate=" + minBitrate;
223
+ }
224
+ if (maxBitrate && string.indexOf("x-google-max-bitrate") == -1) {
225
+ if (bitrateString) {
226
+ bitrateString += ";";
227
+ }
228
+ bitrateString += "x-google-max-bitrate=" + maxBitrate;
229
+ }
230
+ return bitrateString;
176
231
  }
177
232
  };
178
233
 
@@ -422,6 +477,19 @@ const isPromise = function(object) {
422
477
  return false;
423
478
  };
424
479
 
480
+ const setPublishingBitrate = function(sdp, mediaConnection, minBitrate, maxBitrate) {
481
+ if (minBitrate || maxBitrate) {
482
+ if (sdp && Browser.isChrome() || Browser.isSafariWebRTC()) {
483
+ // Set publishing bitrate constraints via remote SDP
484
+ sdp = SDP.setPublishingBitrate(sdp, minBitrate, maxBitrate);
485
+ } else if (mediaConnection) {
486
+ // Set publishing bitrate via sender encodings if SDP feature is not supported
487
+ mediaConnection.setPublishingBitrate(minBitrate, maxBitrate);
488
+ }
489
+ }
490
+ return sdp;
491
+ };
492
+
425
493
  module.exports = {
426
494
  isEmptyObject,
427
495
  copyObjectToArray,
@@ -432,5 +500,6 @@ module.exports = {
432
500
  logger,
433
501
  stripCodecs,
434
502
  getCurrentCodecAndSampleRate,
435
- isPromise
503
+ isPromise,
504
+ setPublishingBitrate
436
505
  };
@@ -69,7 +69,7 @@ var createConnection = function (options) {
69
69
  if (localVideo.srcObject) {
70
70
  localVideo.id = id + "-local";
71
71
  setContentHint(localVideo.srcObject, videoContentHint);
72
- connection.addStream(localVideo.srcObject);
72
+ addStreamTracks(connection, localVideo.srcObject);
73
73
  } else {
74
74
  localVideo = null;
75
75
  }
@@ -113,7 +113,7 @@ var createConnection = function (options) {
113
113
  localVideo = cachedVideo;
114
114
  localVideo.id = id;
115
115
  setContentHint(localVideo.srcObject, videoContentHint);
116
- connection.addStream(localVideo.srcObject);
116
+ addStreamTracks(connection, localVideo.srcObject);
117
117
  }
118
118
  } else {
119
119
  // There is a custom video element, get its id if set #WCS-3606
@@ -159,7 +159,12 @@ var createConnection = function (options) {
159
159
  track.contentHint = hint;
160
160
  }
161
161
  });
162
- }
162
+ }
163
+ function addStreamTracks(pc, stream) {
164
+ stream.getTracks().forEach((track) => {
165
+ pc.addTrack(track, stream);
166
+ });
167
+ }
163
168
  connection.ontrack = function (event) {
164
169
  if (remoteVideo) {
165
170
  remoteVideo.srcObject = event.streams[0];
@@ -773,6 +778,21 @@ var createConnection = function (options) {
773
778
  screenShare = false;
774
779
  };
775
780
 
781
+ var setPublishingBitrate = function(minBitrate, maxBitrate) {
782
+ let senders = connection.getSenders();
783
+ senders.forEach((sender) => {
784
+ if (sender.track.kind == "video" && maxBitrate) {
785
+ let parameters = sender.getParameters();
786
+ for (let i = 0; i < parameters.encodings.length; i++) {
787
+ if (!parameters.encodings[i].maxBitrate) {
788
+ parameters.encodings[i].maxBitrate = maxBitrate * 1000;
789
+ }
790
+ }
791
+ sender.setParameters(parameters).then(() => {});
792
+ }
793
+ });
794
+ };
795
+
776
796
  var exports = {};
777
797
  exports.state = state;
778
798
  exports.createOffer = createOffer;
@@ -799,6 +819,7 @@ var createConnection = function (options) {
799
819
  exports.switchMic = switchMic;
800
820
  exports.switchToScreen = switchToScreen;
801
821
  exports.switchToCam = switchToCam;
822
+ exports.setPublishingBitrate = setPublishingBitrate;
802
823
  connections[id] = exports;
803
824
  resolve(exports);
804
825
  });