@flashphoner/websdk 2.0.222 → 2.0.224

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.
@@ -9955,6 +9955,7 @@ var createSession = function (options) {
9955
9955
  * @param {Array<string>=} options.sipSDP Array of custom SDP params (ex. bandwidth (b=))
9956
9956
  * @param {Array<string>=} options.sipHeaders Array of custom SIP headers
9957
9957
  * @param {string=} options.videoContentHint Video content hint for browser ('detail' by default to maintain resolution), {@link Flashphoner.constants.CONTENT_HINT_TYPE}
9958
+ * @param {Boolean=} options.useControls Use a standard HTML5 video controls (play, pause, fullscreen). May be a workaround for fullscreen mode to work in Safari 16
9958
9959
  * @param {Object=} options.logger Call logger options
9959
9960
  * @param {sdpHook} sdpHook The callback that handles sdp from the server
9960
9961
  * @returns {Call} Call
@@ -10019,6 +10020,7 @@ var createSession = function (options) {
10019
10020
  var sipSDP = options.sipSDP;
10020
10021
  var sipHeaders = options.sipHeaders;
10021
10022
  var videoContentHint = options.videoContentHint;
10023
+ var useControls = options.useControls;
10022
10024
  /**
10023
10025
  * Represents sip call.
10024
10026
  *
@@ -10115,6 +10117,7 @@ var createSession = function (options) {
10115
10117
  connectionConfig: mediaOptions,
10116
10118
  audioOutputId: audioOutputId,
10117
10119
  videoContentHint: videoContentHint,
10120
+ useControls: useControls,
10118
10121
  logger: logger
10119
10122
  }).then(function (newConnection) {
10120
10123
  mediaConnection = newConnection;
@@ -10253,7 +10256,8 @@ var createSession = function (options) {
10253
10256
  login: cConfig.sipLogin,
10254
10257
  constraints: constraints,
10255
10258
  connectionConfig: mediaOptions,
10256
- audioOutputId: audioOutputId
10259
+ audioOutputId: audioOutputId,
10260
+ useControls: useControls
10257
10261
  }).then(function (newConnection) {
10258
10262
  mediaConnection = newConnection;
10259
10263
  return mediaConnection.setRemoteSdp(sdp);
@@ -10731,6 +10735,7 @@ var createSession = function (options) {
10731
10735
  * @param {string=} options.useCanvasMediaStream EXPERIMENTAL: when publish bind browser's media stream to the canvas. It can be useful for image filtering
10732
10736
  * @param {string=} options.videoContentHint Video content hint for browser ('detail' by default to maintain resolution), {@link Flashphoner.constants.CONTENT_HINT_TYPE}
10733
10737
  * @param {Boolean=} options.unmutePlayOnStart Unmute playback on start. May be used after user gesture only, so set 'unmutePlayOnStart: false' for autoplay
10738
+ * @param {Boolean=} options.useControls Use a standard HTML5 video controls (play, pause, fullscreen). May be a workaround for fullscreen mode to work in Safari 16
10734
10739
  * @param {Object=} options.logger Stream logger options
10735
10740
  * @param {sdpHook} sdpHook The callback that handles sdp from the server
10736
10741
  * @returns {Stream} Stream
@@ -10841,6 +10846,7 @@ var createSession = function (options) {
10841
10846
  var useCanvasMediaStream = options.useCanvasMediaStream;
10842
10847
  var videoContentHint = options.videoContentHint;
10843
10848
  var unmutePlayOnStart = options.unmutePlayOnStart;
10849
+ var useControls = options.useControls;
10844
10850
 
10845
10851
  var audioState_;
10846
10852
  var videoState_;
@@ -11026,6 +11032,7 @@ var createSession = function (options) {
11026
11032
  remoteVideo: remoteVideo,
11027
11033
  playoutDelay: playoutDelay,
11028
11034
  unmutePlayOnStart: unmutePlayOnStart,
11035
+ useControls: useControls,
11029
11036
  logger: logger
11030
11037
  }, streamRefreshHandlers[id_]).then(function (newConnection) {
11031
11038
  mediaConnection = newConnection;
@@ -11115,6 +11122,7 @@ var createSession = function (options) {
11115
11122
  connectionConstraints: mediaConnectionConstraints,
11116
11123
  customStream: constraints && constraints.customStream ? constraints.customStream : false,
11117
11124
  videoContentHint: videoContentHint,
11125
+ useControls: useControls,
11118
11126
  logger: logger
11119
11127
  }).then(function (newConnection) {
11120
11128
  mediaConnection = newConnection;
@@ -13234,7 +13242,7 @@ const Browser = {
13234
13242
  return !!window.chrome && /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor) && !/OPR/.test(navigator.userAgent);
13235
13243
  },
13236
13244
  isEdge: function () {
13237
- return !isIE && !!window.StyleMedia;
13245
+ return !this.isIE() && !!window.StyleMedia;
13238
13246
  },
13239
13247
  isOpera: function () {
13240
13248
  return (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
@@ -13260,6 +13268,33 @@ const Browser = {
13260
13268
  },
13261
13269
  isChromiumEdge: function () {
13262
13270
  return /Chrome/i.test(navigator.userAgent) && /Edg/i.test(navigator.userAgent);
13271
+ },
13272
+ version: function () {
13273
+ var version = navigator.userAgent.match(/version\/(\d+)/i);
13274
+ if (version) {
13275
+ return version[1];
13276
+ } else {
13277
+ if (this.isEdge()) {
13278
+ version = /\brv[ :]+(\d+)/g.exec(navigator.userAgent) || [];
13279
+ }
13280
+ if (this.isOpera()) {
13281
+ version = navigator.userAgent.match(/\b(OPR)\/(\d+)/) || [];
13282
+ }
13283
+ if (this.isChromiumEdge()) {
13284
+ version = navigator.userAgent.match(/\b(Edg)\/(\d+)/) || [];
13285
+ }
13286
+ if (this.isSamsungBrowser()) {
13287
+ version = navigator.userAgent.match(/\b(SamsungBrowser)\/(\d+)/) || [];
13288
+ }
13289
+ if (this.isChrome()) {
13290
+ version = navigator.userAgent.match(/\b(Chrome)\/(\d+)/) || [];
13291
+ }
13292
+ if (this.isFirefox()) {
13293
+ version = navigator.userAgent.match(/\b(Firefox)\/(\d+)/) || [];
13294
+ }
13295
+ return version[2] || 0;
13296
+ }
13297
+ return 0;
13263
13298
  }
13264
13299
  };
13265
13300
 
@@ -13508,9 +13543,9 @@ const stripCodecs = function(sdp, codecs) {
13508
13543
  const getCurrentCodecAndSampleRate = function(sdp, mediaType) {
13509
13544
  var rows = sdp.split("\n");
13510
13545
  var codecPt;
13546
+ var ret = {};
13511
13547
  for (var i = 0; i < rows.length ; i++) {
13512
13548
  if (codecPt && rows[i].indexOf("a=rtpmap:" + codecPt) != -1) {
13513
- var ret = {};
13514
13549
  ret.name = rows[i].split(" ")[1].split("/")[0];
13515
13550
  ret.sampleRate = rows[i].split(" ")[1].split("/")[1];
13516
13551
  return ret;
@@ -13520,8 +13555,22 @@ const getCurrentCodecAndSampleRate = function(sdp, mediaType) {
13520
13555
  codecPt = rows[i].split(" ")[3].trim();
13521
13556
  }
13522
13557
  }
13558
+ // A workaround for empty sdp passed #WCS-3583
13559
+ ret.name = "undefined";
13560
+ ret.sampleRate = "undefined";
13561
+ return ret;
13523
13562
  };
13524
13563
 
13564
+ const isPromise = function(object) {
13565
+ if (object !== null &&
13566
+ typeof object === 'object' &&
13567
+ typeof object.then === 'function' &&
13568
+ typeof object.catch === 'function') {
13569
+ return true;
13570
+ }
13571
+
13572
+ return false;
13573
+ };
13525
13574
 
13526
13575
  module.exports = {
13527
13576
  isEmptyObject,
@@ -13532,11 +13581,12 @@ module.exports = {
13532
13581
  SDP,
13533
13582
  logger,
13534
13583
  stripCodecs,
13535
- getCurrentCodecAndSampleRate
13584
+ getCurrentCodecAndSampleRate,
13585
+ isPromise
13536
13586
  };
13537
13587
 
13538
13588
  },{}],45:[function(require,module,exports){
13539
- 'use strict';
13589
+ -'use strict';
13540
13590
 
13541
13591
  var browserDetails = require('webrtc-adapter').default.browserDetails;
13542
13592
  const { v1: uuid_v1 } = require('uuid');
@@ -13597,6 +13647,8 @@ var createConnection = function (options) {
13597
13647
  var videoContentHint = options.videoContentHint ? options.videoContentHint : 'detail';
13598
13648
  // Pass the option to unmute automatically (true by default) #WCS-2425
13599
13649
  var unmutePlayOnStart = options.unmutePlayOnStart !== undefined ? options.unmutePlayOnStart : true;
13650
+ // Use a standard HTML5 video controls if needed (to enable fullscreen in Safari 16 for example) #WCS-3606
13651
+ var useControls = options.useControls || false;
13600
13652
 
13601
13653
  if (bidirectional) {
13602
13654
  localVideo = getCacheInstance(localDisplay);
@@ -13612,7 +13664,7 @@ var createConnection = function (options) {
13612
13664
  }
13613
13665
  remoteVideo = getCacheInstance(remoteDisplay);
13614
13666
  if (!remoteVideo) {
13615
- remoteVideo = createVideoElement();
13667
+ remoteVideo = createVideoElement(useControls);
13616
13668
  remoteDisplay.appendChild(remoteVideo);
13617
13669
  }
13618
13670
  remoteVideo.id = id + "-remote";
@@ -13633,7 +13685,7 @@ var createConnection = function (options) {
13633
13685
  if (cachedVideo) {
13634
13686
  remoteVideo = cachedVideo;
13635
13687
  } else {
13636
- remoteVideo = createVideoElement();
13688
+ remoteVideo = createVideoElement(useControls);
13637
13689
  display.appendChild(remoteVideo);
13638
13690
  }
13639
13691
  remoteVideo.id = id;
@@ -13651,9 +13703,18 @@ var createConnection = function (options) {
13651
13703
  setContentHint(localVideo.srcObject, videoContentHint);
13652
13704
  connection.addStream(localVideo.srcObject);
13653
13705
  }
13706
+ } else {
13707
+ // There is a custom video element, get its id if set #WCS-3606
13708
+ if (remoteVideo.id) {
13709
+ id = remoteVideo.id;
13710
+ }
13654
13711
  }
13655
13712
  }
13656
13713
  if (localVideo) {
13714
+ // Enable local video controls if option requires #WCS-3606
13715
+ if (useControls) {
13716
+ enableVideoControls(localVideo);
13717
+ }
13657
13718
  var videoTrack = localVideo.srcObject.getVideoTracks()[0];
13658
13719
  if (videoTrack) {
13659
13720
  videoCams.forEach((cam, index) => {
@@ -13671,6 +13732,12 @@ var createConnection = function (options) {
13671
13732
  });
13672
13733
  }
13673
13734
  }
13735
+ if (remoteVideo) {
13736
+ // Enable remote video controls if option requires #WCS-3606
13737
+ if (useControls) {
13738
+ enableVideoControls(remoteVideo);
13739
+ }
13740
+ }
13674
13741
  function setContentHint(stream, hint) {
13675
13742
  stream.getVideoTracks().forEach(function(track) {
13676
13743
  if(track.contentHint === undefined) {
@@ -13994,7 +14061,14 @@ var createConnection = function (options) {
13994
14061
  obj[mediaType] = {};
13995
14062
  //WCS-1922, currentRemoteDescription - browser compatibilitySection: Chrome 70, FF 57, Safari 11
13996
14063
  var description = connection.currentRemoteDescription != undefined ? connection.currentRemoteDescription : connection.remoteDescription;
13997
- var codec = util.getCurrentCodecAndSampleRate(description.sdp, mediaType);
14064
+ // SDP may be null in Safari 12.1 and older, prevent TypeError here #WCS-3583
14065
+ var sdp = "";
14066
+ if (description && description.sdp) {
14067
+ sdp = description.sdp;
14068
+ } else {
14069
+ logger.debug(LOG_PREFIX, "Can't parse current SDP to detect codec and sampleRate");
14070
+ }
14071
+ var codec = util.getCurrentCodecAndSampleRate(sdp, mediaType);
13998
14072
  obj[mediaType]["codec"] = codec.name;
13999
14073
  obj[mediaType]["codecRate"] = codec.sampleRate;
14000
14074
  Object.keys(report).forEach(function (key) {
@@ -14011,7 +14085,13 @@ var createConnection = function (options) {
14011
14085
  if (!document.fullscreenElement && !document.mozFullScreenElement &&
14012
14086
  !document.webkitFullscreenElement && !document.msFullscreenElement) {
14013
14087
  if (video.requestFullscreen) {
14014
- video.requestFullscreen();
14088
+ var result = video.requestFullscreen();
14089
+ // Chromium based browsers return a promise which is rejected although user click is present #WCS-3606
14090
+ if (util.isPromise(result)) {
14091
+ result.catch(function(e) {
14092
+ logger.debug(LOG_PREFIX, e);
14093
+ });
14094
+ }
14015
14095
  } else if (video.msRequestFullscreen) {
14016
14096
  video.msRequestFullscreen();
14017
14097
  } else if (video.mozRequestFullScreen) {
@@ -14020,10 +14100,18 @@ var createConnection = function (options) {
14020
14100
  video.webkitRequestFullscreen();
14021
14101
  } else if (video.webkitEnterFullscreen) {
14022
14102
  video.webkitEnterFullscreen();
14023
- //hack for iOS safari. Video is getting paused when switching from fullscreen to normal mode.
14103
+ // iOS (all versions)/MacOS (since 15) Safari hack: video is paused when leaving fullscreen mode #WCS-3606
14104
+ var needRestart = false;
14024
14105
  video.addEventListener("pause", function () {
14025
- video.play();
14106
+ if(needRestart) {
14107
+ video.play();
14108
+ needRestart = false;
14109
+ }
14026
14110
  });
14111
+ video.addEventListener("webkitendfullscreen", function () {
14112
+ video.play();
14113
+ needRestart = true;
14114
+ });
14027
14115
  }
14028
14116
  } else {
14029
14117
  if (document.exitFullscreen) {
@@ -14399,7 +14487,9 @@ var loadOrdinaryVideo = function(display, stream, screenShare, constraints, vide
14399
14487
  vEl = createVideoElement();
14400
14488
  display.appendChild(vEl);
14401
14489
  }
14402
- vEl.id = uuid_v1() + LOCAL_CACHED_VIDEO;
14490
+ if (!vEl.id) {
14491
+ vEl.id = uuid_v1() + LOCAL_CACHED_VIDEO;
14492
+ }
14403
14493
  vEl.srcObject = stream;
14404
14494
  vEl.onloadedmetadata = function (e) {
14405
14495
  //WCS-2751 Add screen capture using getDisplayMedia in Safari
@@ -14427,7 +14517,9 @@ var loadCanvasVideo = function (display, stream, video) {
14427
14517
  vEl = canvas;
14428
14518
  }
14429
14519
  }
14430
- vEl.id = uuid_v1() + LOCAL_CACHED_VIDEO;
14520
+ if (!vEl.id) {
14521
+ vEl.id = uuid_v1() + LOCAL_CACHED_VIDEO;
14522
+ }
14431
14523
 
14432
14524
  let child = vEl.children[0];
14433
14525
  child.srcObject = stream;
@@ -14734,13 +14826,16 @@ function getCacheInstance(display) {
14734
14826
  }
14735
14827
  }
14736
14828
 
14737
- function createVideoElement() {
14829
+ function createVideoElement(useControls = false) {
14738
14830
  let video = document.createElement('video');
14739
14831
  // Prepare video tag to auto play and add specific Safari tweaks #WCS-2425
14740
14832
  video.muted = true;
14741
- if(util.Browser.isSafariWebRTC()) {
14742
- video.setAttribute("playsinline", "");
14743
- video.setAttribute("webkit-playsinline", "");
14833
+ if (util.Browser.isSafariWebRTC()) {
14834
+ video.setAttribute("playsinline", "");
14835
+ video.setAttribute("webkit-playsinline", "");
14836
+ }
14837
+ if (useControls) {
14838
+ enableVideoControls(video);
14744
14839
  }
14745
14840
  return(video);
14746
14841
  }
@@ -14766,6 +14861,12 @@ function removeVideoElement(video) {
14766
14861
  }
14767
14862
  }
14768
14863
 
14864
+ function enableVideoControls(video) {
14865
+ if(video && !video.controls) {
14866
+ video.setAttribute("controls", "controls");
14867
+ }
14868
+ }
14869
+
14769
14870
  /**
14770
14871
  * Check WebRTC available
14771
14872
  *
@@ -14936,12 +15037,10 @@ var playFirstSound = function () {
14936
15037
  return false;
14937
15038
  };
14938
15039
 
14939
- var playFirstVideo = function (display, isLocal, src) {
15040
+ var playFirstVideo = function (display, isLocal, src, useControls = false) {
14940
15041
  return new Promise(function (resolve, reject) {
14941
15042
  if (!getCacheInstance(display)) {
14942
- var video = document.createElement('video');
14943
- video.setAttribute("playsinline", "");
14944
- video.setAttribute("webkit-playsinline", "");
15043
+ var video = createVideoElement(useControls);
14945
15044
  //Mute video tag to prevent local audio playback in Safari #WCS-3430
14946
15045
  video.muted = true;
14947
15046
  video.id = uuid_v1() + (isLocal ? LOCAL_CACHED_VIDEO : REMOTE_CACHED_VIDEO);
@@ -14952,6 +15051,7 @@ var playFirstVideo = function (display, isLocal, src) {
14952
15051
  video.src = src;
14953
15052
  video.play().then(function () {
14954
15053
  display.appendChild(video);
15054
+ video.removeAttribute("src");
14955
15055
  resolve();
14956
15056
  }).catch(function () {
14957
15057
  //WCS-2375. fixed autoplay in ios safari
@@ -14959,6 +15059,7 @@ var playFirstVideo = function (display, isLocal, src) {
14959
15059
  video.muted = true;
14960
15060
  video.play().then(function () {
14961
15061
  display.appendChild(video);
15062
+ video.removeAttribute("src");
14962
15063
  resolve();
14963
15064
  });
14964
15065
  //WCS-2375. low power mode suspends video play