@flashphoner/websdk 2.0.246 → 2.0.248

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.
@@ -1,4 +1,4 @@
1
- Web SDK - 2.0.246
1
+ Web SDK - 2.0.248
2
2
 
3
3
  [Download builds](https://docs.flashphoner.com/display/WEBSDK2EN/Web+SDK+release+notes)
4
4
 
@@ -140,6 +140,12 @@ function init_page() {
140
140
  $("#notifyFlash").text("Failed to get media devices");
141
141
  });
142
142
 
143
+ if (Browser.isiOS() && Browser.isSafariWebRTC()) {
144
+ document.addEventListener('visibilitychange', () => {
145
+ onVisibilityChanged();
146
+ });
147
+ }
148
+
143
149
  $("#urlServer").val(setURL());
144
150
  var streamName = createUUID(4);
145
151
  $("#publishStream").val(streamName);
@@ -217,6 +223,7 @@ function onPublishing(stream) {
217
223
  }).prop('disabled', false);
218
224
  $("#switchBtn").text("Switch").off('click').click(function () {
219
225
  stream.switchCam().then(function(id) {
226
+ console.log("Switched by button to camera " + id);
220
227
  $('#videoInput option:selected').prop('selected', false);
221
228
  $("#videoInput option[value='"+ id +"']").prop('selected', true);
222
229
  }).catch(function(e) {
@@ -272,6 +279,21 @@ function onDisconnected() {
272
279
  onStopped();
273
280
  }
274
281
 
282
+ function onVisibilityChanged() {
283
+ if (Browser.isiOS() && Browser.isSafariWebRTC() && document.hidden !== undefined) {
284
+ // iOS Safari may change camera when rising from the background, use chosen one explicitly
285
+ if (publishStream && !document.hidden) {
286
+ publishStream.switchCam($('#videoInput').val()).then(function(id) {
287
+ console.log("Switched explicitly to camera " + id);
288
+ $('#videoInput option:selected').prop('selected', false);
289
+ $("#videoInput option[value='"+ id +"']").prop('selected', true);
290
+ }).catch(function(e) {
291
+ console.log("Error " + e);
292
+ });
293
+ }
294
+ }
295
+ }
296
+
275
297
  function connect() {
276
298
  var url = $('#urlServer').val();
277
299
  var tm = parseInt($('#timeout').val());
@@ -433,6 +455,7 @@ function publish() {
433
455
  stripCodecs: strippedCodecs,
434
456
  videoContentHint: contentHint
435
457
  }).on(STREAM_STATUS.PUBLISHING, function (stream) {
458
+ publishConnectionQualityStat.connectionQualityUpdateTimestamp = new Date().valueOf();
436
459
  $("#testBtn").prop('disabled', true);
437
460
  var video = document.getElementById(stream.id());
438
461
  //resize local if resolution is available
@@ -891,33 +914,39 @@ function readyControls() {
891
914
  function loadPublishStats() {
892
915
  if (publishStream) {
893
916
  publishStream.getStats(function (stats) {
894
- if (stats && stats.outboundStream) {
895
- if (stats.outboundStream.video) {
896
- showStat(stats.outboundStream.video, "outVideoStat");
897
- let vBitrate = (stats.outboundStream.video.bytesSent - videoBytesSent) * 8;
898
- if ($('#outVideoStatBitrate').length == 0) {
899
- let html = "<div>Bitrate: " + "<span id='outVideoStatBitrate' style='font-weight: normal'>" + vBitrate + "</span>" + "</div>";
900
- $("#outVideoStat").append(html);
901
- } else {
902
- $('#outVideoStatBitrate').text(vBitrate);
903
- }
904
- videoBytesSent = stats.outboundStream.video.bytesSent;
917
+ if (stats) {
918
+ if (stats.outboundStream) {
919
+ if (stats.outboundStream.video) {
920
+ showStat(stats.outboundStream.video, "outVideoStat");
921
+ let vBitrate = (stats.outboundStream.video.bytesSent - videoBytesSent) * 8;
922
+ if ($('#outVideoStatBitrate').length == 0) {
923
+ let html = "<div>Bitrate: " + "<span id='outVideoStatBitrate' style='font-weight: normal'>" + vBitrate + "</span>" + "</div>";
924
+ $("#outVideoStat").append(html);
925
+ } else {
926
+ $('#outVideoStatBitrate').text(vBitrate);
927
+ }
928
+ videoBytesSent = stats.outboundStream.video.bytesSent;
905
929
 
906
- if(new Date().valueOf() - CONNECTION_QUALITY_UPDATE_TIMEOUT_MS > publishConnectionQualityStat.connectionQualityUpdateTimestamp) {
907
- publishConnectionQualityStat.quality = CONNECTION_QUALITY.UNKNOWN;
930
+ if(new Date().valueOf() - CONNECTION_QUALITY_UPDATE_TIMEOUT_MS > publishConnectionQualityStat.connectionQualityUpdateTimestamp) {
931
+ publishConnectionQualityStat.quality = CONNECTION_QUALITY.UNKNOWN;
932
+ }
908
933
  }
909
- }
910
934
 
911
- if (stats.outboundStream.audio) {
912
- showStat(stats.outboundStream.audio, "outAudioStat");
913
- let aBitrate = (stats.outboundStream.audio.bytesSent - audioBytesSent) * 8;
914
- if ($('#outAudioStatBitrate').length == 0) {
915
- let html = "<div>Bitrate: " + "<span id='outAudioStatBitrate' style='font-weight: normal'>" + aBitrate + "</span>" + "</div>";
916
- $("#outAudioStat").append(html);
917
- } else {
918
- $('#outAudioStatBitrate').text(aBitrate);
935
+ if (stats.outboundStream.audio) {
936
+ showStat(stats.outboundStream.audio, "outAudioStat");
937
+ let aBitrate = (stats.outboundStream.audio.bytesSent - audioBytesSent) * 8;
938
+ if ($('#outAudioStatBitrate').length == 0) {
939
+ let html = "<div>Bitrate: " + "<span id='outAudioStatBitrate' style='font-weight: normal'>" + aBitrate + "</span>" + "</div>";
940
+ $("#outAudioStat").append(html);
941
+ } else {
942
+ $('#outAudioStatBitrate').text(aBitrate);
943
+ }
944
+ audioBytesSent = stats.outboundStream.audio.bytesSent;
919
945
  }
920
- audioBytesSent = stats.outboundStream.audio.bytesSent;
946
+
947
+ }
948
+ if (stats.otherStats) {
949
+ showStat(stats.otherStats, "outConnectionStat");
921
950
  }
922
951
  }
923
952
  if (publishConnectionQualityStat.quality !== undefined) {
@@ -931,47 +960,52 @@ function loadPublishStats() {
931
960
  function loadPlayStats() {
932
961
  if (previewStream) {
933
962
  previewStream.getStats(function (stats) {
934
- if (stats && stats.inboundStream) {
935
- if (stats.inboundStream.video) {
936
- showStat(stats.inboundStream.video, "inVideoStat");
937
- let vBitrate = (stats.inboundStream.video.bytesReceived - videoBytesReceived) * 8;
938
- if ($('#inVideoStatBitrate').length == 0) {
939
- let html = "<div>Bitrate: " + "<span id='inVideoStatBitrate' style='font-weight: normal'>" + vBitrate + "</span>" + "</div>";
940
- $("#inVideoStat").append(html);
941
- } else {
942
- $('#inVideoStatBitrate').text(vBitrate);
943
- }
944
- videoBytesReceived = stats.inboundStream.video.bytesReceived;
963
+ if (stats) {
964
+ if (stats.inboundStream) {
965
+ if (stats.inboundStream.video) {
966
+ showStat(stats.inboundStream.video, "inVideoStat");
967
+ let vBitrate = (stats.inboundStream.video.bytesReceived - videoBytesReceived) * 8;
968
+ if ($('#inVideoStatBitrate').length == 0) {
969
+ let html = "<div>Bitrate: " + "<span id='inVideoStatBitrate' style='font-weight: normal'>" + vBitrate + "</span>" + "</div>";
970
+ $("#inVideoStat").append(html);
971
+ } else {
972
+ $('#inVideoStatBitrate').text(vBitrate);
973
+ }
974
+ videoBytesReceived = stats.inboundStream.video.bytesReceived;
945
975
 
946
- if(new Date().valueOf() - CONNECTION_QUALITY_UPDATE_TIMEOUT_MS > playConnectionQualityStat.connectionQualityUpdateTimestamp) {
947
- playConnectionQualityStat.quality = CONNECTION_QUALITY.UNKNOWN;
976
+ if (new Date().valueOf() - CONNECTION_QUALITY_UPDATE_TIMEOUT_MS > playConnectionQualityStat.connectionQualityUpdateTimestamp) {
977
+ playConnectionQualityStat.quality = CONNECTION_QUALITY.UNKNOWN;
978
+ }
948
979
  }
949
- }
950
980
 
951
- if (stats.inboundStream.audio) {
952
- if (stats.inboundStream.audio.audioLevel) {
953
- // Round audio level to 6 decimal places
954
- stats.inboundStream.audio.audioLevel = stats.inboundStream.audio.audioLevel.toFixed(6);
955
- }
956
- showStat(stats.inboundStream.audio, "inAudioStat");
957
- let aBitrate = (stats.inboundStream.audio.bytesReceived - audioBytesReceived) * 8;
958
- if ($('#inAudioStatBitrate').length == 0) {
959
- let html = "<div style='font-weight: bold'>Bitrate: " + "<span id='inAudioStatBitrate' style='font-weight: normal'>" + aBitrate + "</span>" + "</div>";
960
- $("#inAudioStat").append(html);
961
- } else {
962
- $('#inAudioStatBitrate').text(aBitrate);
981
+ if (stats.inboundStream.audio) {
982
+ if (stats.inboundStream.audio.audioLevel) {
983
+ // Round audio level to 6 decimal places
984
+ stats.inboundStream.audio.audioLevel = stats.inboundStream.audio.audioLevel.toFixed(6);
985
+ }
986
+ showStat(stats.inboundStream.audio, "inAudioStat");
987
+ let aBitrate = (stats.inboundStream.audio.bytesReceived - audioBytesReceived) * 8;
988
+ if ($('#inAudioStatBitrate').length == 0) {
989
+ let html = "<div style='font-weight: bold'>Bitrate: " + "<span id='inAudioStatBitrate' style='font-weight: normal'>" + aBitrate + "</span>" + "</div>";
990
+ $("#inAudioStat").append(html);
991
+ } else {
992
+ $('#inAudioStatBitrate').text(aBitrate);
993
+ }
994
+ audioBytesReceived = stats.inboundStream.audio.bytesReceived;
963
995
  }
964
- audioBytesReceived = stats.inboundStream.audio.bytesReceived;
965
996
  }
966
- if (playConnectionQualityStat.quality !== undefined) {
967
- showStat({"quality": playConnectionQualityStat.quality}, "inConnectionStat");
997
+ if (stats.otherStats) {
998
+ showStat(stats.otherStats, "inConnectionStat");
968
999
  }
969
1000
  }
1001
+ if (playConnectionQualityStat.quality !== undefined) {
1002
+ showStat({"quality": playConnectionQualityStat.quality}, "inConnectionStat");
1003
+ }
970
1004
  });
971
1005
  }
972
1006
  }
973
1007
 
974
- // Helper funcltion to display stats
1008
+ // Helper function to display stats
975
1009
  function showStat(stat, type) {
976
1010
  Object.keys(stat).forEach(function(key) {
977
1011
  if (typeof stat[key] !== 'object') {
@@ -29,12 +29,12 @@
29
29
  </div>
30
30
  <div class="row">
31
31
  <h2 id="notifyFlash" class="text-danger"></h2>
32
- <div class="col-sm-2" style="width: auto">
33
- <label id="outVideoStat">Video stats</label>
34
- <div></div>
35
- <label id="outAudioStat">Audio stats</label>
36
- <div></div>
37
- <label id="outConnectionStat">Connection</label>
32
+ <div class="col-sm-2">
33
+ <label id="outVideoStat">Video stats</label>
34
+ <div></div>
35
+ <label id="outAudioStat">Audio stats</label>
36
+ <div></div>
37
+ <label id="outConnectionStat">Connection</label>
38
38
  </div>
39
39
  <div class="col-sm-4">
40
40
  <div class="text-center text-muted">Local</div>
@@ -68,16 +68,16 @@
68
68
  <div id="playStatus"></div>
69
69
  </div>
70
70
  </div>
71
- <div class="col-sm-2" style="width: auto">
72
- <label id="inVideoStat">Video stats</label>
73
- <div></div>
74
- <label id="inAudioStat">Audio stats</label>
75
- <div></div>
76
- <label id="inConnectionStat">Connection</label>
71
+ <div class="col-sm-2">
72
+ <label id="inVideoStat">Video stats</label>
73
+ <div></div>
74
+ <label id="inAudioStat">Audio stats</label>
75
+ <div></div>
76
+ <label id="inConnectionStat">Connection</label>
77
77
  </div>
78
78
  </div>
79
79
  <div class="row row-space">
80
- <div class="col-sm-4 col-sm-offset-3">
80
+ <div class="col-sm-4 col-sm-offset-4">
81
81
  <div id="connectionForm" class="input-group form-group">
82
82
  <input class="form-control" id="urlServer" type="text">
83
83
  <div class="input-group-btn">
@@ -98,7 +98,7 @@
98
98
  </div>
99
99
  <div class="row">
100
100
  <form id="form" class="form-horizontal" role="form" style="margin-top: 10px; margin-left: 10px">
101
- <div class="col-sm-4 col-sm-offset-1">
101
+ <div class="col-sm-4 col-sm-offset-2">
102
102
  <div class="form-group" id="sendAudioGroup">
103
103
  <div class="form-group">
104
104
  <label class="col-sm-2 control-label"></label>
@@ -82,6 +82,8 @@
82
82
  <div id="screenName"></div>
83
83
  <div id="screenStatus"></div>
84
84
  <div id="screenInfo"></div>
85
+ <div id="screenBitrate"></div>
86
+ <div id="screenAvailableBitrate"></div>
85
87
  </div>
86
88
  </div>
87
89
  <div class="col-sm-6 text-center">
@@ -93,6 +95,8 @@
93
95
  <div id="cameraName"></div>
94
96
  <div id="cameraStatus"></div>
95
97
  <div id="cameraInfo"></div>
98
+ <div id="cameraBitrate"></div>
99
+ <div id="cameraAvailableBitrate"></div>
96
100
  </div>
97
101
  </div>
98
102
  <div class="row row-space text-center" style="margin-top: 20px">
@@ -1,8 +1,11 @@
1
1
  const SESSION_STATUS = Flashphoner.constants.SESSION_STATUS;
2
2
  const STREAM_STATUS = Flashphoner.constants.STREAM_STATUS;
3
3
  const Browser = Flashphoner.Browser;
4
+ const STAT_INTERVAL = 1000;
4
5
  let localVideoScreen;
5
6
  let localVideoCamera;
7
+ let screenStats;
8
+ let cameraStats;
6
9
 
7
10
  const init_page = function() {
8
11
  //init api
@@ -61,6 +64,12 @@ const onStarted = function(cameraStream) {
61
64
  }
62
65
 
63
66
  const onStopped = function(session) {
67
+ if (cameraStats) {
68
+ cameraStats.stop();
69
+ }
70
+ if (screenStats) {
71
+ screenStats.stop();
72
+ }
64
73
  setPublishButton("Start", session, null);
65
74
  $("#connectBtn").prop('disabled', false);
66
75
  }
@@ -152,6 +161,7 @@ const startStreamingScreen = function(session) {
152
161
  resizeVideo(event.target);
153
162
  });
154
163
  setStatus("screen", STREAM_STATUS.PUBLISHING, screenStream);
164
+ screenStats = StreamStats("screen", screenStream, STAT_INTERVAL);
155
165
  startStreamingCamera(session, screenStream);
156
166
  }).on(STREAM_STATUS.UNPUBLISHED, function() {
157
167
  setStatus("screen", STREAM_STATUS.UNPUBLISHED);
@@ -175,6 +185,7 @@ const startStreamingCamera = function(session, screenStream) {
175
185
  resizeVideo(event.target);
176
186
  });
177
187
  setStatus("camera", STREAM_STATUS.PUBLISHING, cameraStream);
188
+ cameraStats = StreamStats("camera", cameraStream, STAT_INTERVAL);
178
189
  onStarted(cameraStream);
179
190
  }).on(STREAM_STATUS.UNPUBLISHED, function() {
180
191
  setStatus("camera", STREAM_STATUS.UNPUBLISHED);
@@ -188,7 +199,6 @@ const startStreamingCamera = function(session, screenStream) {
188
199
  }).publish();
189
200
  }
190
201
 
191
- //show connection or local stream status
192
202
  const setStatus = function(type, status, stream) {
193
203
  let nameField = $("#"+type+"Name");
194
204
  let statusField = $("#"+type+"Status");
@@ -211,6 +221,24 @@ const setStatus = function(type, status, stream) {
211
221
  }
212
222
  }
213
223
 
224
+ const setBitrate = function(type, bitrate) {
225
+ let bitrateField = $("#" + type + "Bitrate");
226
+ let text = bitrate;
227
+ if (bitrate !== "") {
228
+ text = "Bitrate: " + bitrate;
229
+ }
230
+ bitrateField.text(text);
231
+ }
232
+
233
+ const setAvailableBitrate = function(type, bitrate) {
234
+ let bitrateField = $("#" + type + "AvailableBitrate");
235
+ let text = bitrate;
236
+ if (bitrate !== "") {
237
+ text = "Available bitrate: " + bitrate;
238
+ }
239
+ bitrateField.text(text);
240
+ }
241
+
214
242
  const muteInputs = function() {
215
243
  $(":input").each(function() {
216
244
  $(this).prop('disabled',true);
@@ -250,7 +278,7 @@ const removeHighlight = function(input) {
250
278
  input.closest('.form-group').removeClass("has-error");
251
279
  }
252
280
 
253
- function getStreamName(type, url) {
281
+ const getStreamName = function(type, url) {
254
282
  let streamName = url.endsWith('/') === false ? url.split('/')[3] : "";
255
283
  if (streamName) {
256
284
  streamName += "-" + type;
@@ -262,4 +290,44 @@ function getStreamName(type, url) {
262
290
  }
263
291
  }
264
292
  return streamName;
293
+ }
294
+
295
+ const StreamStats = function(type, stream, interval) {
296
+ const streamStats = {
297
+ type: type,
298
+ timer: null,
299
+ stream: stream,
300
+ bytesSent: 0,
301
+ start: function(interval) {
302
+ if (!streamStats.timer) {
303
+ streamStats.timer = setInterval(streamStats.displayStats, interval);
304
+ }
305
+ },
306
+ stop: function() {
307
+ if (streamStats.timer) {
308
+ clearInterval(streamStats.timer);
309
+ streamStats.timer = null;
310
+ }
311
+ setBitrate(streamStats.type, "");
312
+ setAvailableBitrate(streamStats.type, "");
313
+ },
314
+ displayStats: function() {
315
+ if (streamStats.stream) {
316
+ streamStats.stream.getStats((stats) => {
317
+ if (stats) {
318
+ if (stats.outboundStream && stats.outboundStream.video) {
319
+ let vBitrate = (stats.outboundStream.video.bytesSent - streamStats.bytesSent) * 8;
320
+ setBitrate(streamStats.type, vBitrate);
321
+ streamStats.bytesSent = stats.outboundStream.video.bytesSent;
322
+ }
323
+ if (stats.otherStats && stats.otherStats.availableOutgoingBitrate !== undefined) {
324
+ setAvailableBitrate(streamStats.type, stats.otherStats.availableOutgoingBitrate);
325
+ }
326
+ }
327
+ });
328
+ }
329
+ }
330
+ };
331
+ streamStats.start(interval);
332
+ return streamStats;
265
333
  }