@flashphoner/websdk 2.0.238 → 2.0.240
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/docTemplate/README.md +1 -1
- package/examples/demo/dependencies/js/utils.js +16 -14
- package/examples/demo/streaming/hls-player/hls-player.js +108 -13
- package/examples/demo/streaming/hls-player/player-page.html +13 -2
- package/flashphoner-no-flash.js +135 -22
- package/flashphoner-no-flash.min.js +2 -2
- package/flashphoner-no-webrtc.js +113 -20
- package/flashphoner-no-webrtc.min.js +2 -2
- package/flashphoner-no-wsplayer.js +135 -22
- package/flashphoner-no-wsplayer.min.js +2 -2
- package/flashphoner-room-api.js +156 -43
- package/flashphoner-room-api.min.js +2 -2
- package/flashphoner-temasys-flash-websocket-without-adapterjs.js +113 -20
- package/flashphoner-temasys-flash-websocket.js +113 -20
- package/flashphoner-temasys-flash-websocket.min.js +1 -1
- package/flashphoner-webrtc-only.js +135 -22
- package/flashphoner-webrtc-only.min.js +1 -1
- package/flashphoner.js +135 -22
- package/flashphoner.min.js +2 -2
- package/package.json +1 -1
- package/src/flashphoner-core.js +62 -39
- package/src/util.js +70 -1
- package/src/webrtc-media-provider.js +24 -3
package/package.json
CHANGED
package/src/flashphoner-core.js
CHANGED
|
@@ -1,35 +1,46 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { v1: uuid_v1 } = require('uuid');
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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,
|
|
880
|
+
var audioProperty = getConstraintsProperty(constraints, CONSTRAINT_AUDIO, undefined);
|
|
870
881
|
if (typeof audioProperty === 'object') {
|
|
871
|
-
audioOutputId = getConstraintsProperty(audioProperty,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
1660
|
-
var _bitrate = getConstraintsProperty(audioProperty,
|
|
1661
|
-
var _fec = getConstraintsProperty(audioProperty,
|
|
1662
|
-
audioOutputId = getConstraintsProperty(audioProperty,
|
|
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,
|
|
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,
|
|
1681
|
-
var minBitrate = getConstraintsProperty(constraints,
|
|
1682
|
-
var maxBitrate = getConstraintsProperty(constraints,
|
|
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,
|
|
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,
|
|
1689
|
-
var playHeight = (typeof options.playHeight !== 'undefined') ? options.playHeight : getConstraintsProperty(constraints,
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
});
|