@reactoo/watchtogether-sdk-js 2.6.99 → 2.7.2
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/example/index.html
CHANGED
|
@@ -169,10 +169,14 @@
|
|
|
169
169
|
Instance.room.getSessionByConstructId(constructId).setTalkIntercomChannels(groups)
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
function setRestrictSubscribeToUserIds(userIds) {
|
|
173
|
+
Instance.room.getSessionByConstructId(constructId).setRestrictSubscribeToUserIds(userIds)
|
|
174
|
+
}
|
|
175
|
+
|
|
172
176
|
let Instance = WatchTogetherSDK({debug:true})({instanceType:'reactooDemo'});
|
|
173
177
|
|
|
174
|
-
Instance.auth.$on('login', () => {
|
|
175
|
-
console.log('We are in');
|
|
178
|
+
Instance.auth.$on('login', (r) => {
|
|
179
|
+
console.log('We are in', r);
|
|
176
180
|
});
|
|
177
181
|
|
|
178
182
|
Instance.iot.$on('connect', () => {
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@ import syncModule from "../modules/sync-modules/sync-module";
|
|
|
21
21
|
let roomSession = function ({roomId, pinHash, role, options = {}}, room, wt) {
|
|
22
22
|
|
|
23
23
|
let primaryRoomId = roomId;
|
|
24
|
-
let {simulcast = null, simulcastBitrates = null, simulcastMode = null, simulcastDefaultManualSubstream = null} = options;
|
|
24
|
+
let {simulcast = null, simulcastBitrates = null, simulcastMode = null, simulcastDefaultManualSubstream = null, enableDtx = null} = options;
|
|
25
25
|
let publicCustomEvents = ['changePlayerSource', 'chatMessage', 'userUpdate', 'reconnecting', 'connecting', 'remoteMuted', 'scaling'];
|
|
26
26
|
|
|
27
27
|
const addEvents = (events) => {
|
|
@@ -122,6 +122,7 @@ let roomSession = function ({roomId, pinHash, role, options = {}}, room, wt) {
|
|
|
122
122
|
simulcastBitrates !== null ? simulcastBitrates : roomData?.data?.simulcast?.bitrates,
|
|
123
123
|
simulcastMode !== null ? simulcastMode : roomData?.data?.simulcast?.mode,
|
|
124
124
|
simulcastDefaultManualSubstream !== null ? simulcastDefaultManualSubstream : roomData?.data?.simulcast?.defaultManualSubstream,
|
|
125
|
+
enableDtx !== null ? enableDtx : roomData?.data?.enableDtx,
|
|
125
126
|
)
|
|
126
127
|
})
|
|
127
128
|
.finally(() => {
|
|
@@ -339,6 +340,10 @@ let roomSession = function ({roomId, pinHash, role, options = {}}, room, wt) {
|
|
|
339
340
|
return room.toggleVideo(value, source);
|
|
340
341
|
},
|
|
341
342
|
|
|
343
|
+
setRestrictSubscribeToUserIds: (userIds = []) => {
|
|
344
|
+
return room.setRestrictSubscribeToUserIds(userIds);
|
|
345
|
+
},
|
|
346
|
+
|
|
342
347
|
setTalkIntercomChannels: (groups) => {
|
|
343
348
|
return room.setTalkIntercomChannels(groups);
|
|
344
349
|
},
|
package/src/models/room.js
CHANGED
|
@@ -55,14 +55,16 @@ let room = function () {
|
|
|
55
55
|
}))
|
|
56
56
|
},
|
|
57
57
|
|
|
58
|
-
createRoom: ({title, description, isPublic, isRouter, isStudioLayout, wtChannelId, isHd, disableSync, reduceRoomControls, hasStudioChat, maxParticipants, customAttributes, chatRoomId, linkedRoomId, type, dotAttribute} = {}) => {
|
|
58
|
+
createRoom: ({sourceRoomId, title, description, isPublic, isRouter, isStudioLayout, wtChannelId, isHd, disableSync, reduceRoomControls, hasStudioChat, maxParticipants, customAttributes, chatRoomId, linkedRoomId, type, dotAttribute} = {}) => {
|
|
59
59
|
let _da = dotAttribute
|
|
60
60
|
? (Array.isArray(dotAttribute)
|
|
61
61
|
? dotAttribute.reduce((p, cv) => (p[cv.name] = cv.value) && p || p, {})
|
|
62
62
|
: {[dotAttribute.name]: dotAttribute.value})
|
|
63
63
|
: {};
|
|
64
64
|
return this.__privates.auth.__client
|
|
65
|
-
.then(client => client.apis.wt.createRoom({
|
|
65
|
+
.then(client => client.apis.wt.createRoom({
|
|
66
|
+
sourceRoomId
|
|
67
|
+
}, {
|
|
66
68
|
requestBody: {
|
|
67
69
|
title,
|
|
68
70
|
description,
|
package/src/modules/wt-room.js
CHANGED
|
@@ -182,6 +182,7 @@ class RoomSession {
|
|
|
182
182
|
this.sessiontype = type;
|
|
183
183
|
this.initialBitrate = 0;
|
|
184
184
|
this.simulcast = false;
|
|
185
|
+
this.enableDtx = false;
|
|
185
186
|
this.simulcastMode = 'controlled'; // controlled, manual, browserControlled
|
|
186
187
|
this.simulcastDefaultManualSubstream = 0; // 0 = maximum quality
|
|
187
188
|
|
|
@@ -222,11 +223,13 @@ class RoomSession {
|
|
|
222
223
|
this._maxRetries = 5;
|
|
223
224
|
this._keepAliveId = null;
|
|
224
225
|
this._participants = [];
|
|
226
|
+
this._restrictSubscribeToUserIds = []; // all if empty
|
|
225
227
|
this._talkIntercomChannels = ['participants'];
|
|
226
228
|
this._listenIntercomChannels = ['participants'];
|
|
227
229
|
this._roomType = 'watchparty';
|
|
228
230
|
this._isDataChannelOpen = false;
|
|
229
231
|
this._abortController = null;
|
|
232
|
+
this._remoteUsersCache = [];
|
|
230
233
|
|
|
231
234
|
this.userRoleSubscriptionRules = {
|
|
232
235
|
...RoomSession.userRoleSubscriptionRules,
|
|
@@ -239,12 +242,29 @@ class RoomSession {
|
|
|
239
242
|
}
|
|
240
243
|
}
|
|
241
244
|
|
|
245
|
+
_pushToRemoteUsersCache(userId, streams, id) {
|
|
246
|
+
const existingIndex = this._remoteUsersCache.findIndex(u => u.userId === userId);
|
|
247
|
+
if (existingIndex > -1) {
|
|
248
|
+
this._remoteUsersCache.splice(existingIndex, 1, {userId, streams, id})
|
|
249
|
+
} else {
|
|
250
|
+
this._remoteUsersCache.push({userId, streams, id});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
_removeFromRemoteUsersCache(rfid) {
|
|
255
|
+
const existingIndex = this._remoteUsersCache.findIndex(u => u.id === rfid);
|
|
256
|
+
if (existingIndex > -1) {
|
|
257
|
+
this._remoteUsersCache.splice(existingIndex, 1);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
242
261
|
_participantShouldSubscribe(userId) {
|
|
243
262
|
const myUser = decodeJanusDisplay(this.display);
|
|
244
263
|
const remoteUser = decodeJanusDisplay(userId);
|
|
245
264
|
let localUserRole = myUser?.role || 'participant';
|
|
246
265
|
let remoteUserRole = remoteUser?.role || 'participant';
|
|
247
|
-
return this.userRoleSubscriptionRules[localUserRole][(this._roomType || 'watchparty')].indexOf(remoteUserRole) > -1
|
|
266
|
+
return this.userRoleSubscriptionRules[localUserRole][(this._roomType || 'watchparty')].indexOf(remoteUserRole) > -1
|
|
267
|
+
&& (this._restrictSubscribeToUserIds.length === 0 || this._restrictSubscribeToUserIds.indexOf(remoteUser?.userId) > -1);
|
|
248
268
|
}
|
|
249
269
|
|
|
250
270
|
_intercomSubscribe = (stream) => {
|
|
@@ -582,6 +602,7 @@ class RoomSession {
|
|
|
582
602
|
streams[i]["display"] = userId;
|
|
583
603
|
}
|
|
584
604
|
this._log('Remote userId: ', userId);
|
|
605
|
+
this._pushToRemoteUsersCache(userId, streams, id);
|
|
585
606
|
if (this._participantShouldSubscribe(userId)) {
|
|
586
607
|
this._log('Creating user: ', userId);
|
|
587
608
|
this._createParticipant(userId, id)
|
|
@@ -632,6 +653,9 @@ class RoomSession {
|
|
|
632
653
|
streams[i]["display"] = userId;
|
|
633
654
|
}
|
|
634
655
|
this._log('Remote userId: ', userId);
|
|
656
|
+
|
|
657
|
+
this._pushToRemoteUsersCache(userId, streams, id);
|
|
658
|
+
|
|
635
659
|
if (this._participantShouldSubscribe(userId)) {
|
|
636
660
|
|
|
637
661
|
let handle = this._getHandle(null, id);
|
|
@@ -694,8 +718,9 @@ class RoomSession {
|
|
|
694
718
|
this.disconnect().catch(() => {});
|
|
695
719
|
}
|
|
696
720
|
} else if (leaving) {
|
|
697
|
-
//TODO: in 1 PeerConnection case we only unsubscribe from streams
|
|
721
|
+
//TODO: in 1 PeerConnection case we only unsubscribe from streams, this may not be true, check janus docs
|
|
698
722
|
this._log('leaving', leaving);
|
|
723
|
+
this._removeFromRemoteUsersCache(leaving);
|
|
699
724
|
this._removeParticipant(null, leaving, true);
|
|
700
725
|
}
|
|
701
726
|
|
|
@@ -705,6 +730,7 @@ class RoomSession {
|
|
|
705
730
|
} else if (unpublished) {
|
|
706
731
|
//TODO: in 1 PeerConnection case we only unsubscribe from streams
|
|
707
732
|
this._log('unpublished', unpublished);
|
|
733
|
+
this._removeFromRemoteUsersCache(unpublished);
|
|
708
734
|
this._removeParticipant(null, unpublished, true); // we do hangup and detach
|
|
709
735
|
}
|
|
710
736
|
|
|
@@ -712,6 +738,7 @@ class RoomSession {
|
|
|
712
738
|
// this case shouldn't exist
|
|
713
739
|
} else if(kicked) {
|
|
714
740
|
this._log('kicked', kicked);
|
|
741
|
+
this._removeFromRemoteUsersCache(kicked);
|
|
715
742
|
this._removeParticipant(null, kicked, true); // we do hangup and detach
|
|
716
743
|
}
|
|
717
744
|
|
|
@@ -1068,7 +1095,7 @@ class RoomSession {
|
|
|
1068
1095
|
message: 'id non-existent',
|
|
1069
1096
|
data: [handleId, 'isAlreadySubscribed']
|
|
1070
1097
|
});
|
|
1071
|
-
return;
|
|
1098
|
+
return false;
|
|
1072
1099
|
}
|
|
1073
1100
|
return handle.webrtcStuff.subscribeMap.findIndex(t => t.mid === mid && t.feed === feed) > -1
|
|
1074
1101
|
}
|
|
@@ -1264,7 +1291,7 @@ class RoomSession {
|
|
|
1264
1291
|
simulcastBitrates = this.simulcastBitrates,
|
|
1265
1292
|
simulcastMode = this.simulcastMode,
|
|
1266
1293
|
simulcastDefaultManualSubstream = this.simulcastDefaultManualSubstream,
|
|
1267
|
-
|
|
1294
|
+
enableDtx = false
|
|
1268
1295
|
) {
|
|
1269
1296
|
|
|
1270
1297
|
if (this.isConnecting) {
|
|
@@ -1289,6 +1316,7 @@ class RoomSession {
|
|
|
1289
1316
|
this.initialBitrate = initialBitrate;
|
|
1290
1317
|
this.recordingFilename = recordingFilename;
|
|
1291
1318
|
this.isConnecting = true;
|
|
1319
|
+
this.enableDtx = enableDtx;
|
|
1292
1320
|
this.simulcast = simulcast;
|
|
1293
1321
|
this.simulcastMode = simulcastMode;
|
|
1294
1322
|
this.simulcastDefaultManualSubstream = simulcastDefaultManualSubstream;
|
|
@@ -2343,6 +2371,13 @@ class RoomSession {
|
|
|
2343
2371
|
|
|
2344
2372
|
return config.pc[methodName](mediaConstraints)
|
|
2345
2373
|
.then( (response) => {
|
|
2374
|
+
|
|
2375
|
+
// if type offer and its me and we want dtx we mungle the sdp
|
|
2376
|
+
if(handleId === this.handleId && type === 'offer' && this.enableDtx) {
|
|
2377
|
+
// enable DTX
|
|
2378
|
+
response.sdp = response.sdp.replace("useinbandfec=1", "useinbandfec=1;usedtx=1")
|
|
2379
|
+
}
|
|
2380
|
+
|
|
2346
2381
|
config.mySdp = response.sdp;
|
|
2347
2382
|
let _p = config.pc.setLocalDescription(response)
|
|
2348
2383
|
.catch((e) => {
|
|
@@ -3140,6 +3175,68 @@ class RoomSession {
|
|
|
3140
3175
|
return this._roomType;
|
|
3141
3176
|
}
|
|
3142
3177
|
|
|
3178
|
+
setRestrictSubscribeToUserIds(userIds = []) {
|
|
3179
|
+
this._restrictSubscribeToUserIds = structuredClone(userIds);
|
|
3180
|
+
if(!this.isConnected) {
|
|
3181
|
+
return Promise.resolve(this._restrictSubscribeToUserIds);
|
|
3182
|
+
}
|
|
3183
|
+
// sanity check by getting listparticipants and comparing it to _remoteUsersCache
|
|
3184
|
+
this.sendMessage(this.handleId, {body: {request: 'listparticipants', room: this.roomId}})
|
|
3185
|
+
.then(r => {
|
|
3186
|
+
let participants = r.participants;
|
|
3187
|
+
let remoteUsersCache = this._remoteUsersCache;
|
|
3188
|
+
let handle = this._getHandle(this.handleId);
|
|
3189
|
+
|
|
3190
|
+
// filter out my user id from response and compare it to remoteUsersCache
|
|
3191
|
+
participants = participants.filter(p => p.id !== handle.userId);
|
|
3192
|
+
|
|
3193
|
+
// get rid of participants that are in participants but not in remoteUsersCache
|
|
3194
|
+
remoteUsersCache = remoteUsersCache.filter(r => participants.find(p => p.id === r.id));
|
|
3195
|
+
remoteUsersCache.forEach(r => {
|
|
3196
|
+
const handle = this._getHandle(null, null, decodeJanusDisplay(r.userId)?.userId);
|
|
3197
|
+
|
|
3198
|
+
if(this._participantShouldSubscribe(r.userId)) {
|
|
3199
|
+
// todo: do a nicer flag to indicate inactive handle than just checking for pc
|
|
3200
|
+
if(!handle || !handle.webrtcStuff?.pc) {
|
|
3201
|
+
this._log('Subscribing to ', r.userId)
|
|
3202
|
+
this._createParticipant(r.userId, r.id)
|
|
3203
|
+
.then(handle => {
|
|
3204
|
+
this._updateParticipantsTrackData(handle.handleId, r.streams);
|
|
3205
|
+
const subscribe = r.streams.filter(s => !s.disabled && this._intercomSubscribe(s)).map(stream => ({feed: stream.id, mid: stream.mid}));
|
|
3206
|
+
handle.webrtcStuff.subscribeMap = structuredClone(subscribe);
|
|
3207
|
+
return this.sendMessage(handle.handleId, {
|
|
3208
|
+
body: {
|
|
3209
|
+
"request": "join",
|
|
3210
|
+
"room": this.roomId,
|
|
3211
|
+
"ptype": "subscriber",
|
|
3212
|
+
"private_id": this.privateId,
|
|
3213
|
+
streams: subscribe,
|
|
3214
|
+
//"feed": id,
|
|
3215
|
+
...(this.webrtcVersion > 1000 ? {id: this.userId} : {}),
|
|
3216
|
+
pin: this.pin
|
|
3217
|
+
}
|
|
3218
|
+
})
|
|
3219
|
+
})
|
|
3220
|
+
.catch(err => {
|
|
3221
|
+
this.emit('error', err);
|
|
3222
|
+
})
|
|
3223
|
+
|
|
3224
|
+
}
|
|
3225
|
+
|
|
3226
|
+
else {
|
|
3227
|
+
this._log('Already subscribed to ', r.userId);
|
|
3228
|
+
}
|
|
3229
|
+
|
|
3230
|
+
} else if(handle) {
|
|
3231
|
+
this._log('Unsubscribing from ', r.userId)
|
|
3232
|
+
this._removeParticipant(handle.handleId);
|
|
3233
|
+
}
|
|
3234
|
+
})
|
|
3235
|
+
});
|
|
3236
|
+
|
|
3237
|
+
|
|
3238
|
+
}
|
|
3239
|
+
|
|
3143
3240
|
|
|
3144
3241
|
}
|
|
3145
3242
|
|