@reactoo/watchtogether-sdk-js 2.8.0-beta.4 → 2.8.0-beta.6

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.
@@ -576,6 +576,10 @@
576
576
  Instance.room.getSessionByConstructId(constructId).setRestrictSubscribeToUserIds(userIds)
577
577
  }
578
578
 
579
+ window.restart = function () {
580
+ Instance.room.getSessionByConstructId(constructId).restart()
581
+ }
582
+
579
583
 
580
584
  </script>
581
585
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactoo/watchtogether-sdk-js",
3
- "version": "2.8.0-beta.4",
3
+ "version": "2.8.0-beta.6",
4
4
  "description": "Javascript SDK for Reactoo",
5
5
  "main": "dist/watchtogether-sdk.min.js",
6
6
  "module": "dist/watchtogether-sdk.min.js",
@@ -156,22 +156,24 @@ let roomSession = function ({roomId, pinHash, role, options = {}}, room, wt) {
156
156
  room.isRestarting = true;
157
157
 
158
158
  let wasPublished = room.isPublished;
159
- let handle = room._getHandle(room.handleId);
160
- let stream = null;
161
- if (handle?.webrtcStuff?.stream && wasPublished) {
162
- stream = handle.webrtcStuff.stream;
163
- }
159
+ let streams = room.getLocalStreams();
164
160
 
165
161
  return this.disconnect()
166
162
  .then(() => wait(1000)) //TODO: remove 1000ms wait by waiting for proper events from janus
167
163
  .then(() => this.connect({reactooRoomId}))
168
164
  .then(() => {
169
- if (isObserver) {
165
+ if(streams.length) {
166
+ return streams.reduce((promise, stream) => {
167
+ return promise.then(() => {
168
+ return this.publishLocal(stream.stream, stream.source);
169
+ });
170
+ }, Promise.resolve())
171
+
172
+ } else if (wasPublished) {
170
173
  return this.publishLocal(null);
171
- } else if (stream) {
172
- return this.publishLocal(stream);
173
- } else
174
+ } else {
174
175
  return Promise.resolve()
176
+ }
175
177
  })
176
178
  .then(() => {
177
179
  room.isRestarting = false;
@@ -278,6 +278,7 @@ class RoomSession {
278
278
  // helper flags
279
279
 
280
280
  this.isSupposeToBeConnected = false;
281
+ this.isRestarting = false; // used from outside
281
282
  this.isConnecting = false;
282
283
  this.isEstablishingConnection = false;
283
284
  this.isDisconnecting = false;
@@ -800,7 +801,7 @@ class RoomSession {
800
801
  // feed_id === id of participant
801
802
 
802
803
  #updateTransceiverMap(handleId, streams = []) {
803
- this._log('Updating current transceiver map', 'Is me: ' + handleId === this.#publisherHandle.handleId, handleId, streams);
804
+ this._log('Updating current transceiver map', 'Is me: ' + handleId === this.#publisherHandle?.handleId, handleId, streams);
804
805
  let handle = this.#getHandle(handleId);
805
806
  if (!handle) {
806
807
  this.emit('error', {
@@ -1131,12 +1132,12 @@ class RoomSession {
1131
1132
  } else if (type === "webrtcup") {
1132
1133
  //none universal
1133
1134
  } else if (type === "hangup") {
1134
- this._log('hangup on', handle.handleId, handle.handleId === this.#publisherHandle.handleId, json);
1135
+ this._log('hangup on', handle.handleId, handle.handleId === this.handleId, json);
1135
1136
  if(this.#getHandle(handle.handleId)) {
1136
1137
  this.#cleanupHandle(handle.handleId, true).catch(() => {});
1137
1138
  }
1138
1139
  } else if (type === "detached") {
1139
- this._log('detached on', handle.handleId, handle.handleId === this.#publisherHandle.handleId, json);
1140
+ this._log('detached on', handle.handleId, handle.handleId === this.handleId, json);
1140
1141
  if(this.#getHandle(handle.handleId)) {
1141
1142
  this.#destroyHandle(handle.handleId).catch(() => {});
1142
1143
  }
@@ -1158,7 +1159,7 @@ class RoomSession {
1158
1159
 
1159
1160
  // LOCAL
1160
1161
 
1161
- if (sender === this.#publisherHandle.handleId) {
1162
+ if (sender === this.#publisherHandle?.handleId) {
1162
1163
  if (type === "event") {
1163
1164
 
1164
1165
  var plugindata = json["plugindata"] || {};
@@ -1229,7 +1230,7 @@ class RoomSession {
1229
1230
 
1230
1231
 
1231
1232
  if (leaving === 'ok') {
1232
- this._log('leaving', this.#publisherHandle.handleId, 'this is us');
1233
+ this._log('leaving', this.#publisherHandle?.handleId, 'this is us');
1233
1234
 
1234
1235
  this.#emitLocalFeedUpdate({feedRemoval: true});
1235
1236
 
@@ -1251,8 +1252,8 @@ class RoomSession {
1251
1252
  }
1252
1253
 
1253
1254
  if (unpublished === 'ok') {
1254
- this._log('unpublished', this.#publisherHandle.handleId, 'this is us');
1255
- this.#cleanupHandle(this.#publisherHandle.handleId, true).catch(() => {});
1255
+ this._log('unpublished', this.#publisherHandle?.handleId, 'this is us');
1256
+ this.#cleanupHandle(this.#publisherHandle?.handleId, true).catch(() => {});
1256
1257
 
1257
1258
  } else if (unpublished) {
1258
1259
  this._log('unpublished', unpublished);
@@ -1290,7 +1291,7 @@ class RoomSession {
1290
1291
  }
1291
1292
 
1292
1293
  if (jsep !== undefined && jsep !== null) {
1293
- this.#webrtcPeer(this.#publisherHandle.handleId, jsep)
1294
+ this.#webrtcPeer(this.#publisherHandle?.handleId, jsep)
1294
1295
  .catch(err => {
1295
1296
  this.emit('error', err);
1296
1297
  });
@@ -1304,7 +1305,7 @@ class RoomSession {
1304
1305
 
1305
1306
  this._log('Configuring bitrate: ' + this.initialBitrate);
1306
1307
  if (this.initialBitrate > 0) {
1307
- this.sendMessage(this.#publisherHandle.handleId, {
1308
+ this.sendMessage(this.#publisherHandle?.handleId, {
1308
1309
  "body": {
1309
1310
  "request": "configure",
1310
1311
  "bitrate": this.initialBitrate
@@ -1379,7 +1380,9 @@ class RoomSession {
1379
1380
  config.dataChannelOpen = this.defaultDataChannelLabel === data?.label && data?.state === 'open';
1380
1381
  }
1381
1382
 
1382
- if (handleId === this.#publisherHandle.handleId && this.defaultDataChannelLabel === data?.label) {
1383
+
1384
+
1385
+ if (handleId === this.handleId && this.defaultDataChannelLabel === data?.label) {
1383
1386
  this._isDataChannelOpen = data?.state === 'open';
1384
1387
  this.emit('dataChannel', data?.state === 'open');
1385
1388
  }
@@ -1400,13 +1403,13 @@ class RoomSession {
1400
1403
  config.dataChannelOpen = false;
1401
1404
  }
1402
1405
  }
1403
- if (handleId === this.#publisherHandle.handleId && this.defaultDataChannelLabel === data.label) {
1406
+ if (handleId === this.handleId && this.defaultDataChannelLabel === data.label) {
1404
1407
  this._isDataChannelOpen = false;
1405
1408
  this.emit('dataChannel', false);
1406
1409
  }
1407
1410
  }
1408
1411
 
1409
- if (handleId === this.#publisherHandle.handleId && type === 'message') {
1412
+ if (handleId === this.handleId && type === 'message') {
1410
1413
 
1411
1414
  let d = null;
1412
1415
 
@@ -1490,18 +1493,24 @@ class RoomSession {
1490
1493
 
1491
1494
  try {
1492
1495
  if (handle.webrtcStuff.stream) {
1493
- if(!this.isConnecting) {
1494
- handle.webrtcStuff.stream?.getTracks().forEach(track => track.stop());
1496
+
1497
+ if(this.isRestarting && handleId === this.handleId) {
1498
+ handle.webrtcStuff.stream?.getTracks().forEach(track => track.onended = null);
1495
1499
  }
1496
1500
  else {
1497
- handle.webrtcStuff.stream?.getTracks().forEach(track => track.onended = null);
1501
+ handle.webrtcStuff.stream?.getTracks().forEach(track => track.stop());
1498
1502
  }
1503
+
1499
1504
  }
1500
1505
  if(handle.webrtcStuff?.tracks?.length > 0) {
1501
1506
  handle.webrtcStuff.tracks.forEach(track => {
1502
1507
  if (track) {
1503
- track.stop();
1504
- track.onended = null;
1508
+ if(this.isRestarting && handleId === this.handleId) {
1509
+ track.onended = null;
1510
+ }
1511
+ else {
1512
+ track.stop();
1513
+ }
1505
1514
  }
1506
1515
  });
1507
1516
  }
@@ -1558,7 +1567,7 @@ class RoomSession {
1558
1567
  lastSwitchTime : new Map(),
1559
1568
  }
1560
1569
 
1561
- if(this.#publisherHandle && handleId === this.#publisherHandle.handleId) {
1570
+ if(this.#publisherHandle && handleId === this.#publisherHandle?.handleId) {
1562
1571
  this.#emitLocalFeedUpdate({feedRemoval: true});
1563
1572
  }
1564
1573
  else if(this.#subscriberHandle && handleId === this.#subscriberHandle.handleId) {
@@ -1571,7 +1580,7 @@ class RoomSession {
1571
1580
  }
1572
1581
 
1573
1582
  async #joinAsPublisher(roomId, pin, userId, display) {
1574
- return this.sendMessage(this.#publisherHandle.handleId, {
1583
+ return this.sendMessage(this.#publisherHandle?.handleId, {
1575
1584
  body: {
1576
1585
  "request": "join", "room": roomId, "pin": pin, "ptype": "publisher", "display": display, ...(this.webrtcVersion > 1000 ? {id: userId} : {})
1577
1586
  }
@@ -1658,7 +1667,7 @@ class RoomSession {
1658
1667
 
1659
1668
  async #leaveRoom(dontWait = false) {
1660
1669
  return this.isConnected
1661
- ? this.sendMessage(this.#publisherHandle.handleId, {body: {"request": "leave"}}, dontWait)
1670
+ ? this.sendMessage(this.#publisherHandle?.handleId, {body: {"request": "leave"}}, dontWait)
1662
1671
  .finally(() => {
1663
1672
  this.isConnected = false;
1664
1673
  this.emit('joined', false);
@@ -1992,6 +2001,27 @@ class RoomSession {
1992
2001
  });
1993
2002
  }
1994
2003
 
2004
+ getLocalStreams() {
2005
+ const streamMap = this.#publisherHandle?.webrtcStuff?.streamMap[this.id];
2006
+ if(!streamMap) {
2007
+ return [];
2008
+ }
2009
+ return Object.keys(streamMap).reduce((acc, source) => {
2010
+ const sourceTrackIds = streamMap[source] ?? [];
2011
+ const sourceRelatedTracks = this.#publisherHandle?.webrtcStuff?.tracks?.filter(t => sourceTrackIds.includes(t.id)) ?? [];
2012
+ if(sourceRelatedTracks.length) {
2013
+ const stream = new MediaStream();
2014
+ sourceRelatedTracks.forEach(track => {
2015
+ if(track) {
2016
+ stream.addTrack(track);
2017
+ }
2018
+ });
2019
+ acc.push({source, stream});
2020
+ }
2021
+ return acc
2022
+ }, [])
2023
+ }
2024
+
1995
2025
  #enableDebug() {
1996
2026
  this._log = console.log.bind(console);
1997
2027
  }
@@ -2382,7 +2412,7 @@ class RoomSession {
2382
2412
  // removing this so we can cache ice candidates again
2383
2413
  config.remoteSdp = null;
2384
2414
 
2385
- if (this.#publisherHandle.handleId === handleId) {
2415
+ if (this.handleId === handleId) {
2386
2416
  this._log('Performing local ICE restart');
2387
2417
  let hasAudio = !!(config.stream && config.stream.getAudioTracks().length > 0);
2388
2418
  let hasVideo = !!(config.stream && config.stream.getVideoTracks().length > 0);
@@ -2531,7 +2561,7 @@ class RoomSession {
2531
2561
  .then( (response) => {
2532
2562
 
2533
2563
  // if type offer and its me and we want dtx we mungle the sdp
2534
- if(handleId === this.#publisherHandle.handleId && type === 'offer' && this.enableDtx) {
2564
+ if(handleId === this.handleId && type === 'offer' && this.enableDtx) {
2535
2565
  // enable DTX
2536
2566
  response.sdp = response.sdp.replace("useinbandfec=1", "useinbandfec=1;usedtx=1")
2537
2567
  }
@@ -2841,7 +2871,7 @@ class RoomSession {
2841
2871
  let hasAudio = !!(stream && stream.getAudioTracks().length > 0);
2842
2872
  let hasVideo = !!(stream && stream.getVideoTracks().length > 0);
2843
2873
 
2844
- this.#setupTransceivers(this.#publisherHandle.handleId, [hasAudio, false, hasVideo, false, audioTransceiver, videoTransceiver]);
2874
+ this.#setupTransceivers(this.handleId, [hasAudio, false, hasVideo, false, audioTransceiver, videoTransceiver]);
2845
2875
 
2846
2876
  const emitEvents = () => {
2847
2877
  this.isPublished = true;
@@ -2950,7 +2980,7 @@ class RoomSession {
2950
2980
 
2951
2981
  async unpublishLocal(dontWait = false) {
2952
2982
  return this.isPublished
2953
- ? this.sendMessage(this.#publisherHandle.handleId, {body: {"request": "unpublish"}}, dontWait)
2983
+ ? this.sendMessage(this.handleId, {body: {"request": "unpublish"}}, dontWait)
2954
2984
  .finally(r => {
2955
2985
  this.isPublished = false;
2956
2986
  this.emit('published', false);
@@ -3293,6 +3323,9 @@ class RoomSession {
3293
3323
  const display = transceiverData?.feed_display ?? null;
3294
3324
  const description = transceiverData.feed_description ?? null;
3295
3325
 
3326
+ const currentLayer = handle.webrtcStuff?.currentLayers?.get(mid);
3327
+ const currentSubstream = currentLayer.substream;
3328
+
3296
3329
  return handle.webrtcStuff.pc.getStats(track)
3297
3330
  .then(stats => {
3298
3331
 
@@ -3310,6 +3343,7 @@ class RoomSession {
3310
3343
  frameRate: 0,
3311
3344
  freezeCount: 0,
3312
3345
  totalFreezesDuration: 0,
3346
+ selectedSubstream: currentSubstream,
3313
3347
  };
3314
3348
 
3315
3349
  let selectedCandidatePairId = null;
@@ -3645,7 +3679,8 @@ class RoomSession {
3645
3679
  jitter,
3646
3680
  packetLoss,
3647
3681
  rtt,
3648
- totalFreezesDuration
3682
+ totalFreezesDuration,
3683
+ selectedSubstream
3649
3684
  } = stat.parsedStats;
3650
3685
 
3651
3686
  let description = {};
@@ -3667,7 +3702,8 @@ class RoomSession {
3667
3702
  jitter,
3668
3703
  packetLoss,
3669
3704
  rtt,
3670
- totalFreezesDuration
3705
+ totalFreezesDuration,
3706
+ selectedSubstream
3671
3707
  }
3672
3708
  }
3673
3709
  });