@reactoo/watchtogether-sdk-js 2.5.83 → 2.5.85
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/dist/watchtogether-sdk.js +17 -17
- package/dist/watchtogether-sdk.min.js +2 -2
- package/example/index.html +16 -7
- package/package.json +1 -1
- package/src/models/room-session.js +10 -3
- package/src/modules/wt-room.js +297 -293
package/src/modules/wt-room.js
CHANGED
|
@@ -166,6 +166,7 @@ class RoomSession {
|
|
|
166
166
|
constructor(constructId = null, type = 'reactooroom', options = {}) {
|
|
167
167
|
|
|
168
168
|
Object.assign(this, emitter());
|
|
169
|
+
this.options = {...options};
|
|
169
170
|
this.defaultDataChannelLabel = 'JanusDataChannel'
|
|
170
171
|
this.server = null;
|
|
171
172
|
this.iceServers = null;
|
|
@@ -176,9 +177,14 @@ class RoomSession {
|
|
|
176
177
|
this.userId = null;
|
|
177
178
|
this.sessiontype = type;
|
|
178
179
|
this.initialBitrate = 0;
|
|
180
|
+
this.simulcast = false;
|
|
181
|
+
this.simulcastBitrates = {
|
|
182
|
+
high: 900000,
|
|
183
|
+
medium: 300000,
|
|
184
|
+
low: 100000
|
|
185
|
+
};
|
|
179
186
|
this.recordingFilename = null;
|
|
180
187
|
this.pluginName = RoomSession.sessionTypes[type];
|
|
181
|
-
this.options = options;
|
|
182
188
|
this.id = null;
|
|
183
189
|
this.privateId = null;
|
|
184
190
|
this.constructId = constructId || RoomSession.randomString(16);
|
|
@@ -186,7 +192,6 @@ class RoomSession {
|
|
|
186
192
|
this.handleId = null;
|
|
187
193
|
this.ws = null;
|
|
188
194
|
this.isRestarting = false;
|
|
189
|
-
|
|
190
195
|
this.isConnecting = false;
|
|
191
196
|
this.isDisconnecting = false;
|
|
192
197
|
this.isConnected = false;
|
|
@@ -206,7 +211,6 @@ class RoomSession {
|
|
|
206
211
|
this.isVideoMuted = false;
|
|
207
212
|
this.isVideoEnabled = false;
|
|
208
213
|
this.isAudioEnabed = false;
|
|
209
|
-
this.isUnifiedPlan = RoomSession.checkUnifiedPlan();
|
|
210
214
|
|
|
211
215
|
this.subscriptionRules = {
|
|
212
216
|
...RoomSession.subscriptionRules,
|
|
@@ -220,35 +224,6 @@ class RoomSession {
|
|
|
220
224
|
|
|
221
225
|
}
|
|
222
226
|
|
|
223
|
-
// Check if this browser supports Unified Plan and transceivers
|
|
224
|
-
// Based on https://codepen.io/anon/pen/ZqLwWV?editors=0010
|
|
225
|
-
static checkUnifiedPlan() {
|
|
226
|
-
let unifiedPlan = false;
|
|
227
|
-
if (adapter.browserDetails.browser === 'firefox' &&
|
|
228
|
-
adapter.browserDetails.version >= 59) {
|
|
229
|
-
// Firefox definitely does, starting from version 59
|
|
230
|
-
unifiedPlan = true;
|
|
231
|
-
} else if (adapter.browserDetails.browser === 'chrome' &&
|
|
232
|
-
adapter.browserDetails.version >= 72) {
|
|
233
|
-
// Chrome does, but it's only usable from version 72 on
|
|
234
|
-
unifiedPlan = true;
|
|
235
|
-
} else if (!window.RTCRtpTransceiver || !('currentDirection' in RTCRtpTransceiver.prototype)) {
|
|
236
|
-
// Safari supports addTransceiver() but not Unified Plan when
|
|
237
|
-
// currentDirection is not defined (see codepen above).
|
|
238
|
-
unifiedPlan = false;
|
|
239
|
-
} else {
|
|
240
|
-
// Check if addTransceiver() throws an exception
|
|
241
|
-
const tempPc = new RTCPeerConnection();
|
|
242
|
-
try {
|
|
243
|
-
tempPc.addTransceiver('audio');
|
|
244
|
-
unifiedPlan = true;
|
|
245
|
-
} catch (e) {
|
|
246
|
-
}
|
|
247
|
-
tempPc.close();
|
|
248
|
-
}
|
|
249
|
-
return unifiedPlan;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
227
|
_participantShouldSubscribe(userId) {
|
|
253
228
|
const myUser = decodeJanusDisplay(this.display);
|
|
254
229
|
const remoteUser = decodeJanusDisplay(userId);
|
|
@@ -564,7 +539,8 @@ class RoomSession {
|
|
|
564
539
|
"request": "join",
|
|
565
540
|
"room": this.roomId,
|
|
566
541
|
"ptype": "subscriber",
|
|
567
|
-
|
|
542
|
+
streams: streams.map(stream => ({feed: stream.id, mid: stream.mid})),
|
|
543
|
+
//"feed": id,
|
|
568
544
|
"private_id": this.privateId,
|
|
569
545
|
...(this.webrtcVersion > 1000 ? {id: this.userId} : {}),
|
|
570
546
|
pin: this.pin
|
|
@@ -576,7 +552,8 @@ class RoomSession {
|
|
|
576
552
|
})
|
|
577
553
|
}
|
|
578
554
|
}
|
|
579
|
-
}
|
|
555
|
+
}
|
|
556
|
+
else if (event === "event") {
|
|
580
557
|
|
|
581
558
|
if (msg["streams"] !== undefined && msg["streams"] !== null) {
|
|
582
559
|
this._log('Got my own streams back', msg["streams"]);
|
|
@@ -600,7 +577,7 @@ class RoomSession {
|
|
|
600
577
|
"request": "join",
|
|
601
578
|
"room": this.roomId,
|
|
602
579
|
"ptype": "subscriber",
|
|
603
|
-
|
|
580
|
+
streams: streams.map(stream => ({feed: stream.id, mid: stream.mid})),
|
|
604
581
|
"private_id": this.privateId,
|
|
605
582
|
...(this.webrtcVersion > 1000 ? {id: this.userId} : {}),
|
|
606
583
|
pin: this.pin
|
|
@@ -679,6 +656,11 @@ class RoomSession {
|
|
|
679
656
|
|
|
680
657
|
}
|
|
681
658
|
} else if (type === "webrtcup") {
|
|
659
|
+
|
|
660
|
+
if(this.simulcast) {
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
|
|
682
664
|
this._log('Configuring bitrate: ' + this.initialBitrate);
|
|
683
665
|
if (this.initialBitrate > 0) {
|
|
684
666
|
this.sendMessage(this.handleId, {
|
|
@@ -700,6 +682,7 @@ class RoomSession {
|
|
|
700
682
|
let jsep = json["jsep"];
|
|
701
683
|
let event = msg["videoroom"];
|
|
702
684
|
let error = msg["error"];
|
|
685
|
+
let substream = msg["substream"];
|
|
703
686
|
|
|
704
687
|
if (event === "attached") {
|
|
705
688
|
this._log('Remote have successfully joined Room', msg);
|
|
@@ -982,7 +965,7 @@ class RoomSession {
|
|
|
982
965
|
});
|
|
983
966
|
}
|
|
984
967
|
|
|
985
|
-
connect(roomId, pin, server, iceServers, token, display, userId, webrtcVersion = 0, initialBitrate = 0, recordingFilename) {
|
|
968
|
+
connect(roomId, pin, server, iceServers, token, display, userId, webrtcVersion = 0, initialBitrate = 0, recordingFilename, simulcast = false, simulcastBitrates = {}) {
|
|
986
969
|
|
|
987
970
|
if (this.isConnecting) {
|
|
988
971
|
return Promise.reject({type: 'warning', id: 16, message: 'connection already in progress'});
|
|
@@ -993,6 +976,7 @@ class RoomSession {
|
|
|
993
976
|
}
|
|
994
977
|
this._stopKeepAlive();
|
|
995
978
|
this._abortController = new AbortController();
|
|
979
|
+
|
|
996
980
|
this.sessionId = null;
|
|
997
981
|
this.server = server;
|
|
998
982
|
this.iceServers = iceServers;
|
|
@@ -1005,6 +989,9 @@ class RoomSession {
|
|
|
1005
989
|
this.initialBitrate = initialBitrate;
|
|
1006
990
|
this.recordingFilename = recordingFilename;
|
|
1007
991
|
this.isConnecting = true;
|
|
992
|
+
this.simulcast = simulcast;
|
|
993
|
+
this.simulcastBitrates = {...this.simulcastBitrates, ...simulcastBitrates};
|
|
994
|
+
|
|
1008
995
|
this.emit('joining', true);
|
|
1009
996
|
return new Promise((resolve, reject) => {
|
|
1010
997
|
|
|
@@ -1263,7 +1250,7 @@ class RoomSession {
|
|
|
1263
1250
|
if (!config.pc) {
|
|
1264
1251
|
let pc_config = {"iceServers": this.iceServers, "iceTransportPolicy": 'all', "bundlePolicy": undefined};
|
|
1265
1252
|
|
|
1266
|
-
pc_config["sdpSemantics"] =
|
|
1253
|
+
pc_config["sdpSemantics"] = "unified-plan";
|
|
1267
1254
|
|
|
1268
1255
|
let pc_constraints = {};
|
|
1269
1256
|
|
|
@@ -1281,6 +1268,7 @@ class RoomSession {
|
|
|
1281
1268
|
}
|
|
1282
1269
|
this.emit('connectionState', [handleId, handleId === this.handleId, config.pc.connectionState]);
|
|
1283
1270
|
if(handleId !== this.handleId && config.pc.connectionState === 'connected') {
|
|
1271
|
+
|
|
1284
1272
|
this.emit(this._getAddParticipantEventName(handle.handleId), {
|
|
1285
1273
|
tid: generateUUID(),
|
|
1286
1274
|
id: handle.handleId,
|
|
@@ -1376,12 +1364,9 @@ class RoomSession {
|
|
|
1376
1364
|
|
|
1377
1365
|
event.track.onended = (ev) => {
|
|
1378
1366
|
|
|
1379
|
-
let
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
t => t.receiver.track === ev.target);
|
|
1383
|
-
mid = transceiver.mid;
|
|
1384
|
-
}
|
|
1367
|
+
let transceiver = config.pc?.getTransceivers()?.find(
|
|
1368
|
+
t => t.receiver.track === ev.target);
|
|
1369
|
+
let mid = transceiver?.mid || ev.target.id;
|
|
1385
1370
|
|
|
1386
1371
|
if (config.stream) {
|
|
1387
1372
|
config.stream && config.stream.removeTrack(ev.target);
|
|
@@ -1406,12 +1391,9 @@ class RoomSession {
|
|
|
1406
1391
|
event.track.onmute = (ev) => {
|
|
1407
1392
|
this._log('remoteTrackMuted', 'onmute');
|
|
1408
1393
|
|
|
1409
|
-
let
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
t => t.receiver.track === ev.target);
|
|
1413
|
-
mid = transceiver.mid;
|
|
1414
|
-
}
|
|
1394
|
+
let transceiver = config.pc.getTransceivers().find(
|
|
1395
|
+
t => t.receiver.track === ev.target);
|
|
1396
|
+
let mid = transceiver.mid || ev.target.id;
|
|
1415
1397
|
|
|
1416
1398
|
this.emit('remoteTrackMuted', {
|
|
1417
1399
|
id: handle.handleId,
|
|
@@ -1428,12 +1410,9 @@ class RoomSession {
|
|
|
1428
1410
|
event.track.onunmute = (ev) => {
|
|
1429
1411
|
this._log('remoteTrackMuted', 'onunmute');
|
|
1430
1412
|
|
|
1431
|
-
let
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
t => t.receiver.track === ev.target);
|
|
1435
|
-
mid = transceiver.mid;
|
|
1436
|
-
}
|
|
1413
|
+
let transceiver = config.pc.getTransceivers().find(
|
|
1414
|
+
t => t.receiver.track === ev.target);
|
|
1415
|
+
let mid = transceiver.mid || ev.target.id;
|
|
1437
1416
|
|
|
1438
1417
|
this.emit('remoteTrackMuted', {
|
|
1439
1418
|
id: handle.handleId,
|
|
@@ -1552,7 +1531,8 @@ class RoomSession {
|
|
|
1552
1531
|
config.isIceRestarting = true;
|
|
1553
1532
|
let hasAudio = !!(config.stream && config.stream.getAudioTracks().length > 0);
|
|
1554
1533
|
let hasVideo = !!(config.stream && config.stream.getVideoTracks().length > 0);
|
|
1555
|
-
this.
|
|
1534
|
+
this._setupTransceivers([hasAudio, false, hasVideo, false]);
|
|
1535
|
+
this._createAO('offer', handleId, true )
|
|
1556
1536
|
.then((jsep) => {
|
|
1557
1537
|
if (!jsep) {
|
|
1558
1538
|
return null;
|
|
@@ -1568,7 +1548,7 @@ class RoomSession {
|
|
|
1568
1548
|
})
|
|
1569
1549
|
.catch((e) => {
|
|
1570
1550
|
config.isIceRestarting = false;
|
|
1571
|
-
this.emit('
|
|
1551
|
+
this.emit('error', {type: 'warning', id: 28, message: 'iceRestart failed', data: e});
|
|
1572
1552
|
});
|
|
1573
1553
|
} else {
|
|
1574
1554
|
this._log('Performing remote ICE restart', handleId);
|
|
@@ -1584,148 +1564,139 @@ class RoomSession {
|
|
|
1584
1564
|
|
|
1585
1565
|
}
|
|
1586
1566
|
|
|
1587
|
-
|
|
1567
|
+
_setupTransceivers(handleId, [audioSend, audioRecv, videoSend, videoRecv]) {
|
|
1588
1568
|
|
|
1589
1569
|
let handle = this._getHandle(handleId);
|
|
1590
1570
|
if (!handle) {
|
|
1591
|
-
return
|
|
1592
|
-
type: 'warning',
|
|
1593
|
-
id: 15,
|
|
1594
|
-
message: 'id non-existent',
|
|
1595
|
-
data: [handleId, 'createAO', type]
|
|
1596
|
-
});
|
|
1571
|
+
return null;
|
|
1597
1572
|
}
|
|
1598
1573
|
|
|
1599
|
-
let
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1574
|
+
let config = handle.webrtcStuff;
|
|
1575
|
+
let audioTransceiver = null, videoTransceiver = null;
|
|
1576
|
+
let transceivers = config.pc.getTransceivers();
|
|
1577
|
+
if (transceivers && transceivers.length > 0) {
|
|
1578
|
+
for (var i in transceivers) {
|
|
1579
|
+
var t = transceivers[i];
|
|
1580
|
+
if ((t.sender && t.sender.track && t.sender.track.kind === "audio") ||
|
|
1581
|
+
(t.receiver && t.receiver.track && t.receiver.track.kind === "audio")) {
|
|
1582
|
+
if (!audioTransceiver)
|
|
1583
|
+
audioTransceiver = t;
|
|
1584
|
+
continue;
|
|
1585
|
+
}
|
|
1586
|
+
if ((t.sender && t.sender.track && t.sender.track.kind === "video") ||
|
|
1587
|
+
(t.receiver && t.receiver.track && t.receiver.track.kind === "video")) {
|
|
1588
|
+
if (!videoTransceiver)
|
|
1589
|
+
videoTransceiver = t;
|
|
1590
|
+
continue;
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1604
1593
|
}
|
|
1605
1594
|
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
for (var i in transceivers) {
|
|
1615
|
-
var t = transceivers[i];
|
|
1616
|
-
if ((t.sender && t.sender.track && t.sender.track.kind === "audio" && t.stopped === false) ||
|
|
1617
|
-
(t.receiver && t.receiver.track && t.receiver.track.kind === "audio" && t.stopped === false)) {
|
|
1618
|
-
if (!audioTransceiver)
|
|
1619
|
-
audioTransceiver = t;
|
|
1620
|
-
continue;
|
|
1621
|
-
}
|
|
1622
|
-
if ((t.sender && t.sender.track && t.sender.track.kind === "video" && t.stopped === false) ||
|
|
1623
|
-
(t.receiver && t.receiver.track && t.receiver.track.kind === "video" && t.stopped === false)) {
|
|
1624
|
-
if (!videoTransceiver)
|
|
1625
|
-
videoTransceiver = t;
|
|
1626
|
-
continue;
|
|
1627
|
-
}
|
|
1595
|
+
// Handle audio (and related changes, if any)
|
|
1596
|
+
if (!audioSend && !audioRecv) {
|
|
1597
|
+
// Audio disabled: have we removed it?
|
|
1598
|
+
if (audioTransceiver) {
|
|
1599
|
+
if (audioTransceiver.setDirection) {
|
|
1600
|
+
audioTransceiver.setDirection("inactive");
|
|
1601
|
+
} else {
|
|
1602
|
+
audioTransceiver.direction = "inactive";
|
|
1628
1603
|
}
|
|
1629
1604
|
}
|
|
1630
|
-
|
|
1631
|
-
//
|
|
1632
|
-
if (
|
|
1633
|
-
// Audio disabled: have we removed it?
|
|
1605
|
+
} else {
|
|
1606
|
+
// Take care of audio m-line
|
|
1607
|
+
if (audioSend && audioRecv) {
|
|
1634
1608
|
if (audioTransceiver) {
|
|
1635
1609
|
if (audioTransceiver.setDirection) {
|
|
1636
|
-
audioTransceiver.setDirection("
|
|
1610
|
+
audioTransceiver.setDirection("sendrecv");
|
|
1637
1611
|
} else {
|
|
1638
|
-
audioTransceiver.direction = "
|
|
1612
|
+
audioTransceiver.direction = "sendrecv";
|
|
1639
1613
|
}
|
|
1640
1614
|
}
|
|
1641
|
-
} else {
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
} else {
|
|
1648
|
-
audioTransceiver.direction = "sendrecv";
|
|
1649
|
-
}
|
|
1650
|
-
}
|
|
1651
|
-
} else if (audioSend && !audioRecv) {
|
|
1652
|
-
if (audioTransceiver) {
|
|
1653
|
-
if (audioTransceiver.setDirection) {
|
|
1654
|
-
audioTransceiver.setDirection("sendonly");
|
|
1655
|
-
} else {
|
|
1656
|
-
audioTransceiver.direction = "sendonly";
|
|
1657
|
-
}
|
|
1615
|
+
} else if (audioSend && !audioRecv) {
|
|
1616
|
+
if (audioTransceiver) {
|
|
1617
|
+
if (audioTransceiver.setDirection) {
|
|
1618
|
+
audioTransceiver.setDirection("sendonly");
|
|
1619
|
+
} else {
|
|
1620
|
+
audioTransceiver.direction = "sendonly";
|
|
1658
1621
|
}
|
|
1659
|
-
}
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
audioTransceiver.direction = "recvonly";
|
|
1665
|
-
}
|
|
1622
|
+
}
|
|
1623
|
+
} else if (!audioSend && audioRecv) {
|
|
1624
|
+
if (audioTransceiver) {
|
|
1625
|
+
if (audioTransceiver.setDirection) {
|
|
1626
|
+
audioTransceiver.setDirection("recvonly");
|
|
1666
1627
|
} else {
|
|
1667
|
-
|
|
1668
|
-
audioTransceiver = config.pc.addTransceiver("audio", {direction: "recvonly"});
|
|
1628
|
+
audioTransceiver.direction = "recvonly";
|
|
1669
1629
|
}
|
|
1630
|
+
} else {
|
|
1631
|
+
// In theory, this is the only case where we might not have a transceiver yet
|
|
1632
|
+
config.pc.addTransceiver("audio", {direction: "recvonly"});
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
// Handle video (and related changes, if any)
|
|
1637
|
+
if (!videoSend && !videoRecv) {
|
|
1638
|
+
if (videoTransceiver) {
|
|
1639
|
+
if (videoTransceiver.setDirection) {
|
|
1640
|
+
videoTransceiver.setDirection("inactive");
|
|
1641
|
+
} else {
|
|
1642
|
+
videoTransceiver.direction = "inactive";
|
|
1670
1643
|
}
|
|
1671
1644
|
}
|
|
1672
|
-
|
|
1673
|
-
|
|
1645
|
+
} else {
|
|
1646
|
+
// Take care of video m-line
|
|
1647
|
+
if (videoSend && videoRecv) {
|
|
1674
1648
|
if (videoTransceiver) {
|
|
1675
1649
|
if (videoTransceiver.setDirection) {
|
|
1676
|
-
videoTransceiver.setDirection("
|
|
1650
|
+
videoTransceiver.setDirection("sendrecv");
|
|
1677
1651
|
} else {
|
|
1678
|
-
videoTransceiver.direction = "
|
|
1652
|
+
videoTransceiver.direction = "sendrecv";
|
|
1679
1653
|
}
|
|
1680
1654
|
}
|
|
1681
|
-
} else {
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
} else {
|
|
1688
|
-
videoTransceiver.direction = "sendrecv";
|
|
1689
|
-
}
|
|
1690
|
-
}
|
|
1691
|
-
} else if (videoSend && !videoRecv) {
|
|
1692
|
-
if (videoTransceiver) {
|
|
1693
|
-
if (videoTransceiver.setDirection) {
|
|
1694
|
-
videoTransceiver.setDirection("sendonly");
|
|
1695
|
-
} else {
|
|
1696
|
-
videoTransceiver.direction = "sendonly";
|
|
1697
|
-
}
|
|
1655
|
+
} else if (videoSend && !videoRecv) {
|
|
1656
|
+
if (videoTransceiver) {
|
|
1657
|
+
if (videoTransceiver.setDirection) {
|
|
1658
|
+
videoTransceiver.setDirection("sendonly");
|
|
1659
|
+
} else {
|
|
1660
|
+
videoTransceiver.direction = "sendonly";
|
|
1698
1661
|
}
|
|
1699
|
-
}
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
videoTransceiver.direction = "recvonly";
|
|
1705
|
-
}
|
|
1662
|
+
}
|
|
1663
|
+
} else if (!videoSend && videoRecv) {
|
|
1664
|
+
if (videoTransceiver) {
|
|
1665
|
+
if (videoTransceiver.setDirection) {
|
|
1666
|
+
videoTransceiver.setDirection("recvonly");
|
|
1706
1667
|
} else {
|
|
1707
|
-
|
|
1708
|
-
videoTransceiver = config.pc.addTransceiver("video", {direction: "recvonly"});
|
|
1668
|
+
videoTransceiver.direction = "recvonly";
|
|
1709
1669
|
}
|
|
1670
|
+
} else {
|
|
1671
|
+
// In theory, this is the only case where we might not have a transceiver yet
|
|
1672
|
+
config.pc.addTransceiver("video", {direction: "recvonly"});
|
|
1710
1673
|
}
|
|
1711
1674
|
}
|
|
1712
|
-
}
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1713
1677
|
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
}
|
|
1725
|
-
};
|
|
1726
|
-
}
|
|
1678
|
+
_createAO(type = 'offer', handleId, iceRestart = false) {
|
|
1679
|
+
|
|
1680
|
+
let handle = this._getHandle(handleId);
|
|
1681
|
+
if (!handle) {
|
|
1682
|
+
return Promise.reject({
|
|
1683
|
+
type: 'warning',
|
|
1684
|
+
id: 15,
|
|
1685
|
+
message: 'id non-existent',
|
|
1686
|
+
data: [handleId, 'createAO', type]
|
|
1687
|
+
});
|
|
1727
1688
|
}
|
|
1728
1689
|
|
|
1690
|
+
let methodName = null;
|
|
1691
|
+
if (type === 'offer') {
|
|
1692
|
+
methodName = 'createOffer'
|
|
1693
|
+
} else {
|
|
1694
|
+
methodName = 'createAnswer'
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
let config = handle.webrtcStuff;
|
|
1698
|
+
let mediaConstraints = {};
|
|
1699
|
+
|
|
1729
1700
|
if (iceRestart) {
|
|
1730
1701
|
mediaConstraints["iceRestart"] = true;
|
|
1731
1702
|
}
|
|
@@ -1795,8 +1766,11 @@ class RoomSession {
|
|
|
1795
1766
|
}
|
|
1796
1767
|
config.candidates = [];
|
|
1797
1768
|
}
|
|
1769
|
+
|
|
1770
|
+
this._setupTransceivers(handleId, [false, true, false, true]);
|
|
1771
|
+
|
|
1798
1772
|
// Create the answer now
|
|
1799
|
-
return this._createAO('answer', handleId, false
|
|
1773
|
+
return this._createAO('answer', handleId, false)
|
|
1800
1774
|
.then(_jsep => {
|
|
1801
1775
|
if (!_jsep) {
|
|
1802
1776
|
this.emit('error', {
|
|
@@ -1827,7 +1801,7 @@ class RoomSession {
|
|
|
1827
1801
|
|
|
1828
1802
|
//Public methods
|
|
1829
1803
|
|
|
1830
|
-
publishLocal(stream
|
|
1804
|
+
publishLocal(stream = null) {
|
|
1831
1805
|
|
|
1832
1806
|
if(this.isDisconnecting || !this.isConnected) {
|
|
1833
1807
|
return Promise.reject({
|
|
@@ -1852,122 +1826,130 @@ class RoomSession {
|
|
|
1852
1826
|
this._webrtc(this.handleId);
|
|
1853
1827
|
|
|
1854
1828
|
let config = handle.webrtcStuff;
|
|
1829
|
+
let audioTrackReplacePromise = Promise.resolve();
|
|
1830
|
+
let videoTrackReplacePromise = Promise.resolve();
|
|
1855
1831
|
|
|
1856
|
-
if (stream) {
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
stream.getTracks().forEach(function (track) {
|
|
1860
|
-
config.pc.addTrack(track, stream);
|
|
1861
|
-
});
|
|
1862
|
-
|
|
1863
|
-
} else {
|
|
1864
|
-
|
|
1865
|
-
/* UPDATE Audio */
|
|
1866
|
-
|
|
1867
|
-
let replaceAudio = stream.getAudioTracks().length;
|
|
1832
|
+
if (!config.stream) {
|
|
1833
|
+
config.stream = stream;
|
|
1834
|
+
stream?.getTracks()?.forEach( (track) => {
|
|
1868
1835
|
|
|
1869
|
-
if
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1836
|
+
if(track.kind === 'audio' || !this.simulcast) {
|
|
1837
|
+
config.pc.addTrack(track, stream);
|
|
1838
|
+
}
|
|
1839
|
+
else {
|
|
1840
|
+
// adding simulcast streams
|
|
1841
|
+
let bitRates = this.simulcastBitrates;
|
|
1842
|
+
if(adapter.browserDetails.browser !== 'firefox') {
|
|
1843
|
+
// standard
|
|
1844
|
+
|
|
1845
|
+
config.pc.addTransceiver(track, {
|
|
1846
|
+
direction: 'sendonly',
|
|
1847
|
+
streams: [config.stream],
|
|
1848
|
+
sendEncodings: [
|
|
1849
|
+
{ rid: 'h', active: true, maxBitrate: bitRates.high },
|
|
1850
|
+
{ rid: 'm', active: true, maxBitrate: bitRates.medium, scaleResolutionDownBy: 2 },
|
|
1851
|
+
{ rid: 'l', active: true, maxBitrate: bitRates.low, scaleResolutionDownBy: 4 }
|
|
1852
|
+
]
|
|
1853
|
+
})
|
|
1854
|
+
}
|
|
1855
|
+
else {
|
|
1856
|
+
// firefox
|
|
1857
|
+
let transceiver = config.pc.addTransceiver(track, {
|
|
1858
|
+
direction: 'sendonly',
|
|
1859
|
+
streams: [config.stream]
|
|
1860
|
+
});
|
|
1861
|
+
let sender = transceiver ? transceiver.sender : null;
|
|
1862
|
+
if(sender) {
|
|
1863
|
+
let parameters = sender.getParameters() || {};
|
|
1864
|
+
parameters.encodings = track.sendEncodings || [
|
|
1865
|
+
{ rid: 'h', active: true, maxBitrate: bitRates.high },
|
|
1866
|
+
{ rid: 'm', active: true, maxBitrate: bitRates.medium, scaleResolutionDownBy: 2 },
|
|
1867
|
+
{ rid: 'l', active: true, maxBitrate: bitRates.low, scaleResolutionDownBy: 4 }
|
|
1868
|
+
];
|
|
1869
|
+
sender.setParameters(parameters);
|
|
1878
1870
|
}
|
|
1879
1871
|
}
|
|
1880
1872
|
}
|
|
1873
|
+
});
|
|
1881
1874
|
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1875
|
+
} else {
|
|
1876
|
+
|
|
1877
|
+
let transceivers = config.pc.getTransceivers();
|
|
1878
|
+
let audioTransceiver = null;
|
|
1879
|
+
let videoTransceiver = null;
|
|
1880
|
+
if (transceivers && transceivers.length > 0) {
|
|
1881
|
+
for (let i in transceivers) {
|
|
1882
|
+
let t = transceivers[i];
|
|
1883
|
+
if ((t.sender && t.sender.track && t.sender.track.kind === "audio") ||
|
|
1884
|
+
(t.receiver && t.receiver.track && t.receiver.track.kind === "audio")) {
|
|
1885
|
+
audioTransceiver = t;
|
|
1886
|
+
break;
|
|
1892
1887
|
}
|
|
1893
1888
|
}
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
if (transceivers && transceivers.length > 0) {
|
|
1901
|
-
for (let i in transceivers) {
|
|
1902
|
-
let t = transceivers[i];
|
|
1903
|
-
if ((t.sender && t.sender.track && t.sender.track.kind === "audio" && t.stopped === false) ||
|
|
1904
|
-
(t.receiver && t.receiver.track && t.receiver.track.kind === "audio" && t.stopped === false)) {
|
|
1905
|
-
audioTransceiver = t;
|
|
1906
|
-
break;
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
}
|
|
1889
|
+
for (let i in transceivers) {
|
|
1890
|
+
let t = transceivers[i];
|
|
1891
|
+
if ((t.sender && t.sender.track && t.sender.track.kind === "video") ||
|
|
1892
|
+
(t.receiver && t.receiver.track && t.receiver.track.kind === "video")) {
|
|
1893
|
+
videoTransceiver = t;
|
|
1894
|
+
break;
|
|
1910
1895
|
}
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1911
1898
|
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
} else {
|
|
1915
|
-
config.pc.addTrack(stream.getAudioTracks()[0], stream);
|
|
1916
|
-
}
|
|
1899
|
+
/* UPDATE Audio */
|
|
1900
|
+
// stopping existing tracks
|
|
1917
1901
|
|
|
1902
|
+
let oldAudioStream = config?.stream?.getAudioTracks()?.[0];
|
|
1903
|
+
if (oldAudioStream) {
|
|
1904
|
+
config.stream.removeTrack(oldAudioStream);
|
|
1905
|
+
try {
|
|
1906
|
+
oldAudioStream.stop();
|
|
1907
|
+
} catch (e) {
|
|
1908
|
+
this._log(e);
|
|
1918
1909
|
}
|
|
1910
|
+
}
|
|
1919
1911
|
|
|
1920
|
-
|
|
1912
|
+
let replaceAudio = stream?.getAudioTracks()?.length;
|
|
1913
|
+
if (replaceAudio) {
|
|
1914
|
+
config.stream.addTrack(stream.getAudioTracks()[0]);
|
|
1915
|
+
if (audioTransceiver && audioTransceiver.sender) {
|
|
1916
|
+
audioTrackReplacePromise = audioTransceiver.sender.replaceTrack(stream.getAudioTracks()[0]);
|
|
1917
|
+
} else {
|
|
1918
|
+
config.pc.addTrack(stream.getAudioTracks()[0], stream);
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
else {
|
|
1922
|
+
if (audioTransceiver && audioTransceiver.sender) {
|
|
1923
|
+
audioTrackReplacePromise = audioTransceiver.sender.replaceTrack(null);
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1921
1926
|
|
|
1922
|
-
|
|
1927
|
+
/* UPDATE Video */
|
|
1923
1928
|
|
|
1924
|
-
|
|
1925
|
-
let oldVideoStream = config.stream.getVideoTracks()[0];
|
|
1926
|
-
if (oldVideoStream) {
|
|
1927
|
-
config.stream.removeTrack(oldVideoStream);
|
|
1928
|
-
try {
|
|
1929
|
-
oldVideoStream.stop();
|
|
1930
|
-
} catch (e) {
|
|
1931
|
-
this._log(e);
|
|
1932
|
-
}
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1929
|
+
// stopping existing tracks
|
|
1935
1930
|
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
config.pc.removeTrack(s);
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
}
|
|
1931
|
+
let oldVideoStream = config?.stream?.getVideoTracks()?.[0];
|
|
1932
|
+
if (oldVideoStream) {
|
|
1933
|
+
config.stream.removeTrack(oldVideoStream);
|
|
1934
|
+
try {
|
|
1935
|
+
oldVideoStream.stop();
|
|
1936
|
+
} catch (e) {
|
|
1937
|
+
this._log(e);
|
|
1947
1938
|
}
|
|
1939
|
+
}
|
|
1948
1940
|
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
}
|
|
1962
|
-
}
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1965
|
-
if (videoTransceiver && videoTransceiver.sender) {
|
|
1966
|
-
//TODO: check if t.stopped === false still gets us videoTransceiver
|
|
1967
|
-
videoTransceiver.sender.replaceTrack(stream.getVideoTracks()[0]);
|
|
1968
|
-
} else {
|
|
1969
|
-
config.pc.addTrack(stream.getVideoTracks()[0], stream);
|
|
1970
|
-
}
|
|
1941
|
+
let replaceVideo = stream?.getVideoTracks()?.length;
|
|
1942
|
+
if (replaceVideo) {
|
|
1943
|
+
config.stream.addTrack(stream.getVideoTracks()[0]);
|
|
1944
|
+
if (videoTransceiver && videoTransceiver.sender) {
|
|
1945
|
+
videoTrackReplacePromise = videoTransceiver.sender.replaceTrack(stream.getVideoTracks()[0]);
|
|
1946
|
+
} else {
|
|
1947
|
+
config.pc.addTrack(stream.getVideoTracks()[0], stream);
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
else {
|
|
1951
|
+
if (videoTransceiver && videoTransceiver.sender) {
|
|
1952
|
+
videoTrackReplacePromise = videoTransceiver.sender.replaceTrack(null);
|
|
1971
1953
|
}
|
|
1972
1954
|
}
|
|
1973
1955
|
}
|
|
@@ -1982,7 +1964,16 @@ class RoomSession {
|
|
|
1982
1964
|
this.isAudioMuted = isAudioMuted;
|
|
1983
1965
|
this.isVideoMuted = isVideoMuted;
|
|
1984
1966
|
|
|
1985
|
-
|
|
1967
|
+
this._setupTransceivers(this.handleId, [hasAudio, false, hasVideo, false]);
|
|
1968
|
+
|
|
1969
|
+
// this should be enough
|
|
1970
|
+
if(this.isPublished) {
|
|
1971
|
+
return Promise.resolve();
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
return Promise
|
|
1975
|
+
.all([audioTrackReplacePromise, videoTrackReplacePromise])
|
|
1976
|
+
.then(() => this._createAO('offer', this.handleId, false))
|
|
1986
1977
|
.then((jsep) => {
|
|
1987
1978
|
if (!jsep) {
|
|
1988
1979
|
return null;
|
|
@@ -2117,20 +2108,24 @@ class RoomSession {
|
|
|
2117
2108
|
return Promise.reject({type: 'error', id: 21, message: 'no local id, connect first', data: null})
|
|
2118
2109
|
}
|
|
2119
2110
|
let config = handle.webrtcStuff;
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
this.isAudioMuted = !transceiver || !transceiver.sender.track.enabled;
|
|
2127
|
-
} else {
|
|
2128
|
-
if (config.stream && config.stream.getAudioTracks().length) {
|
|
2129
|
-
config.stream.getAudioTracks()[0].enabled = value !== null ? !!value : !config.stream.getAudioTracks()[0].enabled;
|
|
2130
|
-
}
|
|
2131
|
-
this.isAudioMuted = config.stream.getAudioTracks().length === 0 || !config.stream.getAudioTracks()[0].enabled;
|
|
2111
|
+
|
|
2112
|
+
let transceiver = config.pc.getTransceivers()
|
|
2113
|
+
.find(t => t.sender && t.sender.track && t.receiver.track.kind === "audio" && (mid ? t.mid === mid : true));
|
|
2114
|
+
|
|
2115
|
+
if (transceiver) {
|
|
2116
|
+
transceiver.sender.track.enabled = value !== null ? !!value : !transceiver.sender.track.enabled;
|
|
2132
2117
|
}
|
|
2118
|
+
|
|
2119
|
+
this.isAudioMuted = !transceiver || !transceiver.sender.track.enabled;
|
|
2120
|
+
|
|
2121
|
+
// if (config.stream && config.stream.getAudioTracks().length) {
|
|
2122
|
+
// config.stream.getAudioTracks()[0].enabled = value !== null ? !!value : !config.stream.getAudioTracks()[0].enabled;
|
|
2123
|
+
// }
|
|
2124
|
+
// this.isAudioMuted = config.stream.getAudioTracks().length === 0 || !config.stream.getAudioTracks()[0].enabled;
|
|
2125
|
+
//
|
|
2126
|
+
|
|
2133
2127
|
this.emit('localMuted', {type: 'audio', value: this.isAudioMuted, mid});
|
|
2128
|
+
|
|
2134
2129
|
}
|
|
2135
2130
|
|
|
2136
2131
|
toggleVideo(value = null, mid) {
|
|
@@ -2140,28 +2135,37 @@ class RoomSession {
|
|
|
2140
2135
|
}
|
|
2141
2136
|
let config = handle.webrtcStuff;
|
|
2142
2137
|
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
transceiver.sender.track.enabled = value !== null ? !!value : !transceiver.sender.track.enabled;
|
|
2148
|
-
}
|
|
2149
|
-
this.isVideoMuted = !transceiver || !transceiver.sender.track.enabled;
|
|
2150
|
-
}
|
|
2151
|
-
else {
|
|
2152
|
-
if (config.stream && config.stream.getVideoTracks().length) {
|
|
2153
|
-
config.stream.getVideoTracks()[0].enabled = value !== null ? !!value : !config.stream.getVideoTracks()[0].enabled;
|
|
2154
|
-
}
|
|
2155
|
-
this.isVideoMuted = config.stream.getVideoTracks().length === 0 || !config.stream.getVideoTracks()[0].enabled;
|
|
2138
|
+
let transceiver = config.pc.getTransceivers()
|
|
2139
|
+
.find(t => t.sender && t.sender.track && t.receiver.track.kind === "video" && (mid ? t.mid === mid : true));
|
|
2140
|
+
if (transceiver) {
|
|
2141
|
+
transceiver.sender.track.enabled = value !== null ? !!value : !transceiver.sender.track.enabled;
|
|
2156
2142
|
}
|
|
2143
|
+
|
|
2144
|
+
this.isVideoMuted = !transceiver || !transceiver.sender.track.enabled;
|
|
2145
|
+
|
|
2146
|
+
// if (config.stream && config.stream.getVideoTracks().length) {
|
|
2147
|
+
// config.stream.getVideoTracks()[0].enabled = value !== null ? !!value : !config.stream.getVideoTracks()[0].enabled;
|
|
2148
|
+
// }
|
|
2149
|
+
// this.isVideoMuted = config.stream.getVideoTracks().length === 0 || !config.stream.getVideoTracks()[0].enabled;
|
|
2150
|
+
|
|
2157
2151
|
this.emit('localMuted', {type: 'video', value: this.isVideoMuted, mid});
|
|
2158
2152
|
}
|
|
2159
2153
|
|
|
2154
|
+
selectSubStream(handleId, substream = 2) {
|
|
2155
|
+
this.sendMessage(this.handleId, {
|
|
2156
|
+
"body": {
|
|
2157
|
+
"request": "configure",
|
|
2158
|
+
"substream": substream
|
|
2159
|
+
}
|
|
2160
|
+
}).catch(() => null)
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2160
2163
|
setRoomType(type = 'watchparty') {
|
|
2161
2164
|
this._roomType = type;
|
|
2162
2165
|
return this._roomType;
|
|
2163
2166
|
}
|
|
2164
2167
|
|
|
2168
|
+
|
|
2165
2169
|
}
|
|
2166
2170
|
|
|
2167
2171
|
export default Room;
|