@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.
- package/docTemplate/README.md +1 -1
- package/examples/demo/streaming/embed_player/images/stop.png +0 -0
- package/examples/demo/streaming/embed_player/player.css +11 -1
- package/examples/demo/streaming/embed_player/player.js +101 -20
- package/examples/demo/streaming/player/player.js +25 -2
- package/flashphoner-no-flash.js +927 -2887
- package/flashphoner-no-flash.min.js +2 -2
- package/flashphoner-no-webrtc.js +794 -2595
- package/flashphoner-no-webrtc.min.js +2 -2
- package/flashphoner-no-wsplayer.js +920 -2578
- package/flashphoner-no-wsplayer.min.js +2 -2
- package/flashphoner-room-api.js +122 -21
- package/flashphoner-room-api.min.js +2 -2
- package/flashphoner-temasys-flash-websocket-without-adapterjs.js +844 -2839
- package/flashphoner-temasys-flash-websocket.js +843 -2838
- package/flashphoner-temasys-flash-websocket.min.js +1 -1
- package/flashphoner-webrtc-only.js +920 -2578
- package/flashphoner-webrtc-only.min.js +1 -1
- package/flashphoner.js +927 -2887
- package/flashphoner.min.js +2 -2
- package/package.json +1 -1
- package/src/flashphoner-core.js +9 -1
- package/src/util.js +45 -3
- package/src/webrtc-media-provider.js +68 -17
package/package.json
CHANGED
package/src/flashphoner-core.js
CHANGED
|
@@ -819,6 +819,7 @@ var createSession = function (options) {
|
|
|
819
819
|
* @param {Array<string>=} options.sipSDP Array of custom SDP params (ex. bandwidth (b=))
|
|
820
820
|
* @param {Array<string>=} options.sipHeaders Array of custom SIP headers
|
|
821
821
|
* @param {string=} options.videoContentHint Video content hint for browser ('detail' by default to maintain resolution), {@link Flashphoner.constants.CONTENT_HINT_TYPE}
|
|
822
|
+
* @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
|
|
822
823
|
* @param {Object=} options.logger Call logger options
|
|
823
824
|
* @param {sdpHook} sdpHook The callback that handles sdp from the server
|
|
824
825
|
* @returns {Call} Call
|
|
@@ -883,6 +884,7 @@ var createSession = function (options) {
|
|
|
883
884
|
var sipSDP = options.sipSDP;
|
|
884
885
|
var sipHeaders = options.sipHeaders;
|
|
885
886
|
var videoContentHint = options.videoContentHint;
|
|
887
|
+
var useControls = options.useControls;
|
|
886
888
|
/**
|
|
887
889
|
* Represents sip call.
|
|
888
890
|
*
|
|
@@ -979,6 +981,7 @@ var createSession = function (options) {
|
|
|
979
981
|
connectionConfig: mediaOptions,
|
|
980
982
|
audioOutputId: audioOutputId,
|
|
981
983
|
videoContentHint: videoContentHint,
|
|
984
|
+
useControls: useControls,
|
|
982
985
|
logger: logger
|
|
983
986
|
}).then(function (newConnection) {
|
|
984
987
|
mediaConnection = newConnection;
|
|
@@ -1117,7 +1120,8 @@ var createSession = function (options) {
|
|
|
1117
1120
|
login: cConfig.sipLogin,
|
|
1118
1121
|
constraints: constraints,
|
|
1119
1122
|
connectionConfig: mediaOptions,
|
|
1120
|
-
audioOutputId: audioOutputId
|
|
1123
|
+
audioOutputId: audioOutputId,
|
|
1124
|
+
useControls: useControls
|
|
1121
1125
|
}).then(function (newConnection) {
|
|
1122
1126
|
mediaConnection = newConnection;
|
|
1123
1127
|
return mediaConnection.setRemoteSdp(sdp);
|
|
@@ -1595,6 +1599,7 @@ var createSession = function (options) {
|
|
|
1595
1599
|
* @param {string=} options.useCanvasMediaStream EXPERIMENTAL: when publish bind browser's media stream to the canvas. It can be useful for image filtering
|
|
1596
1600
|
* @param {string=} options.videoContentHint Video content hint for browser ('detail' by default to maintain resolution), {@link Flashphoner.constants.CONTENT_HINT_TYPE}
|
|
1597
1601
|
* @param {Boolean=} options.unmutePlayOnStart Unmute playback on start. May be used after user gesture only, so set 'unmutePlayOnStart: false' for autoplay
|
|
1602
|
+
* @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
|
|
1598
1603
|
* @param {Object=} options.logger Stream logger options
|
|
1599
1604
|
* @param {sdpHook} sdpHook The callback that handles sdp from the server
|
|
1600
1605
|
* @returns {Stream} Stream
|
|
@@ -1705,6 +1710,7 @@ var createSession = function (options) {
|
|
|
1705
1710
|
var useCanvasMediaStream = options.useCanvasMediaStream;
|
|
1706
1711
|
var videoContentHint = options.videoContentHint;
|
|
1707
1712
|
var unmutePlayOnStart = options.unmutePlayOnStart;
|
|
1713
|
+
var useControls = options.useControls;
|
|
1708
1714
|
|
|
1709
1715
|
var audioState_;
|
|
1710
1716
|
var videoState_;
|
|
@@ -1890,6 +1896,7 @@ var createSession = function (options) {
|
|
|
1890
1896
|
remoteVideo: remoteVideo,
|
|
1891
1897
|
playoutDelay: playoutDelay,
|
|
1892
1898
|
unmutePlayOnStart: unmutePlayOnStart,
|
|
1899
|
+
useControls: useControls,
|
|
1893
1900
|
logger: logger
|
|
1894
1901
|
}, streamRefreshHandlers[id_]).then(function (newConnection) {
|
|
1895
1902
|
mediaConnection = newConnection;
|
|
@@ -1979,6 +1986,7 @@ var createSession = function (options) {
|
|
|
1979
1986
|
connectionConstraints: mediaConnectionConstraints,
|
|
1980
1987
|
customStream: constraints && constraints.customStream ? constraints.customStream : false,
|
|
1981
1988
|
videoContentHint: videoContentHint,
|
|
1989
|
+
useControls: useControls,
|
|
1982
1990
|
logger: logger
|
|
1983
1991
|
}).then(function (newConnection) {
|
|
1984
1992
|
mediaConnection = newConnection;
|
package/src/util.js
CHANGED
|
@@ -92,7 +92,7 @@ const Browser = {
|
|
|
92
92
|
return !!window.chrome && /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor) && !/OPR/.test(navigator.userAgent);
|
|
93
93
|
},
|
|
94
94
|
isEdge: function () {
|
|
95
|
-
return !isIE && !!window.StyleMedia;
|
|
95
|
+
return !this.isIE() && !!window.StyleMedia;
|
|
96
96
|
},
|
|
97
97
|
isOpera: function () {
|
|
98
98
|
return (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
|
|
@@ -118,6 +118,33 @@ const Browser = {
|
|
|
118
118
|
},
|
|
119
119
|
isChromiumEdge: function () {
|
|
120
120
|
return /Chrome/i.test(navigator.userAgent) && /Edg/i.test(navigator.userAgent);
|
|
121
|
+
},
|
|
122
|
+
version: function () {
|
|
123
|
+
var version = navigator.userAgent.match(/version\/(\d+)/i);
|
|
124
|
+
if (version) {
|
|
125
|
+
return version[1];
|
|
126
|
+
} else {
|
|
127
|
+
if (this.isEdge()) {
|
|
128
|
+
version = /\brv[ :]+(\d+)/g.exec(navigator.userAgent) || [];
|
|
129
|
+
}
|
|
130
|
+
if (this.isOpera()) {
|
|
131
|
+
version = navigator.userAgent.match(/\b(OPR)\/(\d+)/) || [];
|
|
132
|
+
}
|
|
133
|
+
if (this.isChromiumEdge()) {
|
|
134
|
+
version = navigator.userAgent.match(/\b(Edg)\/(\d+)/) || [];
|
|
135
|
+
}
|
|
136
|
+
if (this.isSamsungBrowser()) {
|
|
137
|
+
version = navigator.userAgent.match(/\b(SamsungBrowser)\/(\d+)/) || [];
|
|
138
|
+
}
|
|
139
|
+
if (this.isChrome()) {
|
|
140
|
+
version = navigator.userAgent.match(/\b(Chrome)\/(\d+)/) || [];
|
|
141
|
+
}
|
|
142
|
+
if (this.isFirefox()) {
|
|
143
|
+
version = navigator.userAgent.match(/\b(Firefox)\/(\d+)/) || [];
|
|
144
|
+
}
|
|
145
|
+
return version[2] || 0;
|
|
146
|
+
}
|
|
147
|
+
return 0;
|
|
121
148
|
}
|
|
122
149
|
};
|
|
123
150
|
|
|
@@ -366,9 +393,9 @@ const stripCodecs = function(sdp, codecs) {
|
|
|
366
393
|
const getCurrentCodecAndSampleRate = function(sdp, mediaType) {
|
|
367
394
|
var rows = sdp.split("\n");
|
|
368
395
|
var codecPt;
|
|
396
|
+
var ret = {};
|
|
369
397
|
for (var i = 0; i < rows.length ; i++) {
|
|
370
398
|
if (codecPt && rows[i].indexOf("a=rtpmap:" + codecPt) != -1) {
|
|
371
|
-
var ret = {};
|
|
372
399
|
ret.name = rows[i].split(" ")[1].split("/")[0];
|
|
373
400
|
ret.sampleRate = rows[i].split(" ")[1].split("/")[1];
|
|
374
401
|
return ret;
|
|
@@ -378,8 +405,22 @@ const getCurrentCodecAndSampleRate = function(sdp, mediaType) {
|
|
|
378
405
|
codecPt = rows[i].split(" ")[3].trim();
|
|
379
406
|
}
|
|
380
407
|
}
|
|
408
|
+
// A workaround for empty sdp passed #WCS-3583
|
|
409
|
+
ret.name = "undefined";
|
|
410
|
+
ret.sampleRate = "undefined";
|
|
411
|
+
return ret;
|
|
381
412
|
};
|
|
382
413
|
|
|
414
|
+
const isPromise = function(object) {
|
|
415
|
+
if (object !== null &&
|
|
416
|
+
typeof object === 'object' &&
|
|
417
|
+
typeof object.then === 'function' &&
|
|
418
|
+
typeof object.catch === 'function') {
|
|
419
|
+
return true;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return false;
|
|
423
|
+
};
|
|
383
424
|
|
|
384
425
|
module.exports = {
|
|
385
426
|
isEmptyObject,
|
|
@@ -390,5 +431,6 @@ module.exports = {
|
|
|
390
431
|
SDP,
|
|
391
432
|
logger,
|
|
392
433
|
stripCodecs,
|
|
393
|
-
getCurrentCodecAndSampleRate
|
|
434
|
+
getCurrentCodecAndSampleRate,
|
|
435
|
+
isPromise
|
|
394
436
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict';
|
|
1
|
+
-'use strict';
|
|
2
2
|
|
|
3
3
|
var browserDetails = require('webrtc-adapter').default.browserDetails;
|
|
4
4
|
const { v1: uuid_v1 } = require('uuid');
|
|
@@ -59,6 +59,8 @@ var createConnection = function (options) {
|
|
|
59
59
|
var videoContentHint = options.videoContentHint ? options.videoContentHint : 'detail';
|
|
60
60
|
// Pass the option to unmute automatically (true by default) #WCS-2425
|
|
61
61
|
var unmutePlayOnStart = options.unmutePlayOnStart !== undefined ? options.unmutePlayOnStart : true;
|
|
62
|
+
// Use a standard HTML5 video controls if needed (to enable fullscreen in Safari 16 for example) #WCS-3606
|
|
63
|
+
var useControls = options.useControls || false;
|
|
62
64
|
|
|
63
65
|
if (bidirectional) {
|
|
64
66
|
localVideo = getCacheInstance(localDisplay);
|
|
@@ -74,7 +76,7 @@ var createConnection = function (options) {
|
|
|
74
76
|
}
|
|
75
77
|
remoteVideo = getCacheInstance(remoteDisplay);
|
|
76
78
|
if (!remoteVideo) {
|
|
77
|
-
remoteVideo = createVideoElement();
|
|
79
|
+
remoteVideo = createVideoElement(useControls);
|
|
78
80
|
remoteDisplay.appendChild(remoteVideo);
|
|
79
81
|
}
|
|
80
82
|
remoteVideo.id = id + "-remote";
|
|
@@ -95,7 +97,7 @@ var createConnection = function (options) {
|
|
|
95
97
|
if (cachedVideo) {
|
|
96
98
|
remoteVideo = cachedVideo;
|
|
97
99
|
} else {
|
|
98
|
-
remoteVideo = createVideoElement();
|
|
100
|
+
remoteVideo = createVideoElement(useControls);
|
|
99
101
|
display.appendChild(remoteVideo);
|
|
100
102
|
}
|
|
101
103
|
remoteVideo.id = id;
|
|
@@ -113,9 +115,18 @@ var createConnection = function (options) {
|
|
|
113
115
|
setContentHint(localVideo.srcObject, videoContentHint);
|
|
114
116
|
connection.addStream(localVideo.srcObject);
|
|
115
117
|
}
|
|
118
|
+
} else {
|
|
119
|
+
// There is a custom video element, get its id if set #WCS-3606
|
|
120
|
+
if (remoteVideo.id) {
|
|
121
|
+
id = remoteVideo.id;
|
|
122
|
+
}
|
|
116
123
|
}
|
|
117
124
|
}
|
|
118
125
|
if (localVideo) {
|
|
126
|
+
// Enable local video controls if option requires #WCS-3606
|
|
127
|
+
if (useControls) {
|
|
128
|
+
enableVideoControls(localVideo);
|
|
129
|
+
}
|
|
119
130
|
var videoTrack = localVideo.srcObject.getVideoTracks()[0];
|
|
120
131
|
if (videoTrack) {
|
|
121
132
|
videoCams.forEach((cam, index) => {
|
|
@@ -133,6 +144,12 @@ var createConnection = function (options) {
|
|
|
133
144
|
});
|
|
134
145
|
}
|
|
135
146
|
}
|
|
147
|
+
if (remoteVideo) {
|
|
148
|
+
// Enable remote video controls if option requires #WCS-3606
|
|
149
|
+
if (useControls) {
|
|
150
|
+
enableVideoControls(remoteVideo);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
136
153
|
function setContentHint(stream, hint) {
|
|
137
154
|
stream.getVideoTracks().forEach(function(track) {
|
|
138
155
|
if(track.contentHint === undefined) {
|
|
@@ -456,7 +473,14 @@ var createConnection = function (options) {
|
|
|
456
473
|
obj[mediaType] = {};
|
|
457
474
|
//WCS-1922, currentRemoteDescription - browser compatibilitySection: Chrome 70, FF 57, Safari 11
|
|
458
475
|
var description = connection.currentRemoteDescription != undefined ? connection.currentRemoteDescription : connection.remoteDescription;
|
|
459
|
-
|
|
476
|
+
// SDP may be null in Safari 12.1 and older, prevent TypeError here #WCS-3583
|
|
477
|
+
var sdp = "";
|
|
478
|
+
if (description && description.sdp) {
|
|
479
|
+
sdp = description.sdp;
|
|
480
|
+
} else {
|
|
481
|
+
logger.debug(LOG_PREFIX, "Can't parse current SDP to detect codec and sampleRate");
|
|
482
|
+
}
|
|
483
|
+
var codec = util.getCurrentCodecAndSampleRate(sdp, mediaType);
|
|
460
484
|
obj[mediaType]["codec"] = codec.name;
|
|
461
485
|
obj[mediaType]["codecRate"] = codec.sampleRate;
|
|
462
486
|
Object.keys(report).forEach(function (key) {
|
|
@@ -473,7 +497,13 @@ var createConnection = function (options) {
|
|
|
473
497
|
if (!document.fullscreenElement && !document.mozFullScreenElement &&
|
|
474
498
|
!document.webkitFullscreenElement && !document.msFullscreenElement) {
|
|
475
499
|
if (video.requestFullscreen) {
|
|
476
|
-
video.requestFullscreen();
|
|
500
|
+
var result = video.requestFullscreen();
|
|
501
|
+
// Chromium based browsers return a promise which is rejected although user click is present #WCS-3606
|
|
502
|
+
if (util.isPromise(result)) {
|
|
503
|
+
result.catch(function(e) {
|
|
504
|
+
logger.debug(LOG_PREFIX, e);
|
|
505
|
+
});
|
|
506
|
+
}
|
|
477
507
|
} else if (video.msRequestFullscreen) {
|
|
478
508
|
video.msRequestFullscreen();
|
|
479
509
|
} else if (video.mozRequestFullScreen) {
|
|
@@ -482,10 +512,18 @@ var createConnection = function (options) {
|
|
|
482
512
|
video.webkitRequestFullscreen();
|
|
483
513
|
} else if (video.webkitEnterFullscreen) {
|
|
484
514
|
video.webkitEnterFullscreen();
|
|
485
|
-
//
|
|
515
|
+
// iOS (all versions)/MacOS (since 15) Safari hack: video is paused when leaving fullscreen mode #WCS-3606
|
|
516
|
+
var needRestart = false;
|
|
486
517
|
video.addEventListener("pause", function () {
|
|
487
|
-
|
|
518
|
+
if(needRestart) {
|
|
519
|
+
video.play();
|
|
520
|
+
needRestart = false;
|
|
521
|
+
}
|
|
488
522
|
});
|
|
523
|
+
video.addEventListener("webkitendfullscreen", function () {
|
|
524
|
+
video.play();
|
|
525
|
+
needRestart = true;
|
|
526
|
+
});
|
|
489
527
|
}
|
|
490
528
|
} else {
|
|
491
529
|
if (document.exitFullscreen) {
|
|
@@ -861,7 +899,9 @@ var loadOrdinaryVideo = function(display, stream, screenShare, constraints, vide
|
|
|
861
899
|
vEl = createVideoElement();
|
|
862
900
|
display.appendChild(vEl);
|
|
863
901
|
}
|
|
864
|
-
vEl.id
|
|
902
|
+
if (!vEl.id) {
|
|
903
|
+
vEl.id = uuid_v1() + LOCAL_CACHED_VIDEO;
|
|
904
|
+
}
|
|
865
905
|
vEl.srcObject = stream;
|
|
866
906
|
vEl.onloadedmetadata = function (e) {
|
|
867
907
|
//WCS-2751 Add screen capture using getDisplayMedia in Safari
|
|
@@ -889,7 +929,9 @@ var loadCanvasVideo = function (display, stream, video) {
|
|
|
889
929
|
vEl = canvas;
|
|
890
930
|
}
|
|
891
931
|
}
|
|
892
|
-
vEl.id
|
|
932
|
+
if (!vEl.id) {
|
|
933
|
+
vEl.id = uuid_v1() + LOCAL_CACHED_VIDEO;
|
|
934
|
+
}
|
|
893
935
|
|
|
894
936
|
let child = vEl.children[0];
|
|
895
937
|
child.srcObject = stream;
|
|
@@ -1196,13 +1238,16 @@ function getCacheInstance(display) {
|
|
|
1196
1238
|
}
|
|
1197
1239
|
}
|
|
1198
1240
|
|
|
1199
|
-
function createVideoElement() {
|
|
1241
|
+
function createVideoElement(useControls = false) {
|
|
1200
1242
|
let video = document.createElement('video');
|
|
1201
1243
|
// Prepare video tag to auto play and add specific Safari tweaks #WCS-2425
|
|
1202
1244
|
video.muted = true;
|
|
1203
|
-
if(util.Browser.isSafariWebRTC()) {
|
|
1204
|
-
|
|
1205
|
-
|
|
1245
|
+
if (util.Browser.isSafariWebRTC()) {
|
|
1246
|
+
video.setAttribute("playsinline", "");
|
|
1247
|
+
video.setAttribute("webkit-playsinline", "");
|
|
1248
|
+
}
|
|
1249
|
+
if (useControls) {
|
|
1250
|
+
enableVideoControls(video);
|
|
1206
1251
|
}
|
|
1207
1252
|
return(video);
|
|
1208
1253
|
}
|
|
@@ -1228,6 +1273,12 @@ function removeVideoElement(video) {
|
|
|
1228
1273
|
}
|
|
1229
1274
|
}
|
|
1230
1275
|
|
|
1276
|
+
function enableVideoControls(video) {
|
|
1277
|
+
if(video && !video.controls) {
|
|
1278
|
+
video.setAttribute("controls", "controls");
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1231
1282
|
/**
|
|
1232
1283
|
* Check WebRTC available
|
|
1233
1284
|
*
|
|
@@ -1398,12 +1449,10 @@ var playFirstSound = function () {
|
|
|
1398
1449
|
return false;
|
|
1399
1450
|
};
|
|
1400
1451
|
|
|
1401
|
-
var playFirstVideo = function (display, isLocal, src) {
|
|
1452
|
+
var playFirstVideo = function (display, isLocal, src, useControls = false) {
|
|
1402
1453
|
return new Promise(function (resolve, reject) {
|
|
1403
1454
|
if (!getCacheInstance(display)) {
|
|
1404
|
-
var video =
|
|
1405
|
-
video.setAttribute("playsinline", "");
|
|
1406
|
-
video.setAttribute("webkit-playsinline", "");
|
|
1455
|
+
var video = createVideoElement(useControls);
|
|
1407
1456
|
//Mute video tag to prevent local audio playback in Safari #WCS-3430
|
|
1408
1457
|
video.muted = true;
|
|
1409
1458
|
video.id = uuid_v1() + (isLocal ? LOCAL_CACHED_VIDEO : REMOTE_CACHED_VIDEO);
|
|
@@ -1414,6 +1463,7 @@ var playFirstVideo = function (display, isLocal, src) {
|
|
|
1414
1463
|
video.src = src;
|
|
1415
1464
|
video.play().then(function () {
|
|
1416
1465
|
display.appendChild(video);
|
|
1466
|
+
video.removeAttribute("src");
|
|
1417
1467
|
resolve();
|
|
1418
1468
|
}).catch(function () {
|
|
1419
1469
|
//WCS-2375. fixed autoplay in ios safari
|
|
@@ -1421,6 +1471,7 @@ var playFirstVideo = function (display, isLocal, src) {
|
|
|
1421
1471
|
video.muted = true;
|
|
1422
1472
|
video.play().then(function () {
|
|
1423
1473
|
display.appendChild(video);
|
|
1474
|
+
video.removeAttribute("src");
|
|
1424
1475
|
resolve();
|
|
1425
1476
|
});
|
|
1426
1477
|
//WCS-2375. low power mode suspends video play
|