@reactoo/watchtogether-sdk-js 2.7.38 → 2.7.40

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.
@@ -32,8 +32,8 @@
32
32
 
33
33
  //https://studio.reactoo.com/room/edf441b3-7415-49c4-9557-273cb93bc746/LJj4W2Cz-nG3U-lb0R-TAaY-o7Thmb8xHSbE
34
34
 
35
- let roomId = "c22ada04-6c95-4524-91d8-e915bcef2e61"; // It will create room automatically if not set
36
- let pinHash = "OayoOVzK-XmWr-BTID-fVwH-eH44Tn3xSWeR";// '967ca05f-7fab-a205-5913-39393bbbe923';
35
+ let roomId = "d841ad58-e5a6-4cb8-aeb8-c92499a213a4"; // It will create room automatically if not set
36
+ let pinHash = null;
37
37
 
38
38
  let participants = document.querySelector('.participants');
39
39
  var video = document.querySelector('.contentVideo');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactoo/watchtogether-sdk-js",
3
- "version": "2.7.38",
3
+ "version": "2.7.40",
4
4
  "description": "Javascript SDK for Reactoo",
5
5
  "main": "src/index.js",
6
6
  "unpkg": "dist/watchtogether-sdk.min.js",
@@ -280,7 +280,11 @@ class Iot {
280
280
  }
281
281
 
282
282
  // Find a suitable topic for the connection check
283
- const suitableTopic = Array.from(this.subscribedTopics).find(topic => topic.indexOf('user') > -1);
283
+ let suitableTopic = Array.from(this.subscribedTopics).find(topic => topic.indexOf('user') > -1);
284
+
285
+ if(!suitableTopic) {
286
+ suitableTopic = Array.from(this.subscribedTopics).find(topic => topic.indexOf('room') > -1 && topic !== 'wt/instanceroom/reactooDemo');
287
+ }
284
288
 
285
289
  if (!suitableTopic) {
286
290
  reject(new Error('No suitable topic found for connection check'));
@@ -323,7 +327,12 @@ class Iot {
323
327
  return;
324
328
  }
325
329
  // Find a suitable topic for the connection check
326
- const suitableTopic = Array.from(this.subscribedTopics).find(topic => topic.indexOf('user') > -1);
330
+ let suitableTopic = Array.from(this.subscribedTopics).find(topic => topic.indexOf('user') > -1);
331
+
332
+ if(!suitableTopic) {
333
+ suitableTopic = Array.from(this.subscribedTopics).find(topic => topic.indexOf('room') > -1 && topic !== 'wt/instanceroom/reactooDemo');
334
+ }
335
+
327
336
  if (!suitableTopic) {
328
337
  this.log('No suitable topic found for keep alive message');
329
338
  return;
@@ -1700,14 +1700,14 @@ class RoomSession {
1700
1700
  let directionDecision = 0;
1701
1701
  if(p.webrtcStuff?.stats?.[mid]?.length > this._upStatsLength) {
1702
1702
  const upMedianStats = this._calculateMedianStats(p.webrtcStuff.stats[mid].slice(this._upStatsLength * -1));
1703
- if(upMedianStats?.framesPerSecond >= Math.floor((settingsForCurrentSubstream?.maxFramerate || 30) * 0.7) && upMedianStats?.freezeDurationSinceLast < (this._upStatsLength * this._statsInterval * 0.33) / 1000 /* && upMedianStats?.freezeCountSinceLast < 3 */) {
1703
+ if(upMedianStats?.freezeDurationSinceLast < (this._upStatsLength * this._statsInterval * 0.33) / 1000 /* && upMedianStats?.freezeCountSinceLast < 3 */) {
1704
1704
  directionDecision = 1;
1705
1705
  }
1706
1706
  }
1707
1707
 
1708
1708
  if(p.webrtcStuff?.stats?.[mid]?.length > this._downStatsLength) {
1709
1709
  const downMedianStats = this._calculateMedianStats(p.webrtcStuff.stats[mid].slice(this._downStatsLength * -1));
1710
- if(downMedianStats?.framesPerSecond < Math.floor((settingsForCurrentSubstream?.maxFramerate || 30) * 0.7) || downMedianStats?.freezeDurationSinceLast > (this._downStatsLength * this._statsInterval * 0.33) / 1000 /* || downMedianStats?.freezeCountSinceLast > 5 || downMedianStats?.jitter > maxJitter(settingsForCurrentSubstream.maxFramerate) */) {
1710
+ if(downMedianStats?.freezeDurationSinceLast > (this._downStatsLength * this._statsInterval * 0.33) / 1000 /* || downMedianStats?.freezeCountSinceLast > 5 || downMedianStats?.jitter > maxJitter(settingsForCurrentSubstream.maxFramerate) */) {
1711
1711
  directionDecision = -1;
1712
1712
  }
1713
1713
  }
@@ -2127,10 +2127,6 @@ class RoomSession {
2127
2127
  });
2128
2128
  };
2129
2129
 
2130
- let mutedTimerId = {};
2131
- let waitPeriod = 300; // ms
2132
- let screenShareWaitPeriod = 5000; // ms
2133
-
2134
2130
  event.track.onmute = (ev) => {
2135
2131
  this._log('Remote track muted');
2136
2132
 
@@ -2153,35 +2149,6 @@ class RoomSession {
2153
2149
  muted: true
2154
2150
  });
2155
2151
 
2156
- // when a track is muted, we try to switch to lower quality substream, but not for screen sharing
2157
-
2158
- if(!this.simulcast) {
2159
- return;
2160
- }
2161
-
2162
- const wPeriod = source.indexOf('screen') > -1 ? screenShareWaitPeriod : waitPeriod;
2163
-
2164
- if(!mutedTimerId[mid]) {
2165
- mutedTimerId[mid] = setTimeout(() => {
2166
- mutedTimerId[mid] = null;
2167
- const simulcastConfigForSource = this._findSimulcastConfig(source, this.simulcastSettings);
2168
- const simulcastMode = handle.webrtcStuff?.overriddenSimulcastMode[mid]?.mode || simulcastConfigForSource?.mode;
2169
- const {simulcastBitrates} = handle.webrtcStuff.tracksMap.find(t => t.mid === mid) || {};
2170
-
2171
- // track is gone
2172
- if(!simulcastBitrates) {
2173
- return;
2174
- }
2175
-
2176
- const currentSubstream = handle.webrtcStuff.selectedSubstream[mid];
2177
- if(!(simulcastMode === 'browserControlled') && ev.target.kind === 'video' && currentSubstream < simulcastBitrates.length - 1) {
2178
- this._log('Attempting to down the quality due to track muted');
2179
- this.selectSubStream(handle.handleId, currentSubstream + 1, undefined, mid, false)
2180
- .catch((reason) => this._log(`Changing substream for mid: ${mid} failed. Reason: ${reason}`));
2181
- }
2182
- }, wPeriod);
2183
- }
2184
-
2185
2152
  };
2186
2153
 
2187
2154
  event.track.onunmute = (ev) => {
@@ -2192,11 +2159,6 @@ class RoomSession {
2192
2159
  let mid = transceiver.mid || ev.target.id;
2193
2160
  let source = Object.keys(config.streamMap).find(key => config.streamMap[key].includes(ev.target.id));
2194
2161
 
2195
- if(mutedTimerId[mid]) {
2196
- clearTimeout(mutedTimerId[mid]);
2197
- mutedTimerId[mid] = null;
2198
- }
2199
-
2200
2162
  this.emit('remoteTrackMuted', {
2201
2163
  id: handle.handleId,
2202
2164
  mid,
@@ -2349,7 +2311,6 @@ class RoomSession {
2349
2311
  config.isIceRestarting = false;
2350
2312
  });
2351
2313
  }
2352
-
2353
2314
  }
2354
2315
 
2355
2316
  _setupTransceivers(handleId, [audioSend, audioRecv, videoSend, videoRecv, audioTransceiver = null, videoTransceiver = null]) {
@@ -2507,6 +2468,77 @@ class RoomSession {
2507
2468
 
2508
2469
  }
2509
2470
 
2471
+ _addSimulcastToSDP(sdp) {
2472
+ // Split SDP into lines
2473
+ let sdpLines = sdp.split('\n');
2474
+
2475
+ // Find the index of the video m-line
2476
+ let videoIndex = sdpLines.findIndex(line => line.startsWith('m=video'));
2477
+ if (videoIndex === -1) {
2478
+ // No video m-line found
2479
+ return sdp;
2480
+ }
2481
+
2482
+ // We need to insert the lines after the mid attribute
2483
+ // Find the index of the 'a=mid' line in the video section
2484
+ let midIndex = sdpLines.findIndex((line, index) =>
2485
+ index > videoIndex && line.startsWith('a=mid:')
2486
+ );
2487
+
2488
+ if (midIndex === -1) {
2489
+ // No 'a=mid' line found in video m-section
2490
+ return sdp;
2491
+ }
2492
+
2493
+ // Prepare the simulcast attributes
2494
+ const simulcastLines = [
2495
+ 'a=rid:l recv',
2496
+ 'a=rid:m recv',
2497
+ 'a=rid:h recv',
2498
+ 'a=simulcast:recv l;m;h'
2499
+ ];
2500
+
2501
+ // Prepare the extmap attributes for RID and Repaired RID
2502
+ const extmapId = sdpLines.reduce((maxId, line) => {
2503
+ const match = line.match(/a=extmap:(\d+)/);
2504
+ return match ? Math.max(maxId, parseInt(match[1])) : maxId;
2505
+ }, 0);
2506
+
2507
+ const extmapLines = [
2508
+ `a=extmap:${extmapId + 1} urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id`,
2509
+ `a=extmap:${extmapId + 2} urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id`
2510
+ ];
2511
+
2512
+ // Insert the extmap lines after the last existing extmap in the video section
2513
+ let lastExtmapIndex = midIndex;
2514
+ for (let i = midIndex + 1; i < sdpLines.length; i++) {
2515
+ if (sdpLines[i].startsWith('a=extmap:')) {
2516
+ lastExtmapIndex = i;
2517
+ } else if (sdpLines[i].startsWith('a=')) {
2518
+ // Reached another attribute
2519
+ break;
2520
+ }
2521
+ }
2522
+
2523
+ // Check if the attributes are already present
2524
+ const hasSimulcast = sdpLines.some(line => line.startsWith('a=simulcast'));
2525
+ const hasRidExtmap = sdpLines.some(line => line.includes('urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id'));
2526
+
2527
+ if (!hasRidExtmap) {
2528
+ // Insert the extmap lines
2529
+ sdpLines.splice(lastExtmapIndex + 1, 0, ...extmapLines);
2530
+ }
2531
+
2532
+ if (!hasSimulcast) {
2533
+ // Insert the simulcast lines after the 'a=mid' line
2534
+ sdpLines.splice(midIndex + 1, 0, ...simulcastLines);
2535
+ }
2536
+
2537
+ // Return the modified SDP
2538
+ return sdpLines.join('\n');
2539
+ }
2540
+
2541
+
2510
2542
  _publishRemote(handleId, jsep) {
2511
2543
  let handle = this._getHandle(handleId);
2512
2544
  if (!handle) {
@@ -2523,6 +2555,13 @@ class RoomSession {
2523
2555
  let config = handle.webrtcStuff;
2524
2556
 
2525
2557
  if (jsep) {
2558
+
2559
+ // Just For Debugging
2560
+ // Munge the SDP before setting the remote description
2561
+ // if (jsep && jsep.sdp) {
2562
+ // jsep.sdp = this._addSimulcastToSDP(jsep.sdp);
2563
+ // }
2564
+
2526
2565
  return config.pc.setRemoteDescription(jsep)
2527
2566
  .then(() => {
2528
2567
  config.remoteSdp = jsep.sdp;