@reactoo/watchtogether-sdk-js 2.6.14 → 2.6.21
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 +732 -410
- package/dist/watchtogether-sdk.min.js +2 -2
- package/example/index.html +60 -27
- package/package.json +1 -3
- package/src/models/room-session.js +18 -10
- package/src/models/utils.js +18 -3
- package/src/modules/wt-fingerprint.js +46 -0
- package/src/modules/wt-room.js +532 -298
- package/src/modules/wt-utils.js +48 -45
package/example/index.html
CHANGED
|
@@ -12,8 +12,11 @@
|
|
|
12
12
|
<video id="thevideo" class="contentVideo" autoplay playsinline controls style="width: 400px" muted="muted" src="https://assetcdn.reactoo.com/watfordFc/Norwich_2010_B_roll_2min16_mute.mp4"></video>
|
|
13
13
|
<div>
|
|
14
14
|
<button onclick="startRoom()">Connect and publish</button>
|
|
15
|
+
<button onclick="startRoom2()">Connect and publish with screen share</button>
|
|
15
16
|
<button onclick="disconnectRoom()">Disconnect</button>
|
|
16
17
|
<button onclick="publish()">publish</button>
|
|
18
|
+
<button onclick="publishBlank()">publish blank</button>
|
|
19
|
+
<button onclick="publishScreen()">publish screen</button>
|
|
17
20
|
<button onclick="unpublish()">unpublish</button>
|
|
18
21
|
<button onclick="toggleVideo()">toggle video</button>
|
|
19
22
|
<button onclick="toggleAudio()">toggle audio</button>
|
|
@@ -27,8 +30,8 @@
|
|
|
27
30
|
|
|
28
31
|
//https://studio.reactoo.com/room/edf441b3-7415-49c4-9557-273cb93bc746/LJj4W2Cz-nG3U-lb0R-TAaY-o7Thmb8xHSbE
|
|
29
32
|
|
|
30
|
-
let roomId =
|
|
31
|
-
let pinHash =
|
|
33
|
+
let roomId = "c22ada04-6c95-4524-91d8-e915bcef2e61"; //It will create room automatically if not set
|
|
34
|
+
let pinHash = "OayoOVzK-XmWr-BTID-fVwH-eH44Tn3xSWeR";//'967ca05f-7fab-a205-5913-39393bbbe923';
|
|
32
35
|
|
|
33
36
|
|
|
34
37
|
let participants = document.querySelector('.participants');
|
|
@@ -61,29 +64,39 @@
|
|
|
61
64
|
|
|
62
65
|
console.log('participantData', isRemote, data);
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if(!
|
|
67
|
-
|
|
68
|
-
el.autoplay = true;
|
|
69
|
-
el.playsInline = true;
|
|
70
|
-
el.muted = !isRemote;
|
|
71
|
-
el.controls = true;
|
|
72
|
-
el.className = id;
|
|
73
|
-
participants.appendChild(el);
|
|
67
|
+
this.removeParticipant({id: data.id})
|
|
68
|
+
|
|
69
|
+
if(!data.stream) {
|
|
70
|
+
return;
|
|
74
71
|
}
|
|
75
72
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
for(let key in data.streamMap) {
|
|
74
|
+
let tracks = data.stream.getTracks().filter(t => data['streamMap'][key].includes(t.id));
|
|
75
|
+
if(tracks.length) {
|
|
76
|
+
let stream = new MediaStream();
|
|
77
|
+
tracks.forEach(t => stream.addTrack(t));
|
|
78
|
+
let id = `_p${data.id} part_${data.id}_${key}`;
|
|
79
|
+
let el = document.createElement("video");
|
|
80
|
+
el.autoplay = true;
|
|
81
|
+
el.playsInline = true;
|
|
82
|
+
el.muted = !isRemote;
|
|
83
|
+
el.controls = true;
|
|
84
|
+
el.className = id;
|
|
85
|
+
participants.appendChild(el);
|
|
86
|
+
try {
|
|
87
|
+
el.srcObject = stream;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
el.src = URL.createObjectURL(stream);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
80
92
|
}
|
|
81
93
|
}
|
|
82
94
|
|
|
83
95
|
function removeParticipant(data) {
|
|
84
|
-
let id = `
|
|
85
|
-
let
|
|
86
|
-
|
|
96
|
+
let id = `_p${data.id}`;
|
|
97
|
+
let els = document.querySelectorAll(`.${id}`);
|
|
98
|
+
console.log(id,els);
|
|
99
|
+
els.length && els.forEach(el => el.parentNode.removeChild(el));
|
|
87
100
|
}
|
|
88
101
|
|
|
89
102
|
|
|
@@ -92,22 +105,42 @@
|
|
|
92
105
|
}
|
|
93
106
|
|
|
94
107
|
function startRoom() {
|
|
108
|
+
let sess = Instance.room.getSessionByConstructId(constructId);
|
|
109
|
+
sess.connect()
|
|
110
|
+
.then(() => Instance.utils.getUserStream({hasVideo:true, hasAudio: true}))
|
|
111
|
+
.then((stream) => sess.publishLocal(stream))
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function startRoom2() {
|
|
95
115
|
let sess = Instance.room.getSessionByConstructId(constructId);
|
|
96
116
|
sess.connect()
|
|
97
117
|
.then(() => Instance.utils.getUserStream({hasVideo:true}))
|
|
98
118
|
.then((stream) => sess.publishLocal(stream))
|
|
119
|
+
.then(() => Instance.utils.getDisplayMedia())
|
|
120
|
+
.then((stream) => sess.publishLocal(stream, 'screen'))
|
|
99
121
|
}
|
|
100
122
|
|
|
101
123
|
function unpublish() {
|
|
102
124
|
Instance.room.getSessionByConstructId(constructId).unpublishLocal()
|
|
103
125
|
}
|
|
104
126
|
|
|
127
|
+
function publishBlank() {
|
|
128
|
+
let sess = Instance.room.getSessionByConstructId(constructId);
|
|
129
|
+
sess.publishLocal(null)
|
|
130
|
+
}
|
|
131
|
+
|
|
105
132
|
function publish(vDeviceId) {
|
|
106
133
|
let sess = Instance.room.getSessionByConstructId(constructId);
|
|
107
134
|
Instance.utils.getUserStream({hasVideo:true, vDeviceId})
|
|
108
135
|
.then(stream => sess.publishLocal(stream))
|
|
109
136
|
}
|
|
110
137
|
|
|
138
|
+
function publishScreen(vDeviceId) {
|
|
139
|
+
let sess = Instance.room.getSessionByConstructId(constructId);
|
|
140
|
+
Instance.utils.getDisplayMedia()
|
|
141
|
+
.then((stream) => sess.publishLocal(stream, 'screen'))
|
|
142
|
+
}
|
|
143
|
+
|
|
111
144
|
function toggleVideo() {
|
|
112
145
|
Instance.room.getSessionByConstructId(constructId).toggleVideo()
|
|
113
146
|
}
|
|
@@ -199,19 +232,19 @@
|
|
|
199
232
|
});
|
|
200
233
|
|
|
201
234
|
session.$on('addLocalParticipant', (participant) => {
|
|
202
|
-
createParticipant(participant); // our
|
|
235
|
+
createParticipant(participant); // our participant is available or updated
|
|
203
236
|
});
|
|
204
237
|
|
|
205
238
|
session.$on('removeLocalParticipant', (participant) => {
|
|
206
|
-
removeParticipant(participant); // our
|
|
239
|
+
removeParticipant(participant); // our participant is gone
|
|
207
240
|
});
|
|
208
241
|
|
|
209
242
|
session.$on('addRemoteParticipant', (participant) => {
|
|
210
|
-
createParticipant(participant, true); // remote
|
|
243
|
+
createParticipant(participant, true); // remote participant is available or updated
|
|
211
244
|
});
|
|
212
245
|
|
|
213
246
|
session.$on('removeRemoteParticipant', (participant) => {
|
|
214
|
-
removeParticipant(participant, true); // remote
|
|
247
|
+
removeParticipant(participant, true); // remote participant is gone
|
|
215
248
|
});
|
|
216
249
|
|
|
217
250
|
session.$on('userUpdate', (userId) => {
|
|
@@ -238,12 +271,12 @@
|
|
|
238
271
|
console.log('remoteMuted', data); // remote participant muted it's video/audio stream
|
|
239
272
|
});
|
|
240
273
|
|
|
241
|
-
session.$on('localHasVideo', (value) => {
|
|
242
|
-
console.log('localHasVideo', value); // local stream contains video track
|
|
274
|
+
session.$on('localHasVideo', (value, source) => {
|
|
275
|
+
console.log('localHasVideo', value, source); // local stream contains video track
|
|
243
276
|
});
|
|
244
277
|
|
|
245
|
-
session.$on('localHasAudio', (value) => {
|
|
246
|
-
console.log('localHasAudio', value); // local stream contains audio track
|
|
278
|
+
session.$on('localHasAudio', (value, source) => {
|
|
279
|
+
console.log('localHasAudio', value, source); // local stream contains audio track
|
|
247
280
|
});
|
|
248
281
|
|
|
249
282
|
session.$on('observerIds', (value) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactoo/watchtogether-sdk-js",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.21",
|
|
4
4
|
"description": "Javascript SDK for Reactoo",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"unpkg": "dist/watchtogether-sdk.min.js",
|
|
@@ -42,8 +42,6 @@
|
|
|
42
42
|
"yargs": "^10.1.2"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@fingerprintjs/fingerprintjs": "^3.3.2",
|
|
46
|
-
"@fingerprintjs/fingerprintjs-pro": "^3.8.1",
|
|
47
45
|
"aws-iot-device-sdk": "^2.2.11",
|
|
48
46
|
"serialize-error": "9.1.0",
|
|
49
47
|
"swagger-client": "3.18.0",
|
|
@@ -46,8 +46,8 @@ let roomSession = function ({roomId, pinHash, role}, room, wt) {
|
|
|
46
46
|
}, 2000);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
room.on('localMuted', ({type, value}) => {
|
|
50
|
-
___.sendSystemMessage('remote_muted', {type, value})
|
|
49
|
+
room.on('localMuted', ({type, value, source, mid}) => {
|
|
50
|
+
___.sendSystemMessage('remote_muted', {type, value, source, mid})
|
|
51
51
|
});
|
|
52
52
|
room.on('data', (data) => {
|
|
53
53
|
___.__parseDataEvents(data);
|
|
@@ -90,10 +90,6 @@ let roomSession = function ({roomId, pinHash, role}, room, wt) {
|
|
|
90
90
|
return wt.room.destroySession(room.constructId)
|
|
91
91
|
},
|
|
92
92
|
|
|
93
|
-
iceRestart: function () {
|
|
94
|
-
return room._iceRestart(room.handleId);
|
|
95
|
-
},
|
|
96
|
-
|
|
97
93
|
connect: function ({reactooRoomId = null} = {}) {
|
|
98
94
|
emitter.emit('connecting', true);
|
|
99
95
|
clearTimeout(alpTimeoutId);
|
|
@@ -324,8 +320,8 @@ let roomSession = function ({roomId, pinHash, role}, room, wt) {
|
|
|
324
320
|
}
|
|
325
321
|
},
|
|
326
322
|
|
|
327
|
-
publishLocal: function (stream = null) {
|
|
328
|
-
return room.publishLocal(stream)
|
|
323
|
+
publishLocal: function (stream = null, source) {
|
|
324
|
+
return room.publishLocal(stream, source)
|
|
329
325
|
},
|
|
330
326
|
|
|
331
327
|
unpublishLocal: () => {
|
|
@@ -388,8 +384,20 @@ let roomSession = function ({roomId, pinHash, role}, room, wt) {
|
|
|
388
384
|
},
|
|
389
385
|
|
|
390
386
|
__sendMuteStatus: function () {
|
|
391
|
-
|
|
392
|
-
|
|
387
|
+
for(const val of room.isMuted) {
|
|
388
|
+
this.sendSystemMessage('remote_muted', {...val});
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
|
|
392
|
+
__test: function (value) {
|
|
393
|
+
return room.sendMessage(room.handleId, {
|
|
394
|
+
body: {
|
|
395
|
+
request: "data",
|
|
396
|
+
room: room.roomId,
|
|
397
|
+
timestamp: new Date().getTime(),
|
|
398
|
+
text: JSON.stringify(value),
|
|
399
|
+
}
|
|
400
|
+
});
|
|
393
401
|
},
|
|
394
402
|
|
|
395
403
|
$on: (key, callback, that) => {
|
package/src/models/utils.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const getUserMediaConstraints = ({
|
|
5
5
|
|
|
6
6
|
hasVideo,
|
|
7
7
|
hasAudio = true,
|
|
@@ -67,7 +67,7 @@ export default {
|
|
|
67
67
|
|
|
68
68
|
if(stream) {
|
|
69
69
|
|
|
70
|
-
let fullConstraints =
|
|
70
|
+
let fullConstraints = getUserMediaConstraints({
|
|
71
71
|
hasVideo: true,
|
|
72
72
|
hasAudio: true,
|
|
73
73
|
autoGainControl, echoCancellation, noiseSuppression, channelCount, isHd, lfps
|
|
@@ -109,7 +109,7 @@ export default {
|
|
|
109
109
|
} = {}
|
|
110
110
|
) {
|
|
111
111
|
|
|
112
|
-
let fullConstraints =
|
|
112
|
+
let fullConstraints = getUserMediaConstraints({
|
|
113
113
|
hasVideo, hasAudio, isHd, aDeviceId, vDeviceId, lfps, autoGainControl, echoCancellation, noiseSuppression, channelCount
|
|
114
114
|
});
|
|
115
115
|
|
|
@@ -151,5 +151,20 @@ export default {
|
|
|
151
151
|
};
|
|
152
152
|
|
|
153
153
|
return navigator.mediaDevices.getUserMedia(fullConstraints);
|
|
154
|
+
},
|
|
155
|
+
getDisplayMedia() {
|
|
156
|
+
|
|
157
|
+
const constraints = {
|
|
158
|
+
video: {
|
|
159
|
+
cursor: "always",
|
|
160
|
+
displaySurface: "monitor",
|
|
161
|
+
logicalSurface: false
|
|
162
|
+
},
|
|
163
|
+
surfaceSwitching: "include",
|
|
164
|
+
selfBrowserSurface: "exclude",
|
|
165
|
+
systemAudio: "exclude",
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
return navigator.mediaDevices.getDisplayMedia(constraints);
|
|
154
169
|
}
|
|
155
170
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const identifierLocalStorageKey = 'reactoo-id';
|
|
2
|
+
|
|
3
|
+
const getFingerPrint = function (instanceType = '', salt = '') {
|
|
4
|
+
return Promise.resolve(generateFingerprint(getRandomNumberGenerator(getId() + instanceType + salt)));
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const generateFingerprint = function (randomNumberGenerator) {
|
|
8
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
|
9
|
+
var r = (randomNumberGenerator()*16)%16 | 0;
|
|
10
|
+
return (c==='x' ? r : (r&0x3|0x8)).toString(16);
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const getId = function () {
|
|
15
|
+
let id = localStorage.getItem(identifierLocalStorageKey);
|
|
16
|
+
if (!id) {
|
|
17
|
+
id = Math.round(Math.random() * Math.pow(10, 16)) + '';
|
|
18
|
+
localStorage.setItem(identifierLocalStorageKey, id);
|
|
19
|
+
}
|
|
20
|
+
return id;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const getRandomNumberGenerator = function (seed) {
|
|
24
|
+
seed = (seed || Math.floor(Math.random() * 10000000000000000)) + '';
|
|
25
|
+
|
|
26
|
+
// https://stackoverflow.com/a/47593316/3162532 - xmur3
|
|
27
|
+
let i, h;
|
|
28
|
+
for (i = 0, h = 1779033703 ^ seed.length; i < seed.length; i++) {
|
|
29
|
+
h = Math.imul(h ^ seed.charCodeAt(i), 3432918353);
|
|
30
|
+
h = h << 13 | h >>> 19;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
h = Math.imul(h ^ h >>> 16, 2246822507);
|
|
34
|
+
h = Math.imul(h ^ h >>> 13, 3266489909);
|
|
35
|
+
seed = (h ^ h >>> 16) >>> 0;
|
|
36
|
+
|
|
37
|
+
// https://stackoverflow.com/a/47593316/3162532 - Mulberry32
|
|
38
|
+
return function () {
|
|
39
|
+
let t = seed += 0x6D2B79F5;
|
|
40
|
+
t = Math.imul(t ^ t >>> 15, t | 1);
|
|
41
|
+
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
|
|
42
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export {getFingerPrint};
|