@reactoo/watchtogether-sdk-js 2.7.80 → 2.7.82

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.
@@ -1,11 +1,11 @@
1
- import {setExactTimeout} from "../wt-utils";
1
+ import {setExactTimeout} from "../../models/utils";
2
2
 
3
3
  const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
4
-
4
+
5
5
  //SYNC VARS
6
6
  let _libraryInstance = null;
7
7
  let _videoElement = null;
8
-
8
+
9
9
  const syncDefaultWaitTime = 60000;
10
10
  const syncShortWaitTime = 10000;
11
11
  const maxSyncThreshold = 0.5;
@@ -15,45 +15,45 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
15
15
  let syncNextWaitTime = null;
16
16
  let stopFlag = false;
17
17
  let isSyncing = false;
18
-
18
+
19
19
  let playbackRate = 2;
20
20
  let isPlaying = false;
21
21
  let isPreloading = true;
22
22
  let isProgrammaticallySeeked = false;
23
23
  let shouldPropagateMaster = false;
24
-
24
+
25
25
  const buffering = (event) => {
26
26
  if(event.buffering) {
27
27
  handleStalledWaiting();
28
28
  }
29
29
  };
30
-
30
+
31
31
  const startSyncLoop = () => {
32
-
32
+
33
33
  if(!isConnected()) {
34
34
  room._log('--- Sync loop will not start due to user not connected yet ---');
35
35
  return
36
36
  }
37
-
37
+
38
38
  if(syncWaitId) {
39
39
  room._log('--- Sync loop already running ---');
40
40
  return
41
41
  }
42
-
42
+
43
43
  room._log('--- Sync enabled ---');
44
-
44
+
45
45
  stopFlag = false;
46
-
46
+
47
47
  const loop = () => {
48
-
48
+
49
49
  isSyncing = true;
50
50
  emitter.emit('playerSyncing', true);
51
-
51
+
52
52
  sync().finally(() => {
53
-
53
+
54
54
  isSyncing = false;
55
55
  emitter.emit('playerSyncing', false);
56
-
56
+
57
57
  if(isConnected() && !stopFlag) {
58
58
  syncWaitId = setTimeout(loop, syncNextWaitTime);
59
59
  }
@@ -61,36 +61,36 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
61
61
  room._log('--- Automatic stop due to user not connected or stop flag enabled ---');
62
62
  stopSyncLoop();
63
63
  }
64
-
64
+
65
65
  })
66
-
66
+
67
67
  };
68
-
68
+
69
69
  loop();
70
-
70
+
71
71
  };
72
-
72
+
73
73
  const stopSyncLoop = () => {
74
-
74
+
75
75
  room._log('--- Sync disabled ---');
76
-
76
+
77
77
  clearTimeout(syncWaitId);
78
78
  syncWaitId = null;
79
79
  currentSyncRetry = 0
80
80
  stopFlag = true;
81
-
81
+
82
82
  };
83
-
83
+
84
84
  const restartSyncLoop = () => {
85
-
85
+
86
86
  room._log('--- Sync restarting ---');
87
87
  stopSyncLoop();
88
88
  startSyncLoop();
89
-
89
+
90
90
  };
91
-
91
+
92
92
  const setNextWaitTime = (didSyncFail = false) => {
93
-
93
+
94
94
  if(!didSyncFail) {
95
95
  syncNextWaitTime = syncDefaultWaitTime;
96
96
  currentSyncRetry = 0
@@ -103,50 +103,50 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
103
103
  syncNextWaitTime = syncShortWaitTime;
104
104
  }
105
105
  }
106
-
106
+
107
107
  room._log('--- Next sync will occur in ' + syncNextWaitTime / 1000 + ' seconds ---');
108
-
108
+
109
109
  }
110
-
110
+
111
111
  const sync = () => {
112
-
112
+
113
113
  return getSyncData()
114
114
  .then(syncData => {
115
-
115
+
116
116
  if(syncData.isMaster) {
117
117
  if(_videoElement.paused) _videoElement.play();
118
118
  setNextWaitTime(false);
119
119
  return Promise.resolve();
120
120
  }
121
-
121
+
122
122
  else if(shouldPropagateMaster) {
123
123
  setNextWaitTime(false);
124
124
  return propagateMasterFunc();
125
125
  }
126
-
126
+
127
127
  else {
128
-
128
+
129
129
  const syncStartTime = Date.now();
130
130
  const {position, realPosition, isBufferSufficient} = calculateSyncDifferenceTime(syncData.masterFragmentSn, syncData.masterFragmentPos, syncData.ping);
131
131
  const currentPosition = getCurrentSegmentPosition() / 1000;
132
-
133
-
132
+
133
+
134
134
  if(position && Math.abs(position - currentPosition) <= maxSyncThreshold) {
135
135
  room._log(`We're within max sync threshold, no need to resync now`);
136
136
  setNextWaitTime(false);
137
137
  return Promise.resolve();
138
138
  }
139
-
139
+
140
140
  if(position !== null) {
141
141
  return seekTo(position)
142
142
  .then(() => {
143
143
  const seekDuration = (Date.now() - syncStartTime) / 1000;
144
144
  const syncPrecision = Math.abs((realPosition + seekDuration) - (getCurrentSegmentPosition() / 1000))
145
-
145
+
146
146
  room._log(`Insufficient buffer: `, !isBufferSufficient);
147
147
  room._log(`Seek duration is ${seekDuration}`);
148
148
  room._log(`Sync precision should be ${syncPrecision}`);
149
-
149
+
150
150
  const didSyncFail = syncPrecision > maxSyncThreshold
151
151
  setNextWaitTime(didSyncFail);
152
152
  return Promise.resolve();
@@ -165,7 +165,7 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
165
165
  return Promise.reject();
166
166
  })
167
167
  }
168
-
168
+
169
169
  const handleAddLocalParticipant = () => {
170
170
  if(shouldPropagateMaster) {
171
171
  propagateMasterFunc();
@@ -176,17 +176,17 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
176
176
  }, {once:true});
177
177
  }
178
178
  };
179
-
179
+
180
180
  const handleAddRemoteParticipant = () => {
181
181
  if(shouldPropagateMaster) {
182
182
  propagateMasterFunc();
183
183
  }
184
184
  };
185
-
185
+
186
186
  const isConnected = () => {
187
187
  return room._isDataChannelOpen && room.isConnected;
188
188
  };
189
-
189
+
190
190
  const parseDataEvents = (msg = {}) => {
191
191
  if(msg.videoroom === 'sync_source_set' && msg.wt_channel_id != "") {
192
192
  emitter.emit('changePlayerSource', msg.wt_channel_id);
@@ -195,12 +195,12 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
195
195
  roomSyncSend(msg.sync_slave_id).catch(()=>{});
196
196
  }
197
197
  };
198
-
198
+
199
199
  const getCurrentSegmentPosition = () => {
200
200
  let position = _videoElement && _videoElement.currentTime;
201
201
  return isNaN(position) ? 0 : position * 1000
202
202
  };
203
-
203
+
204
204
  const calculateSyncDifferenceTime = (fragmentSn, fragmentPos, ping) => {
205
205
  let seekRanges = _videoElement.buffered;
206
206
  let seekRange = {};
@@ -226,7 +226,7 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
226
226
  } else
227
227
  return {position: null, realPosition: position, isBufferSufficient: false}
228
228
  };
229
-
229
+
230
230
  const seekTo = (time) => {
231
231
  return new Promise((resolve, reject) => {
232
232
  if(_videoElement.currentTime !== time) {
@@ -278,7 +278,7 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
278
278
  } else resolve()
279
279
  });
280
280
  };
281
-
281
+
282
282
  // const seekTo = (time) => {
283
283
  // return new Promise((resolve, reject) => {
284
284
  // if(_videoElement.currentTime !== time) {
@@ -293,7 +293,7 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
293
293
  // } else resolve()
294
294
  // });
295
295
  // };
296
-
296
+
297
297
  const handlePlaying = () => {
298
298
  if(!isProgrammaticallySeeked) {
299
299
  room._log('Handle playing');
@@ -303,13 +303,13 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
303
303
  isPreloading = _videoElement.paused;
304
304
  isPlaying = !_videoElement.paused;
305
305
  };
306
-
306
+
307
307
  const handlePause = () => {
308
308
  stopSyncLoop()
309
309
  clientPaused().catch(() => {});
310
310
  isPlaying = !_videoElement.paused;
311
311
  };
312
-
312
+
313
313
  const handleStalledWaiting = () => {
314
314
  room._log('handleStalledWaiting');
315
315
  if(!isProgrammaticallySeeked) {
@@ -318,9 +318,9 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
318
318
  isPreloading = _videoElement.paused;
319
319
  }
320
320
  };
321
-
321
+
322
322
  const roomSyncSend = (slaveId) => {
323
-
323
+
324
324
  if(!_libraryInstance || !_videoElement) {
325
325
  room._log(
326
326
  `I've been asked for position even if we don't have player attached.
@@ -328,12 +328,12 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
328
328
  );
329
329
  return Promise.resolve();
330
330
  }
331
-
331
+
332
332
  let fragmentPosition = parseInt(getCurrentSegmentPosition());
333
-
333
+
334
334
  room._log(`Sending my position to ${slaveId}`);
335
335
  room._log(`Current time: ${fragmentPosition}`);
336
-
336
+
337
337
  return room.sendMessage(room.handleId, {
338
338
  body : {
339
339
  request: "sync_response",
@@ -344,23 +344,23 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
344
344
  slave_id: room.webrtcVersion > 1000 ? String(slaveId) : Number(slaveId)
345
345
  }});
346
346
  };
347
-
347
+
348
348
  const getSyncData = () => {
349
-
349
+
350
350
  room._log('Sending roomSync request');
351
351
  let roomId = room.roomId;
352
352
  let fragmentPosition = parseInt(getCurrentSegmentPosition());
353
-
353
+
354
354
  return new Promise((resolve, reject) => {
355
-
355
+
356
356
  let now = new Date().getTime();
357
357
  let ping = null;
358
-
358
+
359
359
  let sid = setTimeout(() => {
360
360
  room.off('data', fn, this);
361
361
  reject('Timeout');
362
362
  }, 3000);
363
-
363
+
364
364
  let body = {
365
365
  request: "sync",
366
366
  room: roomId,
@@ -368,32 +368,32 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
368
368
  fragment: String("0"),
369
369
  fragment_pos: Number(fragmentPosition)
370
370
  };
371
-
371
+
372
372
  let fn = (msg) => {
373
-
373
+
374
374
  if(msg.videoroom && ['sync', 'sync_response'].includes(msg.videoroom)) {
375
-
375
+
376
376
  if(msg.sync_master_await) {
377
377
  room._log('Waiting for master position');
378
378
  if(!ping) {
379
379
  ping = (new Date().getTime() - now);
380
380
  }
381
381
  }
382
-
382
+
383
383
  else if(msg.sync_master_fragment || msg.sync_master_fragment_pos) {
384
384
  room._log('Got master position data');
385
385
  if(!ping) {
386
386
  ping = (new Date().getTime() - now);
387
387
  }
388
-
388
+
389
389
  room._log(`I'm master: ${!!msg.sync_master_self}`);
390
390
  room._log(`Ping: ${ping}`);
391
391
  room._log(`Master fragment: ${msg.sync_master_fragment}`);
392
392
  room._log(`Master fragment position: ${msg.sync_master_fragment_pos}`);
393
-
393
+
394
394
  room.off('data', fn, this);
395
395
  clearTimeout(sid);
396
-
396
+
397
397
  resolve({
398
398
  isMaster: !!msg.sync_master_self,
399
399
  ping: ping,
@@ -401,7 +401,7 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
401
401
  masterFragmentSn: parseInt(msg.sync_master_fragment),
402
402
  });
403
403
  }
404
-
404
+
405
405
  else {
406
406
  clearTimeout(sid);
407
407
  reject('Master lost connection')
@@ -416,14 +416,14 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
416
416
  });
417
417
  });
418
418
  };
419
-
419
+
420
420
  const clientPaused = () => {
421
421
  room._log('Sending client paused');
422
-
422
+
423
423
  if(!isConnected()) {
424
424
  return Promise.resolve();
425
425
  }
426
-
426
+
427
427
  return room.sendMessage(room.handleId, {
428
428
  body:{
429
429
  request: "sync_paused",
@@ -433,7 +433,7 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
433
433
  fragment_pos:0
434
434
  }});
435
435
  };
436
-
436
+
437
437
  const propagateMasterFunc = () => {
438
438
  room._log('Propagating master');
439
439
  if(!isConnected()) {
@@ -449,65 +449,65 @@ const syncDaznDash = function ({room, wt, roomSession, emitter} = {}) {
449
449
  fragment_pos:0
450
450
  }});
451
451
  };
452
-
452
+
453
453
  return {
454
-
454
+
455
455
  __events: ['playerSyncing'],
456
-
456
+
457
457
  initialize: ({libraryInstance, shakaInstance, propagateMaster = false} = {}) => {
458
-
458
+
459
459
  _libraryInstance = libraryInstance || shakaInstance;
460
460
  _videoElement = _libraryInstance.getMediaElement();
461
-
461
+
462
462
  shouldPropagateMaster = propagateMaster;
463
463
  isPlaying = _videoElement.paused === false;
464
-
464
+
465
465
  room.on('disconnect', stopSyncLoop);
466
466
  room.on('removeLocalParticipant', stopSyncLoop);
467
467
  room.on('addLocalParticipant', handleAddLocalParticipant);
468
468
  room.on('addRemoteParticipant', handleAddRemoteParticipant);
469
469
  room.on('data', parseDataEvents);
470
-
470
+
471
471
  if(shouldPropagateMaster) {
472
472
  propagateMasterFunc().catch(() => {});
473
473
  }
474
-
474
+
475
475
  if(_videoElement && _videoElement.paused === false) {
476
476
  _videoElement.addEventListener('progress', () => {
477
477
  restartSyncLoop();
478
478
  }, {once:true});
479
479
  }
480
-
480
+
481
481
  _libraryInstance.addEventListener('buffering', buffering);
482
482
  _videoElement.addEventListener('playing', handlePlaying);
483
483
  _videoElement.addEventListener('pause', handlePause);
484
-
485
-
484
+
485
+
486
486
  },
487
-
487
+
488
488
  destroy: () => {
489
-
489
+
490
490
  stopSyncLoop();
491
-
491
+
492
492
  room.off('disconnect', stopSyncLoop);
493
493
  room.off('removeLocalParticipant', stopSyncLoop);
494
494
  room.off('addLocalParticipant', handleAddLocalParticipant);
495
495
  room.off('addRemoteParticipant', handleAddRemoteParticipant);
496
496
  room.off('data', parseDataEvents);
497
-
497
+
498
498
  if(_libraryInstance) {
499
499
  _libraryInstance.removeEventListener('buffering', buffering);
500
500
  }
501
-
501
+
502
502
  if(_videoElement) {
503
503
  _videoElement.removeEventListener('playing', handlePlaying);
504
504
  _videoElement.removeEventListener('pause', handlePause);
505
505
  }
506
-
506
+
507
507
  _libraryInstance = null;
508
508
  }
509
509
  };
510
-
510
+
511
511
  };
512
512
 
513
513
  export default syncDaznDash;
@@ -1,5 +1,5 @@
1
1
  import emitter from './wt-emitter';
2
- import { decodeJanusDisplay } from "./wt-utils";
2
+ import { decodeJanusDisplay } from "../models/utils";
3
3
  import { mqtt, iot } from 'aws-iot-device-sdk-v2';
4
4
 
5
5
  class Iot {
@@ -1,5 +1,5 @@
1
1
  import emitter from './wt-emitter';
2
- import { decodeJanusDisplay } from "./wt-utils";
2
+ import { decodeJanusDisplay } from "../models/utils";
3
3
  import Worker from './wt-iot-worker.worker.js';
4
4
 
5
5
  class Iot {
@@ -2,7 +2,7 @@
2
2
 
3
3
  import adapter from 'webrtc-adapter';
4
4
  import emitter from './wt-emitter';
5
- import {decodeJanusDisplay, generateUUID, maxJitter, median, wait} from "./wt-utils";
5
+ import {decodeJanusDisplay, generateUUID, maxJitter, median, wait} from "../models/utils";
6
6
 
7
7
  class Room {
8
8
 
@@ -260,7 +260,7 @@ class RoomSession {
260
260
  this._aqIntervalCounter = 0;
261
261
  this._aqIntervalDivisor = 4;
262
262
  this._aqTimeoutId = null;
263
- this._sendMessageTimeout = 5000;
263
+ this._sendMessageTimeout = 10000;
264
264
  this._retries = 0;
265
265
  this._maxRetries = 5;
266
266
  this._keepAliveId = null;
@@ -498,6 +498,7 @@ class RoomSession {
498
498
  }
499
499
 
500
500
  if (this._retries < this._maxRetries) {
501
+ //TODO: clear this timeout
501
502
  setTimeout(() => {
502
503
  this._retries++;
503
504
  this._reconnect().catch(e => {
@@ -1872,8 +1873,8 @@ class RoomSession {
1872
1873
  .catch(e => Promise.reject({handle: participant, error: e}))
1873
1874
  }
1874
1875
  }))
1875
-
1876
-
1876
+
1877
+
1877
1878
  }
1878
1879
 
1879
1880
  _resetStats(handleId, mid) {
@@ -1,142 +0,0 @@
1
- // import FingerprintJs from "@fingerprintjs/fingerprintjs";
2
- // import FingerprintJsPro from "@fingerprintjs/fingerprintjs-pro";
3
- import {getFingerPrint} from "./wt-fingerprint";
4
-
5
- let wait = function(ms) { return new Promise(resolve => setTimeout(resolve, ms))};
6
-
7
- let median = function(values) {
8
-
9
- if(values.length ===0) return 0;
10
-
11
- values.sort(function(a,b){
12
- return a-b;
13
- });
14
-
15
- var half = Math.floor(values.length / 2);
16
-
17
- if (values.length % 2)
18
- return values[half];
19
-
20
- return (values[half - 1] + values[half]) / 2.0;
21
- }
22
-
23
-
24
- // const getFingerPrint = function(instanceType, salt) {
25
- //
26
- // let fingerprint = FingerprintJs.load({
27
- // monitoring: false
28
- // })
29
- //
30
- // return fingerprint
31
- // .then(fp => fp.get())
32
- // .then(result => {
33
- // const components = {
34
- // ...result.components,
35
- // instanceType: { value: instanceType + '_' + salt },
36
- // }
37
- // return [8,13,18,23].reduce((acc, cur) => {
38
- // return acc.slice(0,cur) + '-' + acc.slice(cur)
39
- // }, FingerprintJs.hashComponents(components)).substring(0,36)
40
- // })
41
- // }
42
- //
43
- // const getPreciseFingerPrint = function() {
44
- //
45
- // let fingerprintPro = FingerprintJsPro.load({
46
- // monitoring: false,
47
- // apiKey: '5UHdpSuX3wHr3CjyEiSP',
48
- // endpoint: "https://fingerprint.reactoo.com"
49
- // })
50
- //
51
- // return fingerprintPro
52
- // .then(fp => fp.get())
53
- // .then(result => {
54
- // let id = result.visitorId.padEnd(32, '0');
55
- // return [8,13,18,23].reduce((acc, cur) => {
56
- // return acc.slice(0,cur) + '-' + acc.slice(cur)
57
- // }, id).substring(0,36)
58
- // })
59
- // }
60
-
61
-
62
- let getBrowserFingerprint = function (instanceType = '', usePrecise = false, salt = '') {
63
- // if(!usePrecise) {
64
- // return getFingerPrint(instanceType, salt)
65
- // }
66
- // else {
67
- // return getPreciseFingerPrint()
68
- // .catch(() => getFingerPrint(instanceType, salt))
69
- // }
70
-
71
- return getFingerPrint(instanceType, salt);
72
- };
73
-
74
- let generateUUID = function () {
75
- var d = Date.now();
76
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
77
- var r = (d + Math.random()*16)%16 | 0;
78
- d = Math.floor(d/16);
79
- return (c=='x' ? r : (r&0x3|0x8)).toString(16);
80
- });
81
- };
82
-
83
-
84
- const janusDisplayDelimiter = ',';
85
- const decodeJanusDisplay = display => {
86
- let output = { userId: null, role: "participant", start: Date.now(), displayName: "?" };
87
- if(display && typeof display === "string") {
88
- if(display.indexOf(janusDisplayDelimiter) >= 0) {
89
- let values = display
90
- .split( new RegExp(`\\${janusDisplayDelimiter}(?=(?:(?:[^"]*"){2})*[^"]*$)`, 'mi') )
91
- .map(v => (v && v.startsWith('"') || v.endsWith('"')) ? v.substring(1, v.length-1) : ( /^\d+$/.test(v) ? parseInt(v) : v ));
92
- Object.keys(output).forEach((key, i) => values[i] ? output[key] = values[i] : null);
93
- } else {
94
- output.userId = display;
95
- }
96
- return output;
97
- } else if(display && typeof display === "object") {
98
- return Object.assign({}, output, display);
99
- }
100
- return null;
101
- }
102
-
103
- const setExactTimeout = function(callback, duration, resolution) {
104
- const start = (new Date()).getTime();
105
- const timeout = setInterval(function(){
106
- if ((new Date()).getTime() - start > duration) {
107
- callback();
108
- clearInterval(timeout);
109
- }
110
- }, resolution);
111
-
112
- return timeout;
113
- };
114
-
115
- const clearExactTimeout = function(timeout) {
116
- clearInterval(timeout);
117
- };
118
-
119
-
120
- const maxJitter = (x) => {
121
- // A function that returns a value between 0.3 and 0.5 depending on the input x
122
- // The function is based on a logistic curve with parameters a, b, c, and d
123
- // The parameters are chosen such that f(30) = 0.3 and f(2) = 0.5
124
- let a = 0.2; // The maximum value of the function
125
- let b = -0.1; // The growth rate of the function
126
- let c = 16; // The inflection point of the function
127
- let d = 0.3; // The minimum value of the function
128
- return a / (1 + Math.exp(-b * (x - c))) + d; // Fixed the typo here
129
- }
130
-
131
- const chunkArray = (array = [], chunkSize) => {
132
- array = [...array];
133
- if (!array?.length) return [[]];
134
-
135
- let results = [];
136
- while (array.length) {
137
- results.push(array.splice(0, chunkSize));
138
- }
139
- return results;
140
- }
141
-
142
- export {wait, getBrowserFingerprint, generateUUID, decodeJanusDisplay, setExactTimeout, clearExactTimeout, median, maxJitter, chunkArray}