@reactoo/watchtogether-sdk-js 2.8.0 → 2.8.1-5.beta.1
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 +492 -89
- package/dist/watchtogether-sdk.js.map +1 -1
- package/dist/watchtogether-sdk.min.js +2 -2
- package/example/index.html +3 -0
- package/package.json +1 -1
- package/src/index.js +2 -0
- package/src/models/asset.js +17 -1
- package/src/models/auth.js +7 -0
- package/src/models/live-barn.js +85 -0
- package/src/models/room-session.js +11 -0
- package/src/models/user.js +23 -11
- package/src/modules/replay-modules/replay-hls.js +0 -0
- package/src/modules/wt-room-sfu.js +174 -51
|
@@ -234,6 +234,7 @@ class RoomSession {
|
|
|
234
234
|
this.enableDtx = false;
|
|
235
235
|
this.simulcast = false;
|
|
236
236
|
|
|
237
|
+
|
|
237
238
|
this.defaultSimulcastSettings = {
|
|
238
239
|
"default" : {
|
|
239
240
|
mode: "controlled", // controlled, manual, browserControlled
|
|
@@ -274,6 +275,7 @@ class RoomSession {
|
|
|
274
275
|
this.sessionId = null;
|
|
275
276
|
this.apisecret = null;
|
|
276
277
|
this.ws = null;
|
|
278
|
+
this.wsOpen = false;
|
|
277
279
|
|
|
278
280
|
// helper flags
|
|
279
281
|
|
|
@@ -291,6 +293,7 @@ class RoomSession {
|
|
|
291
293
|
this.requestMuteStatusTimeout = 100;
|
|
292
294
|
this._statsInterval = 3000;
|
|
293
295
|
this._statsIntervalId = null;
|
|
296
|
+
this._sendMessageWebsocketTimeout = 30000;
|
|
294
297
|
this._sendMessageTimeout = 10000;
|
|
295
298
|
this._keepAlivePeriod = 25000;
|
|
296
299
|
this._longPollTimeout = 60000;
|
|
@@ -313,6 +316,7 @@ class RoomSession {
|
|
|
313
316
|
this.#enableDebug();
|
|
314
317
|
}
|
|
315
318
|
|
|
319
|
+
|
|
316
320
|
}
|
|
317
321
|
|
|
318
322
|
#httpAPICall = function(url, options) {
|
|
@@ -501,6 +505,7 @@ class RoomSession {
|
|
|
501
505
|
id,
|
|
502
506
|
userId,
|
|
503
507
|
role,
|
|
508
|
+
mid,
|
|
504
509
|
fullUserId: display,
|
|
505
510
|
constructId: this.constructId,
|
|
506
511
|
track: track,
|
|
@@ -540,6 +545,7 @@ class RoomSession {
|
|
|
540
545
|
role,
|
|
541
546
|
fullUserId: display,
|
|
542
547
|
constructId: this.constructId,
|
|
548
|
+
mid: null,
|
|
543
549
|
track: null,
|
|
544
550
|
source: null,
|
|
545
551
|
adding: false,
|
|
@@ -882,6 +888,23 @@ class RoomSession {
|
|
|
882
888
|
}
|
|
883
889
|
}
|
|
884
890
|
|
|
891
|
+
sendMessageViaDataChannel(label = this.defaultDataChannelLabel, data) {
|
|
892
|
+
if(this.#publisherHandle) {
|
|
893
|
+
if(label === null) {
|
|
894
|
+
Object.keys(this.#publisherHandle.webrtcStuff.dataChannel).forEach((key) => {
|
|
895
|
+
const channel = this.#publisherHandle.webrtcStuff.dataChannel[key];
|
|
896
|
+
channel.send(JSON.stringify(data));
|
|
897
|
+
})
|
|
898
|
+
}
|
|
899
|
+
else {
|
|
900
|
+
const channel = this.#publisherHandle.webrtcStuff.dataChannel[label];
|
|
901
|
+
if(channel) {
|
|
902
|
+
channel.send(JSON.stringify(data));
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
|
|
885
908
|
async sendMessage(handleId, message = {body: 'Example Body'}, dontWait = false, dontResolveOnAck = false, retry = 0) {
|
|
886
909
|
return this.#send({
|
|
887
910
|
"janus": "message",
|
|
@@ -923,6 +946,9 @@ class RoomSession {
|
|
|
923
946
|
}
|
|
924
947
|
return json;
|
|
925
948
|
})
|
|
949
|
+
.catch(e => {
|
|
950
|
+
return Promise.reject({error: e, requestData});
|
|
951
|
+
})
|
|
926
952
|
}
|
|
927
953
|
|
|
928
954
|
async #sendWebsockets(request = {}, ignoreResponse = false, dontResolveOnAck = false, retry = 0) {
|
|
@@ -936,21 +962,36 @@ class RoomSession {
|
|
|
936
962
|
};
|
|
937
963
|
this._log(requestData);
|
|
938
964
|
const op = () => new Promise((resolve, reject) => {
|
|
965
|
+
|
|
939
966
|
let messageTimeoutId = null;
|
|
940
|
-
|
|
941
|
-
|
|
967
|
+
|
|
968
|
+
let cleanup = () => {
|
|
942
969
|
clearTimeout(messageTimeoutId);
|
|
970
|
+
this._abortController.signal.removeEventListener('abort', abortResponse);
|
|
943
971
|
this.ws.removeEventListener('message', parseResponse);
|
|
972
|
+
};
|
|
973
|
+
|
|
974
|
+
let abortResponse = () => {
|
|
975
|
+
cleanup();
|
|
944
976
|
reject({type: 'warning', id: 4, message: 'connection cancelled'})
|
|
945
977
|
};
|
|
946
978
|
|
|
979
|
+
// we may get multiple responses from parallel requests, so we need to make sure we only resolve the one we sent
|
|
980
|
+
|
|
947
981
|
let parseResponse = (event) => {
|
|
948
|
-
let json
|
|
982
|
+
let json;
|
|
983
|
+
try {
|
|
984
|
+
json = JSON.parse(event.data);
|
|
985
|
+
}
|
|
986
|
+
catch (e) {}
|
|
987
|
+
|
|
988
|
+
if(!json) {
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
|
|
949
992
|
let r_transaction = json['transaction'];
|
|
950
993
|
if (r_transaction === transaction && (!dontResolveOnAck || json['janus'] !== 'ack')) {
|
|
951
|
-
|
|
952
|
-
this._abortController.signal.removeEventListener('abort', abortResponse);
|
|
953
|
-
this.ws.removeEventListener('message', parseResponse);
|
|
994
|
+
cleanup();
|
|
954
995
|
if (json['janus'] === 'error') {
|
|
955
996
|
if (json?.error?.code == 403) {
|
|
956
997
|
this.disconnect();
|
|
@@ -967,31 +1008,78 @@ class RoomSession {
|
|
|
967
1008
|
this.ws.send(JSON.stringify(requestData));
|
|
968
1009
|
}
|
|
969
1010
|
resolve();
|
|
970
|
-
}
|
|
1011
|
+
}
|
|
1012
|
+
else {
|
|
971
1013
|
if (this.ws && this.ws.readyState === 1) {
|
|
1014
|
+
|
|
972
1015
|
this.ws.addEventListener('message', parseResponse);
|
|
1016
|
+
|
|
973
1017
|
messageTimeoutId = setTimeout(() => {
|
|
974
|
-
|
|
975
|
-
this._abortController.signal.removeEventListener('abort', abortResponse);
|
|
1018
|
+
cleanup();
|
|
976
1019
|
reject({type: 'warning', id: 6, message: 'send timeout', data: requestData});
|
|
977
1020
|
}, this._sendMessageTimeout);
|
|
1021
|
+
|
|
978
1022
|
this._abortController.signal.addEventListener('abort', abortResponse);
|
|
1023
|
+
|
|
979
1024
|
this.ws.send(JSON.stringify(requestData));
|
|
980
|
-
}
|
|
1025
|
+
}
|
|
1026
|
+
else {
|
|
1027
|
+
cleanup();
|
|
981
1028
|
reject({type: 'warning', id: 7, message: 'No connection to WebSockets', data: requestData});
|
|
982
1029
|
}
|
|
983
1030
|
}
|
|
984
1031
|
})
|
|
985
1032
|
|
|
986
1033
|
return op().catch(e => {
|
|
987
|
-
if (e.id ===
|
|
1034
|
+
if (e.id === 4 ) {
|
|
988
1035
|
return Promise.reject(e);
|
|
989
1036
|
}
|
|
990
|
-
else if(e.id ===
|
|
991
|
-
|
|
1037
|
+
else if(e.id === 7 && this.isSupposeToBeConnected) {
|
|
1038
|
+
|
|
1039
|
+
return new Promise((resolve, reject) => {
|
|
1040
|
+
|
|
1041
|
+
let establishConnectionTimeoutId = null;
|
|
1042
|
+
|
|
1043
|
+
const cleanup = () => {
|
|
1044
|
+
clearTimeout(establishConnectionTimeoutId);
|
|
1045
|
+
this._abortController.signal.removeEventListener('abort', abort);
|
|
1046
|
+
this.off('webSocketsConnectionOpened', connection);
|
|
1047
|
+
};
|
|
1048
|
+
|
|
1049
|
+
const connection = () => {
|
|
1050
|
+
cleanup();
|
|
1051
|
+
resolve(this.#sendWebsockets(request, ignoreResponse, dontResolveOnAck, retry - 1));
|
|
1052
|
+
};
|
|
1053
|
+
const timeout = () => {
|
|
1054
|
+
cleanup();
|
|
1055
|
+
reject({type: 'warning', id: 46, message: 'WebSocket connection did not open during wait period', data: requestData});
|
|
1056
|
+
};
|
|
1057
|
+
const abort = () => {
|
|
1058
|
+
cleanup();
|
|
1059
|
+
reject({type: 'warning', id: 47, message: 'WebSocket connection was aborted', data: requestData});
|
|
1060
|
+
};
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
if(this.wsOpen) {
|
|
1064
|
+
|
|
1065
|
+
this._log('Retrying failed WebSocket request', requestData);
|
|
1066
|
+
|
|
1067
|
+
resolve(this.#sendWebsockets(request, ignoreResponse, dontResolveOnAck, retry - 1));
|
|
1068
|
+
}
|
|
1069
|
+
else {
|
|
1070
|
+
|
|
1071
|
+
this._log('Waiting for WebSocket connection to open before sending request', requestData);
|
|
1072
|
+
|
|
1073
|
+
this._abortController.signal.addEventListener('abort', abort);
|
|
1074
|
+
establishConnectionTimeoutId = setTimeout(timeout, this._sendMessageWebsocketTimeout);
|
|
1075
|
+
this.once('webSocketsConnectionOpened', connection);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
})
|
|
1079
|
+
|
|
992
1080
|
}
|
|
993
|
-
else if(retry > 0) {
|
|
994
|
-
return this.#
|
|
1081
|
+
else if(retry > 0 && this.isSupposeToBeConnected) {
|
|
1082
|
+
return this.#sendWebsockets(request, ignoreResponse, dontResolveOnAck, retry - 1);
|
|
995
1083
|
}
|
|
996
1084
|
else {
|
|
997
1085
|
return Promise.reject(e);
|
|
@@ -1034,6 +1122,9 @@ class RoomSession {
|
|
|
1034
1122
|
|
|
1035
1123
|
#connectionClosed() {
|
|
1036
1124
|
|
|
1125
|
+
this.wsOpen = false;
|
|
1126
|
+
this.emit('webSocketsConnectionClosed');
|
|
1127
|
+
|
|
1037
1128
|
if (!this.isConnected || this.isConnecting || this.isDisconnecting) {
|
|
1038
1129
|
return;
|
|
1039
1130
|
}
|
|
@@ -1041,7 +1132,7 @@ class RoomSession {
|
|
|
1041
1132
|
this.#reconnect()
|
|
1042
1133
|
.catch(e => {
|
|
1043
1134
|
if(e.type !== 'warning') {
|
|
1044
|
-
this.disconnect();
|
|
1135
|
+
this.disconnect().catch(() => {});
|
|
1045
1136
|
}
|
|
1046
1137
|
this.emit('error', e)
|
|
1047
1138
|
});
|
|
@@ -1112,7 +1203,12 @@ class RoomSession {
|
|
|
1112
1203
|
if (type === "trickle") {
|
|
1113
1204
|
let candidate = json["candidate"];
|
|
1114
1205
|
let config = handle.webrtcStuff;
|
|
1115
|
-
if (config.pc &&
|
|
1206
|
+
if (config.pc &&
|
|
1207
|
+
config.remoteSdp &&
|
|
1208
|
+
!config.isIceRestarting &&
|
|
1209
|
+
config.pc.iceConnectionState !== 'closed' &&
|
|
1210
|
+
config.pc.iceConnectionState !== 'failed' &&
|
|
1211
|
+
config.pc.iceConnectionState !== 'disconnected') {
|
|
1116
1212
|
|
|
1117
1213
|
if (!candidate || candidate.completed === true) {
|
|
1118
1214
|
config.pc.addIceCandidate(null).catch((e) => {
|
|
@@ -1380,8 +1476,6 @@ class RoomSession {
|
|
|
1380
1476
|
config.dataChannelOpen = this.defaultDataChannelLabel === data?.label && data?.state === 'open';
|
|
1381
1477
|
}
|
|
1382
1478
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
1479
|
if (handleId === this.handleId && this.defaultDataChannelLabel === data?.label) {
|
|
1386
1480
|
this._isDataChannelOpen = data?.state === 'open';
|
|
1387
1481
|
this.emit('dataChannel', data?.state === 'open');
|
|
@@ -1394,19 +1488,8 @@ class RoomSession {
|
|
|
1394
1488
|
type: 'warning',
|
|
1395
1489
|
id: 12,
|
|
1396
1490
|
message: 'data event warning',
|
|
1397
|
-
data: [handleId, data]
|
|
1491
|
+
data: [handleId, data, data.error?.message, data.error?.errorDetail]
|
|
1398
1492
|
});
|
|
1399
|
-
|
|
1400
|
-
if (handle) {
|
|
1401
|
-
let config = handle.webrtcStuff;
|
|
1402
|
-
if(this.defaultDataChannelLabel === data.label) {
|
|
1403
|
-
config.dataChannelOpen = false;
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1406
|
-
if (handleId === this.handleId && this.defaultDataChannelLabel === data.label) {
|
|
1407
|
-
this._isDataChannelOpen = false;
|
|
1408
|
-
this.emit('dataChannel', false);
|
|
1409
|
-
}
|
|
1410
1493
|
}
|
|
1411
1494
|
|
|
1412
1495
|
if (handleId === this.handleId && type === 'message') {
|
|
@@ -1422,6 +1505,18 @@ class RoomSession {
|
|
|
1422
1505
|
this.emit('data', d);
|
|
1423
1506
|
}
|
|
1424
1507
|
|
|
1508
|
+
if(handleId !== this.handleId && type === 'message') {
|
|
1509
|
+
let d = null;
|
|
1510
|
+
|
|
1511
|
+
try {
|
|
1512
|
+
d = JSON.parse(data)
|
|
1513
|
+
} catch (e) {
|
|
1514
|
+
this.emit('error', {type: 'warning', id: 45, message: 'data message parse error', data: [handleId, e]});
|
|
1515
|
+
return;
|
|
1516
|
+
}
|
|
1517
|
+
this.emit('dataMessage', d);
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1425
1520
|
}
|
|
1426
1521
|
|
|
1427
1522
|
async #createHandle() {
|
|
@@ -1711,6 +1806,10 @@ class RoomSession {
|
|
|
1711
1806
|
this.ws.addEventListener('message', this.__handleWsEventsBoundFn);
|
|
1712
1807
|
|
|
1713
1808
|
this.ws.onopen = () => {
|
|
1809
|
+
|
|
1810
|
+
this.wsOpen = true;
|
|
1811
|
+
this.emit('webSocketsConnectionOpened');
|
|
1812
|
+
|
|
1714
1813
|
this._abortController.signal.removeEventListener('abort', abortConnect);
|
|
1715
1814
|
if(!reclaim) {
|
|
1716
1815
|
this.#send({"janus": "create"})
|
|
@@ -1824,10 +1923,10 @@ class RoomSession {
|
|
|
1824
1923
|
}
|
|
1825
1924
|
let _rejectTimeout = () => {
|
|
1826
1925
|
cleanup();
|
|
1827
|
-
reject({type: '
|
|
1926
|
+
reject({type: 'error', id: 44, message: 'Connection timeout'})
|
|
1828
1927
|
}
|
|
1829
1928
|
this.once('joined', _resolve);
|
|
1830
|
-
timeoutId = setTimeout(_rejectTimeout,
|
|
1929
|
+
timeoutId = setTimeout(_rejectTimeout, 15000)
|
|
1831
1930
|
this._abortController.signal.addEventListener('abort', _rejectAbort);
|
|
1832
1931
|
})
|
|
1833
1932
|
}
|
|
@@ -1875,8 +1974,6 @@ class RoomSession {
|
|
|
1875
1974
|
enableDtx = false
|
|
1876
1975
|
) {
|
|
1877
1976
|
|
|
1878
|
-
this.isSupposeToBeConnected = true;
|
|
1879
|
-
|
|
1880
1977
|
if (this.isConnecting) {
|
|
1881
1978
|
this.emit('error', {type: 'warning', id: 23, message: 'connection already in progress'});
|
|
1882
1979
|
return
|
|
@@ -1886,6 +1983,8 @@ class RoomSession {
|
|
|
1886
1983
|
await this.disconnect();
|
|
1887
1984
|
}
|
|
1888
1985
|
|
|
1986
|
+
this.isSupposeToBeConnected = true;
|
|
1987
|
+
|
|
1889
1988
|
this._abortController = new AbortController();
|
|
1890
1989
|
|
|
1891
1990
|
this.sessionId = null;
|
|
@@ -1936,6 +2035,9 @@ class RoomSession {
|
|
|
1936
2035
|
await this.#waitForConnectEvent();
|
|
1937
2036
|
|
|
1938
2037
|
} catch (error) {
|
|
2038
|
+
if(error?.type !== 'warning') {
|
|
2039
|
+
this.disconnect().catch(() => {});
|
|
2040
|
+
}
|
|
1939
2041
|
this.emit('error', error);
|
|
1940
2042
|
} finally {
|
|
1941
2043
|
this.isConnecting = false;
|
|
@@ -1975,14 +2077,34 @@ class RoomSession {
|
|
|
1975
2077
|
await this.#destroyHandle(this.#subscriberHandle?.handleId, false);
|
|
1976
2078
|
|
|
1977
2079
|
this.#wipeListeners();
|
|
1978
|
-
|
|
2080
|
+
|
|
2081
|
+
if(!this.useWebsockets) {
|
|
2082
|
+
|
|
2083
|
+
if(this.token) {
|
|
2084
|
+
await this.#send({"janus": "destroy"}, true);
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
else if (this.ws && this.ws.readyState === 1) {
|
|
1979
2089
|
await this.#send({"janus": "destroy"}, true);
|
|
1980
2090
|
this.ws.close();
|
|
1981
2091
|
}
|
|
1982
2092
|
|
|
1983
2093
|
this.#subscriberJoinPromise = null;
|
|
2094
|
+
|
|
1984
2095
|
this.sessionId = null;
|
|
2096
|
+
this.server = null;
|
|
2097
|
+
this.protocol = null;
|
|
2098
|
+
this.iceServers = null;
|
|
2099
|
+
this.token = null;
|
|
2100
|
+
this.roomId = null;
|
|
2101
|
+
this.pin = null;
|
|
2102
|
+
this.id = null;
|
|
2103
|
+
this.display = null;
|
|
2104
|
+
this.userId = null;
|
|
2105
|
+
|
|
1985
2106
|
this.isPublished = false;
|
|
2107
|
+
this.isConnecting = false;
|
|
1986
2108
|
this.isConnected = false;
|
|
1987
2109
|
this.isDisconnecting = false;
|
|
1988
2110
|
this.emit('publishing', false);
|
|
@@ -2111,7 +2233,7 @@ class RoomSession {
|
|
|
2111
2233
|
|
|
2112
2234
|
let descriptions = [];
|
|
2113
2235
|
let transceivers = config.pc.getTransceivers();
|
|
2114
|
-
Object.keys(config.streamMap[this.id]).forEach(source => {
|
|
2236
|
+
Object.keys(config.streamMap[this.id]??{}).forEach(source => {
|
|
2115
2237
|
const simulcastConfigForSource = this.#findSimulcastConfig(source, this.simulcastSettings);
|
|
2116
2238
|
config.streamMap[this.id][source].forEach(trackId => {
|
|
2117
2239
|
let t = transceivers.find(transceiver => transceiver.sender.track && transceiver.sender.track.id === trackId)
|
|
@@ -2157,6 +2279,7 @@ class RoomSession {
|
|
|
2157
2279
|
}
|
|
2158
2280
|
this.emit('iceState', [handleId, handleId === this.#publisherHandle?.handleId, config.pc.iceConnectionState]);
|
|
2159
2281
|
};
|
|
2282
|
+
|
|
2160
2283
|
config.pc.onicecandidate = (event) => {
|
|
2161
2284
|
if (event.candidate == null || (adapter.browserDetails.browser === 'edge' && event.candidate.candidate.indexOf('endOfCandidates') > 0)) {
|
|
2162
2285
|
config.iceDone = true;
|
|
@@ -2409,9 +2532,6 @@ class RoomSession {
|
|
|
2409
2532
|
|
|
2410
2533
|
config.isIceRestarting = true;
|
|
2411
2534
|
|
|
2412
|
-
// removing this so we can cache ice candidates again
|
|
2413
|
-
config.remoteSdp = null;
|
|
2414
|
-
|
|
2415
2535
|
if (this.handleId === handleId) {
|
|
2416
2536
|
this._log('Performing local ICE restart');
|
|
2417
2537
|
let hasAudio = !!(config.stream && config.stream.getAudioTracks().length > 0);
|
|
@@ -2604,6 +2724,9 @@ class RoomSession {
|
|
|
2604
2724
|
}
|
|
2605
2725
|
|
|
2606
2726
|
#publishRemote(handleId, jsep) {
|
|
2727
|
+
|
|
2728
|
+
console.log('picaaaa');
|
|
2729
|
+
|
|
2607
2730
|
let handle = this.#getHandle(handleId);
|
|
2608
2731
|
if (!handle) {
|
|
2609
2732
|
return Promise.reject({
|
|
@@ -2682,7 +2805,7 @@ class RoomSession {
|
|
|
2682
2805
|
if (!config.stream) {
|
|
2683
2806
|
return;
|
|
2684
2807
|
}
|
|
2685
|
-
let sourceTrackIds = (config.streamMap[this.id][source] || []);
|
|
2808
|
+
let sourceTrackIds = (config.streamMap[this.id]?.[source] || []);
|
|
2686
2809
|
let remainingTracks = [];
|
|
2687
2810
|
for(let i = 0; i < sourceTrackIds.length; i++) {
|
|
2688
2811
|
let foundTrack = config.tracks.find(t => t.id === sourceTrackIds[i]);
|
|
@@ -2752,7 +2875,7 @@ class RoomSession {
|
|
|
2752
2875
|
let existingTracks = [...(config.streamMap?.[this.id]?.[source] || [])];
|
|
2753
2876
|
|
|
2754
2877
|
if(stream?.getTracks().length) {
|
|
2755
|
-
if(!config.streamMap[this.id]) {
|
|
2878
|
+
if(!config.streamMap?.[this.id]) {
|
|
2756
2879
|
config.streamMap[this.id] = {};
|
|
2757
2880
|
}
|
|
2758
2881
|
config.streamMap[this.id][source] = stream?.getTracks()?.map(track => track.id) || [];
|
|
@@ -2772,8 +2895,8 @@ class RoomSession {
|
|
|
2772
2895
|
} catch (e) {
|
|
2773
2896
|
this._log(e);
|
|
2774
2897
|
}
|
|
2775
|
-
config
|
|
2776
|
-
config?.tracks
|
|
2898
|
+
config?.stream?.removeTrack(oldAudioStream);
|
|
2899
|
+
config?.tracks?.splice(oldAudioStreamIndex, 1);
|
|
2777
2900
|
}
|
|
2778
2901
|
|
|
2779
2902
|
// remove old video track related to this source
|
|
@@ -2860,7 +2983,7 @@ class RoomSession {
|
|
|
2860
2983
|
// we possibly created new transceivers, so we need to get them again
|
|
2861
2984
|
|
|
2862
2985
|
transceivers = config.pc.getTransceivers();
|
|
2863
|
-
existingTracks = [...(config.streamMap[this.id][source] || [])];
|
|
2986
|
+
existingTracks = [...(config.streamMap[this.id]?.[source] || [])];
|
|
2864
2987
|
if(!audioTransceiver) {
|
|
2865
2988
|
audioTransceiver = transceivers.find(transceiver => transceiver.sender.track && transceiver.sender.track.kind === 'audio' && existingTracks.includes(transceiver.sender.track.id))
|
|
2866
2989
|
}
|
|
@@ -2919,7 +3042,7 @@ class RoomSession {
|
|
|
2919
3042
|
}
|
|
2920
3043
|
|
|
2921
3044
|
this.isMuted = [];
|
|
2922
|
-
for(const source of Object.keys(config.streamMap[this.id])) {
|
|
3045
|
+
for(const source of Object.keys(config.streamMap[this.id]??{})) {
|
|
2923
3046
|
const audioTrack = config.stream?.getAudioTracks()?.find(track => config.streamMap[this.id][source].includes(track.id));
|
|
2924
3047
|
const videoTrack = config.stream?.getVideoTracks()?.find(track => config.streamMap[this.id][source].includes(track.id));
|
|
2925
3048
|
this.isMuted.push({type: 'audio', value: !audioTrack || !audioTrack.enabled, source, mid: transceivers.find(transceiver => transceiver.sender?.track?.kind === 'audio' && transceiver.sender?.track?.id === audioTrack?.id)?.mid});
|
|
@@ -3003,7 +3126,7 @@ class RoomSession {
|
|
|
3003
3126
|
let transceivers = config.pc?.getTransceivers();
|
|
3004
3127
|
let transceiver = null;
|
|
3005
3128
|
if(source) {
|
|
3006
|
-
transceiver = transceivers?.find(t => t.sender && t.sender.track && t.receiver.track.kind === "audio" && (config.streamMap[this.id][source] || []).includes(t.sender.track.id));
|
|
3129
|
+
transceiver = transceivers?.find(t => t.sender && t.sender.track && t.receiver.track.kind === "audio" && (config.streamMap[this.id]?.[source] || []).includes(t.sender.track.id));
|
|
3007
3130
|
}
|
|
3008
3131
|
else {
|
|
3009
3132
|
transceiver = transceivers?.find(t => t.sender && t.sender.track && t.receiver.track.kind === "audio" && (mid ? t.mid === mid : true));
|
|
@@ -3013,7 +3136,7 @@ class RoomSession {
|
|
|
3013
3136
|
}
|
|
3014
3137
|
|
|
3015
3138
|
this.isMuted = [];
|
|
3016
|
-
for(const source of Object.keys(config.streamMap[this.id])) {
|
|
3139
|
+
for(const source of Object.keys(config.streamMap[this.id]??{})) {
|
|
3017
3140
|
const audioTrack = config.stream?.getAudioTracks()?.find(track => config.streamMap[this.id][source].includes(track.id));
|
|
3018
3141
|
const audioTransceiver = transceivers?.find(transceiver => transceiver.sender.track && transceiver.sender.track.kind === 'audio' && transceiver.sender.track.id === audioTrack?.id);
|
|
3019
3142
|
const videoTrack = config.stream?.getVideoTracks()?.find(track => config.streamMap[this.id][source].includes(track.id));
|
|
@@ -3040,7 +3163,7 @@ class RoomSession {
|
|
|
3040
3163
|
let transceivers = config.pc?.getTransceivers();
|
|
3041
3164
|
let transceiver = null;
|
|
3042
3165
|
if(source) {
|
|
3043
|
-
transceiver = transceivers?.find(t => t.sender && t.sender.track && t.receiver.track.kind === "video" && (config.streamMap[this.id][source] || []).includes(t.sender.track.id));
|
|
3166
|
+
transceiver = transceivers?.find(t => t.sender && t.sender.track && t.receiver.track.kind === "video" && (config.streamMap[this.id]?.[source] || []).includes(t.sender.track.id));
|
|
3044
3167
|
}
|
|
3045
3168
|
else {
|
|
3046
3169
|
transceiver = transceivers?.find(t => t.sender && t.sender.track && t.receiver.track.kind === "video" && (mid ? t.mid === mid : true));
|
|
@@ -3049,7 +3172,7 @@ class RoomSession {
|
|
|
3049
3172
|
transceiver.sender.track.enabled = value !== null ? !!value : !transceiver.sender.track.enabled;
|
|
3050
3173
|
}
|
|
3051
3174
|
this.isMuted = [];
|
|
3052
|
-
for(const source of Object.keys(config.streamMap[this.id])) {
|
|
3175
|
+
for(const source of Object.keys(config.streamMap[this.id]??{})) {
|
|
3053
3176
|
const audioTrack = config.stream?.getAudioTracks()?.find(track => config.streamMap[this.id][source].includes(track.id));
|
|
3054
3177
|
const audioTransceiver = transceivers?.find(transceiver => transceiver.sender.track && transceiver.sender.track.kind === 'audio' && transceiver.sender.track.id === audioTrack?.id);
|
|
3055
3178
|
const videoTrack = config.stream?.getVideoTracks()?.find(track => config.streamMap[this.id][source].includes(track.id));
|
|
@@ -3172,7 +3295,7 @@ class RoomSession {
|
|
|
3172
3295
|
let config = handle.webrtcStuff;
|
|
3173
3296
|
let descriptions = [];
|
|
3174
3297
|
let transceivers = config.pc.getTransceivers();
|
|
3175
|
-
Object.keys(config.streamMap[this.id]).forEach(source => {
|
|
3298
|
+
Object.keys(config.streamMap[this.id]??{}).forEach(source => {
|
|
3176
3299
|
const simulcastConfigForSource = this.#findSimulcastConfig(source, this.simulcastSettings);
|
|
3177
3300
|
config.streamMap[this.id][source].forEach(trackId => {
|
|
3178
3301
|
let t = transceivers.find(transceiver => transceiver.sender.track && transceiver.sender.track.id === trackId)
|