@stream-io/video-client 0.0.13 → 0.0.15
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/CHANGELOG.md +14 -0
- package/dist/index.browser.es.js +237 -130
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +239 -129
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +237 -130
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +2 -1
- package/dist/src/StreamSfuClient.d.ts +1 -0
- package/dist/src/StreamVideoClient.d.ts +5 -1
- package/dist/src/coordinator/connection/types.d.ts +3 -2
- package/dist/src/coordinator/connection/utils.d.ts +2 -1
- package/dist/src/logger.d.ts +4 -0
- package/dist/src/rtc/Dispatcher.d.ts +2 -0
- package/dist/src/rtc/IceTrickleBuffer.d.ts +2 -0
- package/dist/src/rtc/publisher.d.ts +1 -0
- package/dist/src/store/CallState.d.ts +2 -0
- package/dist/src/types.d.ts +1 -1
- package/index.ts +1 -0
- package/package.json +1 -1
- package/src/Call.ts +69 -42
- package/src/StreamSfuClient.ts +70 -29
- package/src/StreamVideoClient.ts +46 -3
- package/src/coordinator/connection/client.ts +22 -29
- package/src/coordinator/connection/connection.ts +2 -3
- package/src/coordinator/connection/connection_fallback.ts +0 -1
- package/src/coordinator/connection/types.ts +4 -2
- package/src/coordinator/connection/utils.ts +5 -2
- package/src/devices/devices.ts +10 -3
- package/src/events/__tests__/call-permissions.test.ts +2 -2
- package/src/events/call.ts +11 -4
- package/src/events/sessions.ts +7 -2
- package/src/logger.ts +45 -0
- package/src/rtc/Dispatcher.ts +14 -4
- package/src/rtc/IceTrickleBuffer.ts +8 -1
- package/src/rtc/__tests__/publisher.test.ts +1 -1
- package/src/rtc/codecs.ts +7 -5
- package/src/rtc/flows/join.ts +4 -1
- package/src/rtc/publisher.ts +31 -12
- package/src/rtc/signal.ts +8 -7
- package/src/rtc/subscriber.ts +16 -10
- package/src/stats/state-store-stats-reporter.ts +12 -4
- package/src/store/CallState.ts +7 -2
- package/src/types.ts +3 -2
package/dist/index.cjs.js
CHANGED
|
@@ -4250,7 +4250,7 @@ exports.DebounceType = void 0;
|
|
|
4250
4250
|
DebounceType[DebounceType["SLOW"] = 1200] = "SLOW";
|
|
4251
4251
|
})(exports.DebounceType || (exports.DebounceType = {}));
|
|
4252
4252
|
const isStreamVideoLocalParticipant = (p) => {
|
|
4253
|
-
return !!p.
|
|
4253
|
+
return !!p.isLocalParticipant;
|
|
4254
4254
|
};
|
|
4255
4255
|
|
|
4256
4256
|
/******************************************************************************
|
|
@@ -5277,13 +5277,41 @@ const toggleDtx = (sdp, enable) => {
|
|
|
5277
5277
|
return sdp;
|
|
5278
5278
|
};
|
|
5279
5279
|
|
|
5280
|
+
let logger;
|
|
5281
|
+
const logToConsole = (logLevel, message, extraData, tags) => {
|
|
5282
|
+
let logMethod;
|
|
5283
|
+
if (logLevel === 'error') {
|
|
5284
|
+
logMethod = console.error;
|
|
5285
|
+
}
|
|
5286
|
+
else if (logLevel === 'warn') {
|
|
5287
|
+
logMethod = console.warn;
|
|
5288
|
+
}
|
|
5289
|
+
else {
|
|
5290
|
+
logMethod = console.log;
|
|
5291
|
+
}
|
|
5292
|
+
logMethod(logLevel, `${tags === null || tags === void 0 ? void 0 : tags.join(':')} - ${message}`, extraData ? extraData : '');
|
|
5293
|
+
};
|
|
5294
|
+
const setLogger = (l) => {
|
|
5295
|
+
logger = l;
|
|
5296
|
+
};
|
|
5297
|
+
const getLogger = (withTags) => {
|
|
5298
|
+
const loggerMethod = logger || (() => { });
|
|
5299
|
+
const result = (logLevel, messeage, extraData, tags) => {
|
|
5300
|
+
loggerMethod(logLevel, messeage, extraData, [
|
|
5301
|
+
...(tags || []),
|
|
5302
|
+
...(withTags || []),
|
|
5303
|
+
]);
|
|
5304
|
+
};
|
|
5305
|
+
return result;
|
|
5306
|
+
};
|
|
5307
|
+
|
|
5280
5308
|
const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
|
|
5309
|
+
const logger = getLogger(['codecs']);
|
|
5281
5310
|
if (!('getCapabilities' in RTCRtpSender)) {
|
|
5282
|
-
|
|
5311
|
+
logger === null || logger === void 0 ? void 0 : logger('warn', 'RTCRtpSender.getCapabilities is not supported');
|
|
5283
5312
|
return;
|
|
5284
5313
|
}
|
|
5285
5314
|
const cap = RTCRtpSender.getCapabilities(kind);
|
|
5286
|
-
console.log('s4e');
|
|
5287
5315
|
if (!cap)
|
|
5288
5316
|
return;
|
|
5289
5317
|
const matched = [];
|
|
@@ -5291,7 +5319,7 @@ const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
|
|
|
5291
5319
|
const unmatched = [];
|
|
5292
5320
|
cap.codecs.forEach((c) => {
|
|
5293
5321
|
const codec = c.mimeType.toLowerCase();
|
|
5294
|
-
|
|
5322
|
+
logger === null || logger === void 0 ? void 0 : logger('debug', `Found supported codec: ${codec}`);
|
|
5295
5323
|
const shouldRemoveCodec = codecToRemove && codec === `${kind}/${codecToRemove}`;
|
|
5296
5324
|
if (shouldRemoveCodec)
|
|
5297
5325
|
return;
|
|
@@ -5311,10 +5339,11 @@ const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
|
|
|
5311
5339
|
}
|
|
5312
5340
|
return;
|
|
5313
5341
|
}
|
|
5314
|
-
console.log('matched', matched);
|
|
5315
5342
|
matched.push(c);
|
|
5316
5343
|
});
|
|
5317
|
-
|
|
5344
|
+
const result = [...matched, ...partialMatched, ...unmatched];
|
|
5345
|
+
logger === null || logger === void 0 ? void 0 : logger('info', `Preffered codecs: `, result);
|
|
5346
|
+
return result;
|
|
5318
5347
|
};
|
|
5319
5348
|
const getGenericSdp = (direction, isRedEnabled, preferredVideoCodec) => __awaiter(void 0, void 0, void 0, function* () {
|
|
5320
5349
|
var _a;
|
|
@@ -5380,17 +5409,19 @@ class Dispatcher {
|
|
|
5380
5409
|
constructor() {
|
|
5381
5410
|
this.subscribers = {};
|
|
5382
5411
|
this.dispatch = (message) => {
|
|
5412
|
+
var _a, _b;
|
|
5383
5413
|
const eventKind = message.eventPayload.oneofKind;
|
|
5384
5414
|
if (eventKind) {
|
|
5385
|
-
|
|
5386
|
-
|
|
5415
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'info', `Dispatching ${eventKind}`);
|
|
5416
|
+
(_b = this.logger) === null || _b === void 0 ? void 0 : _b.call(this, 'debug', `Event payload`, message.eventPayload[eventKind]);
|
|
5387
5417
|
const listeners = this.subscribers[eventKind];
|
|
5388
5418
|
listeners === null || listeners === void 0 ? void 0 : listeners.forEach((fn) => {
|
|
5419
|
+
var _a;
|
|
5389
5420
|
try {
|
|
5390
5421
|
fn(message);
|
|
5391
5422
|
}
|
|
5392
5423
|
catch (e) {
|
|
5393
|
-
|
|
5424
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'warn', 'Listener failed with error', e);
|
|
5394
5425
|
}
|
|
5395
5426
|
});
|
|
5396
5427
|
}
|
|
@@ -5414,6 +5445,7 @@ class Dispatcher {
|
|
|
5414
5445
|
this.subscribers = {};
|
|
5415
5446
|
}
|
|
5416
5447
|
};
|
|
5448
|
+
this.logger = getLogger(['sfu-client']);
|
|
5417
5449
|
}
|
|
5418
5450
|
}
|
|
5419
5451
|
|
|
@@ -5426,6 +5458,7 @@ class IceTrickleBuffer {
|
|
|
5426
5458
|
this.subscriberCandidates = new rxjs.ReplaySubject();
|
|
5427
5459
|
this.publisherCandidates = new rxjs.ReplaySubject();
|
|
5428
5460
|
this.push = (iceTrickle) => {
|
|
5461
|
+
var _a;
|
|
5429
5462
|
if (iceTrickle.peerType === PeerType.SUBSCRIBER) {
|
|
5430
5463
|
this.subscriberCandidates.next(iceTrickle);
|
|
5431
5464
|
}
|
|
@@ -5433,9 +5466,10 @@ class IceTrickleBuffer {
|
|
|
5433
5466
|
this.publisherCandidates.next(iceTrickle);
|
|
5434
5467
|
}
|
|
5435
5468
|
else {
|
|
5436
|
-
|
|
5469
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'warn', `ICETrickle, Unknown peer type`, iceTrickle);
|
|
5437
5470
|
}
|
|
5438
5471
|
};
|
|
5472
|
+
this.logger = getLogger(['sfu-client']);
|
|
5439
5473
|
}
|
|
5440
5474
|
}
|
|
5441
5475
|
|
|
@@ -5626,6 +5660,7 @@ class Publisher {
|
|
|
5626
5660
|
* @param opts
|
|
5627
5661
|
*/
|
|
5628
5662
|
this.publishStream = (mediaStream, track, trackType, opts = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
5663
|
+
var _a;
|
|
5629
5664
|
let transceiver = this.publisher
|
|
5630
5665
|
.getTransceivers()
|
|
5631
5666
|
.find((t) => {
|
|
@@ -5639,7 +5674,8 @@ class Publisher {
|
|
|
5639
5674
|
* Once the track has ended, it will notify the SFU and update the state.
|
|
5640
5675
|
*/
|
|
5641
5676
|
const handleTrackEnded = () => __awaiter(this, void 0, void 0, function* () {
|
|
5642
|
-
|
|
5677
|
+
var _b;
|
|
5678
|
+
(_b = this.logger) === null || _b === void 0 ? void 0 : _b.call(this, 'info', `Track ${TrackType[trackType]} has ended, notifying the SFU`);
|
|
5643
5679
|
yield this.notifyTrackMuteStateChanged(mediaStream, track, trackType, true);
|
|
5644
5680
|
// clean-up, this event listener needs to run only once.
|
|
5645
5681
|
track.removeEventListener('ended', handleTrackEnded);
|
|
@@ -5664,7 +5700,7 @@ class Publisher {
|
|
|
5664
5700
|
});
|
|
5665
5701
|
this.transceiverRegistry[trackType] = transceiver;
|
|
5666
5702
|
if ('setCodecPreferences' in transceiver && codecPreferences) {
|
|
5667
|
-
|
|
5703
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'info', `Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
|
|
5668
5704
|
transceiver.setCodecPreferences(codecPreferences);
|
|
5669
5705
|
}
|
|
5670
5706
|
}
|
|
@@ -5748,9 +5784,9 @@ class Publisher {
|
|
|
5748
5784
|
this.publisher.close();
|
|
5749
5785
|
};
|
|
5750
5786
|
this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
|
|
5751
|
-
var
|
|
5752
|
-
|
|
5753
|
-
const videoSender = (
|
|
5787
|
+
var _c, _d, _e, _f;
|
|
5788
|
+
(_c = this.logger) === null || _c === void 0 ? void 0 : _c.call(this, 'info', 'Update publish quality, requested rids by SFU:', enabledRids);
|
|
5789
|
+
const videoSender = (_d = this.transceiverRegistry[TrackType.VIDEO]) === null || _d === void 0 ? void 0 : _d.sender;
|
|
5754
5790
|
if (!videoSender)
|
|
5755
5791
|
return;
|
|
5756
5792
|
const params = videoSender.getParameters();
|
|
@@ -5765,10 +5801,10 @@ class Publisher {
|
|
|
5765
5801
|
});
|
|
5766
5802
|
if (changed) {
|
|
5767
5803
|
if (params.encodings.length === 0) {
|
|
5768
|
-
|
|
5804
|
+
(_e = this.logger) === null || _e === void 0 ? void 0 : _e.call(this, 'warn', 'No suitable video encoding quality found');
|
|
5769
5805
|
}
|
|
5770
5806
|
yield videoSender.setParameters(params);
|
|
5771
|
-
|
|
5807
|
+
(_f = this.logger) === null || _f === void 0 ? void 0 : _f.call(this, 'info', `Update publish quality, enabled rids: ${params.encodings
|
|
5772
5808
|
.filter((e) => e.active)
|
|
5773
5809
|
.map((e) => e.rid)
|
|
5774
5810
|
.join(', ')}`);
|
|
@@ -5785,9 +5821,10 @@ class Publisher {
|
|
|
5785
5821
|
}
|
|
5786
5822
|
};
|
|
5787
5823
|
this.onIceCandidate = (e) => __awaiter(this, void 0, void 0, function* () {
|
|
5824
|
+
var _g;
|
|
5788
5825
|
const { candidate } = e;
|
|
5789
5826
|
if (!candidate) {
|
|
5790
|
-
|
|
5827
|
+
(_g = this.logger) === null || _g === void 0 ? void 0 : _g.call(this, 'warn', 'null ice candidate');
|
|
5791
5828
|
return;
|
|
5792
5829
|
}
|
|
5793
5830
|
yield this.sfuClient.iceTrickle({
|
|
@@ -5796,7 +5833,8 @@ class Publisher {
|
|
|
5796
5833
|
});
|
|
5797
5834
|
});
|
|
5798
5835
|
this.onNegotiationNeeded = () => __awaiter(this, void 0, void 0, function* () {
|
|
5799
|
-
|
|
5836
|
+
var _h, _j;
|
|
5837
|
+
(_h = this.logger) === null || _h === void 0 ? void 0 : _h.call(this, 'info', 'AAA onNegotiationNeeded');
|
|
5800
5838
|
const offer = yield this.publisher.createOffer();
|
|
5801
5839
|
let sdp = offer.sdp;
|
|
5802
5840
|
if (sdp) {
|
|
@@ -5859,28 +5897,38 @@ class Publisher {
|
|
|
5859
5897
|
});
|
|
5860
5898
|
}
|
|
5861
5899
|
catch (e) {
|
|
5862
|
-
|
|
5900
|
+
(_j = this.logger) === null || _j === void 0 ? void 0 : _j.call(this, 'error', `Publisher: setRemoteDescription error`, {
|
|
5901
|
+
sdp: response.sdp,
|
|
5902
|
+
error: e,
|
|
5903
|
+
});
|
|
5863
5904
|
}
|
|
5864
5905
|
this.sfuClient.iceTrickleBuffer.publisherCandidates.subscribe((candidate) => __awaiter(this, void 0, void 0, function* () {
|
|
5906
|
+
var _k;
|
|
5865
5907
|
try {
|
|
5866
5908
|
const iceCandidate = JSON.parse(candidate.iceCandidate);
|
|
5867
5909
|
yield this.publisher.addIceCandidate(iceCandidate);
|
|
5868
5910
|
}
|
|
5869
5911
|
catch (e) {
|
|
5870
|
-
|
|
5912
|
+
(_k = this.logger) === null || _k === void 0 ? void 0 : _k.call(this, 'error', `Publisher: ICE candidate error`, {
|
|
5913
|
+
error: e,
|
|
5914
|
+
candidate,
|
|
5915
|
+
});
|
|
5871
5916
|
}
|
|
5872
5917
|
}));
|
|
5873
5918
|
});
|
|
5874
5919
|
this.onIceCandidateError = (e) => {
|
|
5920
|
+
var _a;
|
|
5875
5921
|
const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
|
|
5876
5922
|
`${e.errorCode}: ${e.errorText}`;
|
|
5877
|
-
|
|
5923
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Candidate error`, errorMessage);
|
|
5878
5924
|
};
|
|
5879
5925
|
this.onIceConnectionStateChange = () => {
|
|
5880
|
-
|
|
5926
|
+
var _a;
|
|
5927
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Connection state changed`, this.publisher.iceConnectionState);
|
|
5881
5928
|
};
|
|
5882
5929
|
this.onIceGatheringStateChange = () => {
|
|
5883
|
-
|
|
5930
|
+
var _a;
|
|
5931
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Gathering State`, this.publisher.iceGatheringState);
|
|
5884
5932
|
};
|
|
5885
5933
|
this.ridToVideoQuality = (rid) => {
|
|
5886
5934
|
return rid === 'q'
|
|
@@ -5913,12 +5961,13 @@ class Publisher {
|
|
|
5913
5961
|
}
|
|
5914
5962
|
|
|
5915
5963
|
const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, }) => {
|
|
5964
|
+
const logger = getLogger(['sfu-client']);
|
|
5916
5965
|
const subscriber = new RTCPeerConnection(connectionConfig);
|
|
5917
5966
|
attachDebugEventListeners(subscriber);
|
|
5918
5967
|
subscriber.addEventListener('icecandidate', (e) => __awaiter(void 0, void 0, void 0, function* () {
|
|
5919
5968
|
const { candidate } = e;
|
|
5920
5969
|
if (!candidate) {
|
|
5921
|
-
|
|
5970
|
+
logger === null || logger === void 0 ? void 0 : logger('warn', 'null ice candidate');
|
|
5922
5971
|
return;
|
|
5923
5972
|
}
|
|
5924
5973
|
yield sfuClient.iceTrickle({
|
|
@@ -5934,7 +5983,7 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
|
|
|
5934
5983
|
if (message.eventPayload.oneofKind !== 'subscriberOffer')
|
|
5935
5984
|
return;
|
|
5936
5985
|
const { subscriberOffer } = message.eventPayload;
|
|
5937
|
-
|
|
5986
|
+
logger === null || logger === void 0 ? void 0 : logger('info', 'Received subscriberOffer', subscriberOffer);
|
|
5938
5987
|
yield subscriber.setRemoteDescription({
|
|
5939
5988
|
type: 'offer',
|
|
5940
5989
|
sdp: subscriberOffer.sdp,
|
|
@@ -5945,7 +5994,10 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
|
|
|
5945
5994
|
yield subscriber.addIceCandidate(iceCandidate);
|
|
5946
5995
|
}
|
|
5947
5996
|
catch (e) {
|
|
5948
|
-
|
|
5997
|
+
logger === null || logger === void 0 ? void 0 : logger('error', `Subscriber: ICE candidate error`, {
|
|
5998
|
+
error: e,
|
|
5999
|
+
candidate,
|
|
6000
|
+
});
|
|
5949
6001
|
}
|
|
5950
6002
|
}));
|
|
5951
6003
|
// apply ice candidates
|
|
@@ -5968,31 +6020,33 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
|
|
|
5968
6020
|
return subscriber;
|
|
5969
6021
|
};
|
|
5970
6022
|
const attachDebugEventListeners = (subscriber) => {
|
|
6023
|
+
const logger = getLogger(['sfu-client']);
|
|
5971
6024
|
subscriber.addEventListener('icecandidateerror', (e) => {
|
|
5972
6025
|
const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
|
|
5973
6026
|
`${e.errorCode}: ${e.errorText}`;
|
|
5974
|
-
|
|
6027
|
+
logger === null || logger === void 0 ? void 0 : logger('error', `Subscriber: ICE Candidate error: ${errorMessage}`);
|
|
5975
6028
|
});
|
|
5976
6029
|
subscriber.addEventListener('iceconnectionstatechange', () => {
|
|
5977
|
-
|
|
6030
|
+
logger === null || logger === void 0 ? void 0 : logger('info', `Subscriber: ICE Connection state changed: ${subscriber.iceConnectionState}`);
|
|
5978
6031
|
});
|
|
5979
6032
|
subscriber.addEventListener('icegatheringstatechange', () => {
|
|
5980
|
-
|
|
6033
|
+
logger === null || logger === void 0 ? void 0 : logger('info', `Subscriber: ICE Gathering State: ${subscriber.iceGatheringState}`);
|
|
5981
6034
|
});
|
|
5982
6035
|
};
|
|
5983
6036
|
|
|
5984
6037
|
const createWebSocketSignalChannel = (opts) => {
|
|
6038
|
+
const logger = getLogger(['sfu-client']);
|
|
5985
6039
|
const { endpoint, onMessage } = opts;
|
|
5986
6040
|
const ws = new WebSocket(endpoint);
|
|
5987
6041
|
ws.binaryType = 'arraybuffer'; // do we need this?
|
|
5988
6042
|
ws.addEventListener('error', (e) => {
|
|
5989
|
-
|
|
6043
|
+
logger === null || logger === void 0 ? void 0 : logger('error', 'Signaling WS channel error', e);
|
|
5990
6044
|
});
|
|
5991
6045
|
ws.addEventListener('close', (e) => {
|
|
5992
|
-
|
|
6046
|
+
logger === null || logger === void 0 ? void 0 : logger('info', 'Signaling WS channel is closed', e);
|
|
5993
6047
|
});
|
|
5994
6048
|
ws.addEventListener('open', (e) => {
|
|
5995
|
-
|
|
6049
|
+
logger === null || logger === void 0 ? void 0 : logger('info', 'Signaling WS channel is open', e);
|
|
5996
6050
|
});
|
|
5997
6051
|
if (onMessage) {
|
|
5998
6052
|
ws.addEventListener('message', (e) => {
|
|
@@ -6003,7 +6057,7 @@ const createWebSocketSignalChannel = (opts) => {
|
|
|
6003
6057
|
onMessage(message);
|
|
6004
6058
|
}
|
|
6005
6059
|
catch (err) {
|
|
6006
|
-
|
|
6060
|
+
logger === null || logger === void 0 ? void 0 : logger('error', 'Failed to decode a message. Check whether the Proto models match.', { event: e, error: err });
|
|
6007
6061
|
}
|
|
6008
6062
|
});
|
|
6009
6063
|
}
|
|
@@ -6104,14 +6158,14 @@ function convertErrorToJson(err) {
|
|
|
6104
6158
|
* isOnline safely return the navigator.online value for browser env
|
|
6105
6159
|
* if navigator is not in global object, it always return true
|
|
6106
6160
|
*/
|
|
6107
|
-
function isOnline() {
|
|
6161
|
+
function isOnline(logger) {
|
|
6108
6162
|
const nav = typeof navigator !== 'undefined'
|
|
6109
6163
|
? navigator
|
|
6110
6164
|
: typeof window !== 'undefined' && window.navigator
|
|
6111
6165
|
? window.navigator
|
|
6112
6166
|
: undefined;
|
|
6113
6167
|
if (!nav) {
|
|
6114
|
-
|
|
6168
|
+
logger('warn', 'isOnline failed to access window.navigator and assume browser is online');
|
|
6115
6169
|
return true;
|
|
6116
6170
|
}
|
|
6117
6171
|
// RN navigator has undefined for onLine
|
|
@@ -6167,16 +6221,16 @@ class StreamSfuClient {
|
|
|
6167
6221
|
return retryable(() => this.rpc.updateSubscriptions({
|
|
6168
6222
|
sessionId: this.sessionId,
|
|
6169
6223
|
tracks: subscriptions,
|
|
6170
|
-
}));
|
|
6224
|
+
}), this.logger);
|
|
6171
6225
|
});
|
|
6172
6226
|
this.setPublisher = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6173
|
-
return retryable(() => this.rpc.setPublisher(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
6227
|
+
return retryable(() => this.rpc.setPublisher(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
6174
6228
|
});
|
|
6175
6229
|
this.sendAnswer = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6176
|
-
return retryable(() => this.rpc.sendAnswer(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
6230
|
+
return retryable(() => this.rpc.sendAnswer(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
6177
6231
|
});
|
|
6178
6232
|
this.iceTrickle = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6179
|
-
return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
6233
|
+
return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
6180
6234
|
});
|
|
6181
6235
|
this.updateMuteState = (trackType, muted) => __awaiter(this, void 0, void 0, function* () {
|
|
6182
6236
|
return this.updateMuteStates({
|
|
@@ -6189,7 +6243,7 @@ class StreamSfuClient {
|
|
|
6189
6243
|
});
|
|
6190
6244
|
});
|
|
6191
6245
|
this.updateMuteStates = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6192
|
-
return retryable(() => this.rpc.updateMuteStates(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
6246
|
+
return retryable(() => this.rpc.updateMuteStates(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
6193
6247
|
});
|
|
6194
6248
|
this.join = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6195
6249
|
const joinRequest = JoinRequest.create(Object.assign(Object.assign({}, data), { sessionId: this.sessionId, token: this.token }));
|
|
@@ -6210,7 +6264,7 @@ class StreamSfuClient {
|
|
|
6210
6264
|
clearInterval(this.keepAliveInterval);
|
|
6211
6265
|
}
|
|
6212
6266
|
this.keepAliveInterval = setInterval(() => {
|
|
6213
|
-
|
|
6267
|
+
this.logger('info', 'Sending healthCheckRequest to SFU');
|
|
6214
6268
|
const message = SfuRequest.create({
|
|
6215
6269
|
requestPayload: {
|
|
6216
6270
|
oneofKind: 'healthCheckRequest',
|
|
@@ -6228,7 +6282,7 @@ class StreamSfuClient {
|
|
|
6228
6282
|
if (this.lastMessageTimestamp) {
|
|
6229
6283
|
const timeSinceLastMessage = new Date().getTime() - this.lastMessageTimestamp.getTime();
|
|
6230
6284
|
if (timeSinceLastMessage > this.unhealthyTimeoutInMs) {
|
|
6231
|
-
|
|
6285
|
+
this.logger('error', 'SFU connection unhealthy, closing');
|
|
6232
6286
|
this.close(4001, `SFU connection unhealthy. Didn't receive any healthcheck messages for ${this.unhealthyTimeoutInMs}ms`);
|
|
6233
6287
|
}
|
|
6234
6288
|
}
|
|
@@ -6236,12 +6290,22 @@ class StreamSfuClient {
|
|
|
6236
6290
|
};
|
|
6237
6291
|
this.sessionId = sessionId || generateUUIDv4();
|
|
6238
6292
|
this.token = token;
|
|
6293
|
+
this.logger = getLogger(['sfu-client']);
|
|
6294
|
+
const logger = this.logger;
|
|
6295
|
+
const logInterceptor = {
|
|
6296
|
+
interceptUnary(next, method, input, options) {
|
|
6297
|
+
logger('info', `Calling SFU RPC method ${method.name}`);
|
|
6298
|
+
logger('debug', `Method call payload`, { input, options });
|
|
6299
|
+
return next(method, input, options);
|
|
6300
|
+
},
|
|
6301
|
+
};
|
|
6239
6302
|
this.rpc = createSignalClient({
|
|
6240
6303
|
baseUrl: url,
|
|
6241
6304
|
interceptors: [
|
|
6242
6305
|
withHeaders({
|
|
6243
6306
|
Authorization: `Bearer ${token}`,
|
|
6244
6307
|
}),
|
|
6308
|
+
logInterceptor,
|
|
6245
6309
|
],
|
|
6246
6310
|
});
|
|
6247
6311
|
// Special handling for the ICETrickle kind of events.
|
|
@@ -6283,7 +6347,7 @@ const MAX_RETRIES = 5;
|
|
|
6283
6347
|
* @param <I> the type of the request object.
|
|
6284
6348
|
* @param <O> the type of the response object.
|
|
6285
6349
|
*/
|
|
6286
|
-
const retryable = (rpc) => __awaiter(void 0, void 0, void 0, function* () {
|
|
6350
|
+
const retryable = (rpc, logger) => __awaiter(void 0, void 0, void 0, function* () {
|
|
6287
6351
|
var _a;
|
|
6288
6352
|
let retryAttempt = 0;
|
|
6289
6353
|
let rpcCallResult;
|
|
@@ -6293,9 +6357,11 @@ const retryable = (rpc) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
6293
6357
|
yield sleep(retryInterval(retryAttempt));
|
|
6294
6358
|
}
|
|
6295
6359
|
rpcCallResult = yield rpc();
|
|
6360
|
+
logger('info', `SFU RPC response received for ${rpcCallResult.method.name}`);
|
|
6361
|
+
logger('debug', `Response payload`, rpcCallResult);
|
|
6296
6362
|
// if the RPC call failed, log the error and retry
|
|
6297
6363
|
if (rpcCallResult.response.error) {
|
|
6298
|
-
|
|
6364
|
+
logger('error', 'SFU RPC Error:', rpcCallResult.response.error);
|
|
6299
6365
|
}
|
|
6300
6366
|
retryAttempt++;
|
|
6301
6367
|
} while (((_a = rpcCallResult.response.error) === null || _a === void 0 ? void 0 : _a.shouldRetry) &&
|
|
@@ -6978,7 +7044,7 @@ class CallState {
|
|
|
6978
7044
|
this.updateParticipant = (sessionId, patch) => {
|
|
6979
7045
|
const participant = this.findParticipantBySessionId(sessionId);
|
|
6980
7046
|
if (!participant) {
|
|
6981
|
-
|
|
7047
|
+
this.logger('warn', `Participant with sessionId ${sessionId} not found`);
|
|
6982
7048
|
return;
|
|
6983
7049
|
}
|
|
6984
7050
|
const thePatch = typeof patch === 'function' ? patch(participant) : patch;
|
|
@@ -7027,9 +7093,10 @@ class CallState {
|
|
|
7027
7093
|
return p;
|
|
7028
7094
|
}));
|
|
7029
7095
|
};
|
|
7096
|
+
this.logger = getLogger(['call-state']);
|
|
7030
7097
|
this.participants$ = this.participantsSubject.pipe(operators.map((ps) => ps.sort(this.sortParticipantsBy)));
|
|
7031
7098
|
this.localParticipant$ = this.participants$.pipe(operators.map((participants) => participants.find(isStreamVideoLocalParticipant)));
|
|
7032
|
-
this.remoteParticipants$ = this.participants$.pipe(operators.map((participants) => participants.filter((p) => !p.
|
|
7099
|
+
this.remoteParticipants$ = this.participants$.pipe(operators.map((participants) => participants.filter((p) => !p.isLocalParticipant)));
|
|
7033
7100
|
this.pinnedParticipants$ = this.participants$.pipe(operators.map((participants) => participants.filter((p) => p.pinnedAt)));
|
|
7034
7101
|
this.dominantSpeaker$ = this.participants$.pipe(operators.map((participants) => participants.find((p) => p.isDominantSpeaker)));
|
|
7035
7102
|
this.hasOngoingScreenShare$ = this.participants$.pipe(operators.map((participants) => {
|
|
@@ -7183,13 +7250,13 @@ const watchCallRejected = (call) => {
|
|
|
7183
7250
|
const { call: eventCall } = event;
|
|
7184
7251
|
const { session: callSession } = eventCall;
|
|
7185
7252
|
if (!callSession) {
|
|
7186
|
-
|
|
7253
|
+
call.logger('warn', 'No call session provided. Ignoring call.rejected event.', event);
|
|
7187
7254
|
return;
|
|
7188
7255
|
}
|
|
7189
7256
|
const rejectedBy = callSession.rejected_by;
|
|
7190
7257
|
const { members, callingState } = call.state;
|
|
7191
7258
|
if (callingState !== exports.CallingState.RINGING) {
|
|
7192
|
-
|
|
7259
|
+
call.logger('warn', 'Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.', event);
|
|
7193
7260
|
return;
|
|
7194
7261
|
}
|
|
7195
7262
|
if (call.isCreatedByMe) {
|
|
@@ -7197,13 +7264,13 @@ const watchCallRejected = (call) => {
|
|
|
7197
7264
|
.filter((m) => m.user_id !== call.currentUserId)
|
|
7198
7265
|
.every((m) => rejectedBy[m.user_id]);
|
|
7199
7266
|
if (everyoneElseRejected) {
|
|
7200
|
-
|
|
7267
|
+
call.logger('info', 'everyone rejected, leaving the call');
|
|
7201
7268
|
yield call.leave();
|
|
7202
7269
|
}
|
|
7203
7270
|
}
|
|
7204
7271
|
else {
|
|
7205
7272
|
if (rejectedBy[eventCall.created_by.id]) {
|
|
7206
|
-
|
|
7273
|
+
call.logger('info', 'call creator rejected, leaving call');
|
|
7207
7274
|
yield call.leave();
|
|
7208
7275
|
}
|
|
7209
7276
|
}
|
|
@@ -7611,7 +7678,7 @@ const watchCallSessionParticipantJoined = (state) => {
|
|
|
7611
7678
|
const { user } = event;
|
|
7612
7679
|
state.setMetadata((metadata) => {
|
|
7613
7680
|
if (!metadata || !metadata.session) {
|
|
7614
|
-
|
|
7681
|
+
state.logger('warn', `Received call.session_participant_joined event but the metadata structure is invalid.`, event);
|
|
7615
7682
|
return metadata;
|
|
7616
7683
|
}
|
|
7617
7684
|
const { session } = metadata;
|
|
@@ -7639,7 +7706,7 @@ const watchCallSessionParticipantLeft = (state) => {
|
|
|
7639
7706
|
const { user } = event;
|
|
7640
7707
|
state.setMetadata((metadata) => {
|
|
7641
7708
|
if (!metadata || !metadata.session) {
|
|
7642
|
-
|
|
7709
|
+
state.logger('warn', `Received call.session_participant_left event but the metadata structure is invalid.`, event);
|
|
7643
7710
|
return metadata;
|
|
7644
7711
|
}
|
|
7645
7712
|
const { session } = metadata;
|
|
@@ -7784,16 +7851,18 @@ const getLocationHint = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
7784
7851
|
const hintURL = `https://hint.stream-io-video.com/`;
|
|
7785
7852
|
const abortController = new AbortController();
|
|
7786
7853
|
const timeoutId = setTimeout(() => abortController.abort(), 1000);
|
|
7854
|
+
const logger = getLogger(['call']);
|
|
7787
7855
|
try {
|
|
7788
7856
|
const response = yield fetch(hintURL, {
|
|
7789
7857
|
method: 'HEAD',
|
|
7790
7858
|
signal: abortController.signal,
|
|
7791
7859
|
});
|
|
7792
7860
|
const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
|
|
7861
|
+
logger === null || logger === void 0 ? void 0 : logger('info', `Location header: ${awsPop}`);
|
|
7793
7862
|
return awsPop.substring(0, 3); // AMS1-P2 -> AMS
|
|
7794
7863
|
}
|
|
7795
7864
|
catch (e) {
|
|
7796
|
-
|
|
7865
|
+
logger === null || logger === void 0 ? void 0 : logger('error', `Failed to get location hint from ${hintURL}`, e);
|
|
7797
7866
|
return 'ERR';
|
|
7798
7867
|
}
|
|
7799
7868
|
finally {
|
|
@@ -7832,6 +7901,7 @@ const getCascadingModeParams = () => {
|
|
|
7832
7901
|
* Creates a new StatsReporter instance that collects metrics about the ongoing call and reports them to the state store
|
|
7833
7902
|
*/
|
|
7834
7903
|
const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIntervalInMs = 2000, }) => {
|
|
7904
|
+
const logger = getLogger(['stats']);
|
|
7835
7905
|
const getRawStatsForTrack = (kind, selector) => __awaiter(void 0, void 0, void 0, function* () {
|
|
7836
7906
|
if (kind === 'subscriber' && subscriber) {
|
|
7837
7907
|
return subscriber.getStats(selector);
|
|
@@ -7840,7 +7910,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
|
|
|
7840
7910
|
return publisher.getStats(selector);
|
|
7841
7911
|
}
|
|
7842
7912
|
else {
|
|
7843
|
-
|
|
7913
|
+
logger('warn', `Can't retrieve RTC stats for ${kind}`);
|
|
7844
7914
|
return undefined;
|
|
7845
7915
|
}
|
|
7846
7916
|
});
|
|
@@ -7878,7 +7948,9 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
|
|
|
7878
7948
|
for (let participant of state.participants) {
|
|
7879
7949
|
if (!sessionIds.has(participant.sessionId))
|
|
7880
7950
|
continue;
|
|
7881
|
-
const kind = participant.
|
|
7951
|
+
const kind = participant.isLocalParticipant
|
|
7952
|
+
? 'publisher'
|
|
7953
|
+
: 'subscriber';
|
|
7882
7954
|
try {
|
|
7883
7955
|
const mergedStream = new MediaStream([
|
|
7884
7956
|
...(((_a = participant.videoStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()) || []),
|
|
@@ -7890,7 +7962,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
|
|
|
7890
7962
|
});
|
|
7891
7963
|
}
|
|
7892
7964
|
catch (e) {
|
|
7893
|
-
|
|
7965
|
+
logger('error', `Failed to collect stats for ${kind} if ${participant.userId}`, e);
|
|
7894
7966
|
}
|
|
7895
7967
|
}
|
|
7896
7968
|
}
|
|
@@ -7928,7 +8000,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
|
|
|
7928
8000
|
if (pollingIntervalInMs > 0) {
|
|
7929
8001
|
const loop = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
7930
8002
|
yield run().catch((e) => {
|
|
7931
|
-
|
|
8003
|
+
logger('warn', 'Failed to collect stats', e);
|
|
7932
8004
|
});
|
|
7933
8005
|
timeoutId = setTimeout(loop, pollingIntervalInMs);
|
|
7934
8006
|
});
|
|
@@ -8471,6 +8543,9 @@ class Call {
|
|
|
8471
8543
|
if ([exports.CallingState.JOINED, exports.CallingState.JOINING].includes(this.state.callingState)) {
|
|
8472
8544
|
throw new Error(`Illegal State: Already joined.`);
|
|
8473
8545
|
}
|
|
8546
|
+
if (this.state.callingState === exports.CallingState.LEFT) {
|
|
8547
|
+
throw new Error('Illegal State: Cannot join already left call. Create a new Call instance to join a call.');
|
|
8548
|
+
}
|
|
8474
8549
|
const previousCallingState = this.state.callingState;
|
|
8475
8550
|
this.state.setCallingState(exports.CallingState.JOINING);
|
|
8476
8551
|
if ((data === null || data === void 0 ? void 0 : data.ring) && !this.ringing) {
|
|
@@ -8526,7 +8601,7 @@ class Call {
|
|
|
8526
8601
|
*/
|
|
8527
8602
|
const rejoin = () => __awaiter(this, void 0, void 0, function* () {
|
|
8528
8603
|
var _g, _h, _j;
|
|
8529
|
-
|
|
8604
|
+
this.logger('debug', `Rejoining call ${this.cid} (${this.reconnectAttempts})...`);
|
|
8530
8605
|
this.reconnectAttempts++;
|
|
8531
8606
|
this.state.setCallingState(exports.CallingState.RECONNECTING);
|
|
8532
8607
|
// take a snapshot of the current "local participant" state
|
|
@@ -8538,7 +8613,7 @@ class Call {
|
|
|
8538
8613
|
sfuClient.close(); // clean up previous connection
|
|
8539
8614
|
yield sleep(retryInterval(this.reconnectAttempts));
|
|
8540
8615
|
yield this.join(data);
|
|
8541
|
-
|
|
8616
|
+
this.logger('info', `Rejoin: ${this.reconnectAttempts} successful!`);
|
|
8542
8617
|
if (localParticipant && !isReactNative()) {
|
|
8543
8618
|
const { audioStream, videoStream, screenShareStream: screenShare, } = localParticipant;
|
|
8544
8619
|
// restore previous publishing state
|
|
@@ -8549,7 +8624,7 @@ class Call {
|
|
|
8549
8624
|
if (screenShare)
|
|
8550
8625
|
yield this.publishScreenShareStream(screenShare);
|
|
8551
8626
|
}
|
|
8552
|
-
|
|
8627
|
+
this.logger('info', `Rejoin: state restored ${this.reconnectAttempts}`);
|
|
8553
8628
|
});
|
|
8554
8629
|
this.rejoinPromise = rejoin;
|
|
8555
8630
|
// reconnect if the connection was closed unexpectedly. example:
|
|
@@ -8569,12 +8644,12 @@ class Call {
|
|
|
8569
8644
|
return;
|
|
8570
8645
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
8571
8646
|
rejoin().catch(() => {
|
|
8572
|
-
|
|
8647
|
+
this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
|
|
8573
8648
|
this.state.setCallingState(exports.CallingState.RECONNECTING_FAILED);
|
|
8574
8649
|
});
|
|
8575
8650
|
}
|
|
8576
8651
|
else {
|
|
8577
|
-
|
|
8652
|
+
this.logger('error', 'Reconnect attempts exceeded. Giving up...');
|
|
8578
8653
|
this.state.setCallingState(exports.CallingState.RECONNECTING_FAILED);
|
|
8579
8654
|
}
|
|
8580
8655
|
});
|
|
@@ -8584,15 +8659,15 @@ class Call {
|
|
|
8584
8659
|
if (typeof window !== 'undefined' && window.addEventListener) {
|
|
8585
8660
|
const handleOnOffline = () => {
|
|
8586
8661
|
window.removeEventListener('offline', handleOnOffline);
|
|
8587
|
-
|
|
8662
|
+
this.logger('warn', 'Join: Going offline...');
|
|
8588
8663
|
this.state.setCallingState(exports.CallingState.OFFLINE);
|
|
8589
8664
|
};
|
|
8590
8665
|
const handleOnOnline = () => {
|
|
8591
8666
|
window.removeEventListener('online', handleOnOnline);
|
|
8592
8667
|
if (this.state.callingState === exports.CallingState.OFFLINE) {
|
|
8593
|
-
|
|
8668
|
+
this.logger('info', 'Join: Going online...');
|
|
8594
8669
|
rejoin().catch(() => {
|
|
8595
|
-
|
|
8670
|
+
this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
|
|
8596
8671
|
this.state.setCallingState(exports.CallingState.RECONNECTING_FAILED);
|
|
8597
8672
|
});
|
|
8598
8673
|
}
|
|
@@ -8649,15 +8724,20 @@ class Call {
|
|
|
8649
8724
|
clientDetails.sdk = getSdkInfo();
|
|
8650
8725
|
// 1. wait for the signal server to be ready before sending "joinRequest"
|
|
8651
8726
|
sfuClient.signalReady
|
|
8652
|
-
.catch((err) =>
|
|
8727
|
+
.catch((err) => this.logger('error', 'Signal ready failed', err))
|
|
8653
8728
|
// prepare a generic SDP and send it to the SFU.
|
|
8654
8729
|
// this is a throw-away SDP that the SFU will use to determine
|
|
8655
8730
|
// the capabilities of the client (codec support, etc.)
|
|
8656
8731
|
.then(() => getGenericSdp('recvonly', isRedEnabled, this.streamClient.options.preferredVideoCodec))
|
|
8657
|
-
.then((sdp) =>
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8732
|
+
.then((sdp) => {
|
|
8733
|
+
const joinRequest = {
|
|
8734
|
+
subscriberSdp: sdp || '',
|
|
8735
|
+
clientDetails,
|
|
8736
|
+
};
|
|
8737
|
+
this.logger('info', 'Sending join request to SFU');
|
|
8738
|
+
this.logger('debug', 'Join request payload', joinRequest);
|
|
8739
|
+
sfuClient.join(joinRequest);
|
|
8740
|
+
});
|
|
8661
8741
|
// 2. in parallel, wait for the SFU to send us the "joinResponse"
|
|
8662
8742
|
// this will throw an error if the SFU rejects the join request or
|
|
8663
8743
|
// fails to respond in time
|
|
@@ -8667,22 +8747,22 @@ class Call {
|
|
|
8667
8747
|
const startedAt = (callState === null || callState === void 0 ? void 0 : callState.startedAt)
|
|
8668
8748
|
? Timestamp.toDate(callState.startedAt)
|
|
8669
8749
|
: new Date();
|
|
8670
|
-
this.state.setParticipants(currentParticipants.map((participant) => (Object.assign(Object.assign({}, participant), {
|
|
8750
|
+
this.state.setParticipants(currentParticipants.map((participant) => (Object.assign(Object.assign({}, participant), { isLocalParticipant: participant.sessionId === sfuClient.sessionId, viewportVisibilityState: exports.VisibilityState.UNKNOWN }))));
|
|
8671
8751
|
this.state.setParticipantCount((participantCount === null || participantCount === void 0 ? void 0 : participantCount.total) || 0);
|
|
8672
8752
|
this.state.setAnonymousParticipantCount((participantCount === null || participantCount === void 0 ? void 0 : participantCount.anonymous) || 0);
|
|
8673
8753
|
this.state.setStartedAt(startedAt);
|
|
8674
8754
|
this.reconnectAttempts = 0; // reset the reconnect attempts counter
|
|
8675
8755
|
this.state.setCallingState(exports.CallingState.JOINED);
|
|
8676
|
-
|
|
8756
|
+
this.logger('info', `Joined call ${this.cid}`);
|
|
8677
8757
|
}
|
|
8678
8758
|
catch (err) {
|
|
8679
8759
|
// join failed, try to rejoin
|
|
8680
8760
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
8681
8761
|
yield rejoin();
|
|
8682
|
-
|
|
8762
|
+
this.logger('info', `Rejoin ${this.reconnectAttempts} successful!`);
|
|
8683
8763
|
}
|
|
8684
8764
|
else {
|
|
8685
|
-
|
|
8765
|
+
this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
|
|
8686
8766
|
this.state.setCallingState(exports.CallingState.RECONNECTING_FAILED);
|
|
8687
8767
|
throw new Error('Join failed');
|
|
8688
8768
|
}
|
|
@@ -8707,7 +8787,8 @@ class Call {
|
|
|
8707
8787
|
}
|
|
8708
8788
|
const [videoTrack] = videoStream.getVideoTracks();
|
|
8709
8789
|
if (!videoTrack) {
|
|
8710
|
-
|
|
8790
|
+
this.logger('error', `There is no video track to publish in the stream.`);
|
|
8791
|
+
return;
|
|
8711
8792
|
}
|
|
8712
8793
|
yield this.publisher.publishStream(videoStream, videoTrack, TrackType.VIDEO, opts);
|
|
8713
8794
|
});
|
|
@@ -8730,7 +8811,8 @@ class Call {
|
|
|
8730
8811
|
}
|
|
8731
8812
|
const [audioTrack] = audioStream.getAudioTracks();
|
|
8732
8813
|
if (!audioTrack) {
|
|
8733
|
-
|
|
8814
|
+
this.logger('error', `There is no audio track in the stream to publish`);
|
|
8815
|
+
return;
|
|
8734
8816
|
}
|
|
8735
8817
|
yield this.publisher.publishStream(audioStream, audioTrack, TrackType.AUDIO);
|
|
8736
8818
|
});
|
|
@@ -8752,7 +8834,8 @@ class Call {
|
|
|
8752
8834
|
}
|
|
8753
8835
|
const [screenShareTrack] = screenShareStream.getVideoTracks();
|
|
8754
8836
|
if (!screenShareTrack) {
|
|
8755
|
-
|
|
8837
|
+
this.logger('error', `There is no video track in the screen share stream to publish`);
|
|
8838
|
+
return;
|
|
8756
8839
|
}
|
|
8757
8840
|
yield this.publisher.publishStream(screenShareStream, screenShareTrack, TrackType.SCREEN_SHARE);
|
|
8758
8841
|
});
|
|
@@ -8767,7 +8850,7 @@ class Call {
|
|
|
8767
8850
|
*/
|
|
8768
8851
|
this.stopPublish = (trackType) => __awaiter(this, void 0, void 0, function* () {
|
|
8769
8852
|
var _k;
|
|
8770
|
-
|
|
8853
|
+
this.logger('info', `stopPublish ${TrackType[trackType]}`);
|
|
8771
8854
|
yield ((_k = this.publisher) === null || _k === void 0 ? void 0 : _k.unpublishStream(trackType));
|
|
8772
8855
|
});
|
|
8773
8856
|
/**
|
|
@@ -8801,7 +8884,7 @@ class Call {
|
|
|
8801
8884
|
const subscriptions = [];
|
|
8802
8885
|
participants.forEach((p) => {
|
|
8803
8886
|
// we don't want to subscribe to our own tracks
|
|
8804
|
-
if (p.
|
|
8887
|
+
if (p.isLocalParticipant)
|
|
8805
8888
|
return;
|
|
8806
8889
|
// NOTE: audio tracks don't have to be requested explicitly
|
|
8807
8890
|
// as the SFU will implicitly subscribe us to all of them,
|
|
@@ -8916,20 +8999,21 @@ class Call {
|
|
|
8916
8999
|
const [primaryStream] = e.streams;
|
|
8917
9000
|
// example: `e3f6aaf8-b03d-4911-be36-83f47d37a76a:TRACK_TYPE_VIDEO`
|
|
8918
9001
|
const [trackId, trackType] = primaryStream.id.split(':');
|
|
8919
|
-
|
|
9002
|
+
this.logger('info', `Got remote ${trackType} track:`);
|
|
9003
|
+
this.logger('debug', `Track: `, e.track);
|
|
8920
9004
|
const participantToUpdate = this.state.participants.find((p) => p.trackLookupPrefix === trackId);
|
|
8921
9005
|
if (!participantToUpdate) {
|
|
8922
|
-
|
|
9006
|
+
this.logger('error', `'Received track for unknown participant: ${trackId}'`, e);
|
|
8923
9007
|
return;
|
|
8924
9008
|
}
|
|
8925
9009
|
e.track.addEventListener('mute', () => {
|
|
8926
|
-
|
|
9010
|
+
this.logger('info', `Track muted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
|
|
8927
9011
|
});
|
|
8928
9012
|
e.track.addEventListener('unmute', () => {
|
|
8929
|
-
|
|
9013
|
+
this.logger('info', `Track unmuted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
|
|
8930
9014
|
});
|
|
8931
9015
|
e.track.addEventListener('ended', () => {
|
|
8932
|
-
|
|
9016
|
+
this.logger('info', `Track ended: ${participantToUpdate.userId} ${trackType}:${trackId}`);
|
|
8933
9017
|
});
|
|
8934
9018
|
const streamKindProp = {
|
|
8935
9019
|
TRACK_TYPE_AUDIO: 'audioStream',
|
|
@@ -8937,12 +9021,12 @@ class Call {
|
|
|
8937
9021
|
TRACK_TYPE_SCREEN_SHARE: 'screenShareStream',
|
|
8938
9022
|
}[trackType];
|
|
8939
9023
|
if (!streamKindProp) {
|
|
8940
|
-
|
|
9024
|
+
this.logger('error', `Unknown track type: ${trackType}`);
|
|
8941
9025
|
return;
|
|
8942
9026
|
}
|
|
8943
9027
|
const previousStream = participantToUpdate[streamKindProp];
|
|
8944
9028
|
if (previousStream) {
|
|
8945
|
-
|
|
9029
|
+
this.logger('info', `Cleaning up previous remote tracks: ${e.track.kind}`);
|
|
8946
9030
|
previousStream.getTracks().forEach((t) => {
|
|
8947
9031
|
t.stop();
|
|
8948
9032
|
previousStream.removeTrack(t);
|
|
@@ -9242,6 +9326,7 @@ class Call {
|
|
|
9242
9326
|
this.streamClient = streamClient;
|
|
9243
9327
|
this.clientStore = clientStore;
|
|
9244
9328
|
this.streamClientBasePath = `/call/${this.type}/${this.id}`;
|
|
9329
|
+
this.logger = getLogger(['call']);
|
|
9245
9330
|
const callTypeConfig = CallTypes.get(type);
|
|
9246
9331
|
const participantSorter = sortParticipantsBy || callTypeConfig.options.sortParticipantsBy;
|
|
9247
9332
|
if (participantSorter) {
|
|
@@ -9279,7 +9364,7 @@ class Call {
|
|
|
9279
9364
|
const hasPermission = this.permissionsContext.hasPermission(permission);
|
|
9280
9365
|
if (!hasPermission && this.publisher.isPublishing(trackType)) {
|
|
9281
9366
|
this.stopPublish(trackType).catch((err) => {
|
|
9282
|
-
|
|
9367
|
+
this.logger('error', `Error stopping publish ${trackType}`, err);
|
|
9283
9368
|
});
|
|
9284
9369
|
}
|
|
9285
9370
|
}
|
|
@@ -9498,12 +9583,12 @@ class StableWSConnection {
|
|
|
9498
9583
|
return;
|
|
9499
9584
|
const user = this.client.user;
|
|
9500
9585
|
if (!user) {
|
|
9501
|
-
|
|
9586
|
+
this.client.logger('error', `User not set, can't connect to WS`);
|
|
9502
9587
|
return;
|
|
9503
9588
|
}
|
|
9504
9589
|
const token = this.client._getToken();
|
|
9505
9590
|
if (!token) {
|
|
9506
|
-
|
|
9591
|
+
this.client.logger('error', `Token not set, can't connect authenticate`);
|
|
9507
9592
|
return;
|
|
9508
9593
|
}
|
|
9509
9594
|
const authMessage = {
|
|
@@ -9736,7 +9821,7 @@ class StableWSConnection {
|
|
|
9736
9821
|
addConnectionEventListeners(this.onlineStatusChanged);
|
|
9737
9822
|
}
|
|
9738
9823
|
_log(msg, extra = {}, level = 'info') {
|
|
9739
|
-
this.client.logger(level, 'connection:' + msg, Object.assign({
|
|
9824
|
+
this.client.logger(level, 'connection:' + msg, Object.assign({}, extra));
|
|
9740
9825
|
}
|
|
9741
9826
|
/**
|
|
9742
9827
|
* connect - Connect to the WS URL
|
|
@@ -10456,7 +10541,7 @@ class WSConnectionFallback {
|
|
|
10456
10541
|
addConnectionEventListeners(this._onlineStatusChanged);
|
|
10457
10542
|
}
|
|
10458
10543
|
_log(msg, extra = {}, level = 'info') {
|
|
10459
|
-
this.client.logger(level, 'WSConnectionFallback:' + msg, Object.assign({
|
|
10544
|
+
this.client.logger(level, 'WSConnectionFallback:' + msg, Object.assign({}, extra));
|
|
10460
10545
|
}
|
|
10461
10546
|
_setState(state) {
|
|
10462
10547
|
this._log(`_setState() - ${state}`);
|
|
@@ -10516,7 +10601,7 @@ class StreamClient {
|
|
|
10516
10601
|
* If the user id remains the same we don't throw error
|
|
10517
10602
|
*/
|
|
10518
10603
|
if (this.userID === user.id && this.setUserPromise) {
|
|
10519
|
-
|
|
10604
|
+
this.logger('warn', 'Consecutive calls to connectUser is detected, ideally you should only call this function once in your app.');
|
|
10520
10605
|
return this.setUserPromise;
|
|
10521
10606
|
}
|
|
10522
10607
|
if (this.userID) {
|
|
@@ -10524,7 +10609,7 @@ class StreamClient {
|
|
|
10524
10609
|
}
|
|
10525
10610
|
if ((this._isUsingServerAuth() || this.node) &&
|
|
10526
10611
|
!this.options.allowServerSideConnect) {
|
|
10527
|
-
|
|
10612
|
+
this.logger('warn', 'Please do not use connectUser server side. connectUser impacts MAU and concurrent connection usage and thus your bill. If you have a valid use-case, add "allowServerSideConnect: true" to the client options to disable this warning.');
|
|
10528
10613
|
}
|
|
10529
10614
|
// we generate the client id client side
|
|
10530
10615
|
this.userID = user.id;
|
|
@@ -10587,16 +10672,12 @@ class StreamClient {
|
|
|
10587
10672
|
throw Error('UserWithId is not set on client, use client.connectUser or client.connectAnonymousUser instead');
|
|
10588
10673
|
}
|
|
10589
10674
|
if (((_d = this.wsConnection) === null || _d === void 0 ? void 0 : _d.isConnecting) && this.wsPromise) {
|
|
10590
|
-
this.logger('info', 'client:openConnection() - connection already in progress'
|
|
10591
|
-
tags: ['connection', 'client'],
|
|
10592
|
-
});
|
|
10675
|
+
this.logger('info', 'client:openConnection() - connection already in progress');
|
|
10593
10676
|
return this.wsPromise;
|
|
10594
10677
|
}
|
|
10595
10678
|
if ((((_e = this.wsConnection) === null || _e === void 0 ? void 0 : _e.isHealthy) || ((_f = this.wsFallback) === null || _f === void 0 ? void 0 : _f.isHealthy())) &&
|
|
10596
10679
|
this._hasConnectionID()) {
|
|
10597
|
-
this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists'
|
|
10598
|
-
tags: ['connection', 'client'],
|
|
10599
|
-
});
|
|
10680
|
+
this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists');
|
|
10600
10681
|
return Promise.resolve();
|
|
10601
10682
|
}
|
|
10602
10683
|
this.clientID = `${this.userID}--${randomId()}`;
|
|
@@ -10619,9 +10700,7 @@ class StreamClient {
|
|
|
10619
10700
|
* https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
|
10620
10701
|
*/
|
|
10621
10702
|
this.disconnectUser = (timeout) => __awaiter(this, void 0, void 0, function* () {
|
|
10622
|
-
this.logger('info', 'client:disconnect() - Disconnecting the client'
|
|
10623
|
-
tags: ['connection', 'client'],
|
|
10624
|
-
});
|
|
10703
|
+
this.logger('info', 'client:disconnect() - Disconnecting the client');
|
|
10625
10704
|
// remove the user specific fields
|
|
10626
10705
|
delete this.user;
|
|
10627
10706
|
delete this._user;
|
|
@@ -10711,7 +10790,8 @@ class StreamClient {
|
|
|
10711
10790
|
this.dispatchEvent = (event) => {
|
|
10712
10791
|
if (!event.received_at)
|
|
10713
10792
|
event.received_at = new Date();
|
|
10714
|
-
|
|
10793
|
+
this.logger('info', `Dispatching event: ${event.type}`);
|
|
10794
|
+
this.logger('debug', 'Event payload:', event);
|
|
10715
10795
|
this._callClientListeners(event);
|
|
10716
10796
|
};
|
|
10717
10797
|
this.handleEvent = (messageEvent) => {
|
|
@@ -10844,9 +10924,7 @@ class StreamClient {
|
|
|
10844
10924
|
if (!(key in this.listeners)) {
|
|
10845
10925
|
this.listeners[key] = [];
|
|
10846
10926
|
}
|
|
10847
|
-
this.logger('info', `Attaching listener for ${key} event
|
|
10848
|
-
tags: ['event', 'client'],
|
|
10849
|
-
});
|
|
10927
|
+
this.logger('info', `Attaching listener for ${key} event`);
|
|
10850
10928
|
this.listeners[key].push(callback);
|
|
10851
10929
|
return () => {
|
|
10852
10930
|
this.off(key, callback);
|
|
@@ -10864,29 +10942,26 @@ class StreamClient {
|
|
|
10864
10942
|
if (!(key in this.listeners)) {
|
|
10865
10943
|
this.listeners[key] = [];
|
|
10866
10944
|
}
|
|
10867
|
-
this.logger('info', `Removing listener for ${key} event
|
|
10868
|
-
tags: ['event', 'client'],
|
|
10869
|
-
});
|
|
10945
|
+
this.logger('info', `Removing listener for ${key} event`);
|
|
10870
10946
|
this.listeners[key] = this.listeners[key].filter((value) => value !== callback);
|
|
10871
10947
|
}
|
|
10872
10948
|
_logApiRequest(type, url, data, config) {
|
|
10873
|
-
this.logger('info', `client: ${type} - Request - ${url}
|
|
10874
|
-
|
|
10875
|
-
url,
|
|
10949
|
+
this.logger('info', `client: ${type} - Request - ${url}`);
|
|
10950
|
+
this.logger('debug', `client: ${type} - Request payload`, {
|
|
10876
10951
|
payload: data,
|
|
10877
10952
|
config,
|
|
10878
10953
|
});
|
|
10879
10954
|
}
|
|
10880
10955
|
_logApiResponse(type, url, response) {
|
|
10881
10956
|
this.logger('info', `client:${type} - Response - url: ${url} > status ${response.status}`, {
|
|
10882
|
-
|
|
10883
|
-
|
|
10957
|
+
response,
|
|
10958
|
+
});
|
|
10959
|
+
this.logger('debug', `client:${type} - Response payload`, {
|
|
10884
10960
|
response,
|
|
10885
10961
|
});
|
|
10886
10962
|
}
|
|
10887
10963
|
_logApiError(type, url, error) {
|
|
10888
10964
|
this.logger('error', `client:${type} - Error - url: ${url}`, {
|
|
10889
|
-
tags: ['api', 'api_response', 'client'],
|
|
10890
10965
|
url,
|
|
10891
10966
|
error,
|
|
10892
10967
|
});
|
|
@@ -10961,7 +11036,7 @@ class StreamClient {
|
|
|
10961
11036
|
if (this.wsFallback) {
|
|
10962
11037
|
return yield this.wsFallback.connect();
|
|
10963
11038
|
}
|
|
10964
|
-
|
|
11039
|
+
this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
|
|
10965
11040
|
// if WSFallback is enabled, ws connect should timeout faster so fallback can try
|
|
10966
11041
|
return yield this.wsConnection.connect(this.options.enableWSFallback
|
|
10967
11042
|
? this.defaultWSTimeoutWithFallback
|
|
@@ -10970,9 +11045,11 @@ class StreamClient {
|
|
|
10970
11045
|
catch (err) {
|
|
10971
11046
|
// run fallback only if it's WS/Network error and not a normal API error
|
|
10972
11047
|
// make sure browser is online before even trying the longpoll
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
|
|
11048
|
+
if (this.options.enableWSFallback &&
|
|
11049
|
+
// @ts-ignore
|
|
11050
|
+
isWSFailure(err) &&
|
|
11051
|
+
isOnline(this.logger)) {
|
|
11052
|
+
this.logger('warn', 'client:connect() - WS failed, fallback to longpoll');
|
|
10976
11053
|
this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
|
|
10977
11054
|
this.wsConnection._destroyCurrentWSConnection();
|
|
10978
11055
|
this.wsConnection.disconnect().then(); // close WS so no retry
|
|
@@ -11007,7 +11084,7 @@ class StreamClient {
|
|
|
11007
11084
|
}
|
|
11008
11085
|
getUserAgent() {
|
|
11009
11086
|
return (this.userAgent ||
|
|
11010
|
-
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.
|
|
11087
|
+
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.14"}`);
|
|
11011
11088
|
}
|
|
11012
11089
|
setUserAgent(userAgent) {
|
|
11013
11090
|
this.userAgent = userAgent;
|
|
@@ -11076,7 +11153,10 @@ class StreamClient {
|
|
|
11076
11153
|
*/
|
|
11077
11154
|
class StreamVideoClient {
|
|
11078
11155
|
constructor(apiKeyOrArgs, opts) {
|
|
11156
|
+
var _a, _b;
|
|
11157
|
+
this.logLevel = 'warn';
|
|
11079
11158
|
this.eventHandlersToUnregister = [];
|
|
11159
|
+
this.logLevels = ['debug', 'info', 'warn', 'error'];
|
|
11080
11160
|
/**
|
|
11081
11161
|
* Disconnects the currently connected user from the client.
|
|
11082
11162
|
*
|
|
@@ -11235,11 +11315,30 @@ class StreamVideoClient {
|
|
|
11235
11315
|
this.connectionPromise.finally(() => (this.connectionPromise = undefined));
|
|
11236
11316
|
return this.connectionPromise;
|
|
11237
11317
|
});
|
|
11318
|
+
this.filterLogs = (logMethod) => {
|
|
11319
|
+
return (logLevel, messeage, extraData, tags) => {
|
|
11320
|
+
if (this.logLevels.indexOf(logLevel) >=
|
|
11321
|
+
this.logLevels.indexOf(this.logLevel)) {
|
|
11322
|
+
logMethod(logLevel, messeage, extraData, tags);
|
|
11323
|
+
}
|
|
11324
|
+
};
|
|
11325
|
+
};
|
|
11326
|
+
let defaultLogger = logToConsole;
|
|
11238
11327
|
if (typeof apiKeyOrArgs === 'string') {
|
|
11239
|
-
this.
|
|
11328
|
+
this.logLevel = (opts === null || opts === void 0 ? void 0 : opts.logLevel) || this.logLevel;
|
|
11329
|
+
this.logger = (opts === null || opts === void 0 ? void 0 : opts.logger) || defaultLogger;
|
|
11240
11330
|
}
|
|
11241
11331
|
else {
|
|
11242
|
-
this.
|
|
11332
|
+
this.logLevel = ((_a = apiKeyOrArgs.options) === null || _a === void 0 ? void 0 : _a.logLevel) || this.logLevel;
|
|
11333
|
+
this.logger = ((_b = apiKeyOrArgs.options) === null || _b === void 0 ? void 0 : _b.logger) || defaultLogger;
|
|
11334
|
+
}
|
|
11335
|
+
setLogger(this.filterLogs(defaultLogger));
|
|
11336
|
+
const clientLogger = getLogger(['client']);
|
|
11337
|
+
if (typeof apiKeyOrArgs === 'string') {
|
|
11338
|
+
this.streamClient = new StreamClient(apiKeyOrArgs, Object.assign(Object.assign({ persistUserOnConnectionFailure: true }, opts), { logLevel: this.logLevel, logger: clientLogger }));
|
|
11339
|
+
}
|
|
11340
|
+
else {
|
|
11341
|
+
this.streamClient = new StreamClient(apiKeyOrArgs.apiKey, Object.assign(Object.assign({ persistUserOnConnectionFailure: true }, apiKeyOrArgs.options), { logLevel: this.logLevel, logger: clientLogger }));
|
|
11243
11342
|
this.user = apiKeyOrArgs.user;
|
|
11244
11343
|
this.token = apiKeyOrArgs.token || apiKeyOrArgs.tokenProvider;
|
|
11245
11344
|
if (this.user) {
|
|
@@ -11301,7 +11400,7 @@ class StreamVideoClient {
|
|
|
11301
11400
|
},
|
|
11302
11401
|
sort: [{ field: 'cid', direction: 1 }],
|
|
11303
11402
|
}).catch((err) => {
|
|
11304
|
-
|
|
11403
|
+
this.logger('error', 'Failed to re-watch calls', err);
|
|
11305
11404
|
});
|
|
11306
11405
|
}
|
|
11307
11406
|
}
|
|
@@ -11311,7 +11410,7 @@ class StreamVideoClient {
|
|
|
11311
11410
|
return;
|
|
11312
11411
|
const { call, members } = event;
|
|
11313
11412
|
if (userToConnect.id === call.created_by.id) {
|
|
11314
|
-
|
|
11413
|
+
this.logger('warn', 'Received `call.created` sent by the current user');
|
|
11315
11414
|
return;
|
|
11316
11415
|
}
|
|
11317
11416
|
this.writeableStateStore.registerCall(new Call({
|
|
@@ -11328,7 +11427,7 @@ class StreamVideoClient {
|
|
|
11328
11427
|
return;
|
|
11329
11428
|
const { call, members } = event;
|
|
11330
11429
|
if (userToConnect.id === call.created_by.id) {
|
|
11331
|
-
|
|
11430
|
+
this.logger('warn', 'Received `call.ring` sent by the current user');
|
|
11332
11431
|
return;
|
|
11333
11432
|
}
|
|
11334
11433
|
// The call might already be tracked by the client,
|
|
@@ -11395,7 +11494,10 @@ const getDevices = (constraints) => {
|
|
|
11395
11494
|
});
|
|
11396
11495
|
})
|
|
11397
11496
|
.catch((error) => {
|
|
11398
|
-
|
|
11497
|
+
const logger = getLogger(['devices']);
|
|
11498
|
+
if (logger) {
|
|
11499
|
+
logger('error', 'Failed to get devices', error);
|
|
11500
|
+
}
|
|
11399
11501
|
subscriber.error(error);
|
|
11400
11502
|
});
|
|
11401
11503
|
});
|
|
@@ -11466,11 +11568,15 @@ const getAudioOutputDevices = () => {
|
|
|
11466
11568
|
return audioDevices$.pipe(rxjs.map((values) => values.filter((d) => d.kind === 'audiooutput')));
|
|
11467
11569
|
};
|
|
11468
11570
|
const getStream = (constraints) => __awaiter(void 0, void 0, void 0, function* () {
|
|
11571
|
+
var _a;
|
|
11469
11572
|
try {
|
|
11470
11573
|
return yield navigator.mediaDevices.getUserMedia(constraints);
|
|
11471
11574
|
}
|
|
11472
11575
|
catch (e) {
|
|
11473
|
-
|
|
11576
|
+
(_a = getLogger(['devices'])) === null || _a === void 0 ? void 0 : _a('error', `Failed get user media`, {
|
|
11577
|
+
error: e,
|
|
11578
|
+
constraints: constraints,
|
|
11579
|
+
});
|
|
11474
11580
|
throw e;
|
|
11475
11581
|
}
|
|
11476
11582
|
});
|
|
@@ -11513,11 +11619,12 @@ const getVideoStream = (trackConstraints) => __awaiter(void 0, void 0, void 0, f
|
|
|
11513
11619
|
* @param options any additional options to pass to the [`getDisplayMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia) API.
|
|
11514
11620
|
*/
|
|
11515
11621
|
const getScreenShareStream = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
11622
|
+
var _b;
|
|
11516
11623
|
try {
|
|
11517
11624
|
return yield navigator.mediaDevices.getDisplayMedia(Object.assign({ video: true, audio: false }, options));
|
|
11518
11625
|
}
|
|
11519
11626
|
catch (e) {
|
|
11520
|
-
|
|
11627
|
+
(_b = getLogger(['devices'])) === null || _b === void 0 ? void 0 : _b('error', 'Failed to get screen share stream', e);
|
|
11521
11628
|
throw e;
|
|
11522
11629
|
}
|
|
11523
11630
|
});
|
|
@@ -11740,12 +11847,14 @@ exports.dominantSpeaker = dominantSpeaker;
|
|
|
11740
11847
|
exports.getAudioDevices = getAudioDevices;
|
|
11741
11848
|
exports.getAudioOutputDevices = getAudioOutputDevices;
|
|
11742
11849
|
exports.getAudioStream = getAudioStream;
|
|
11850
|
+
exports.getLogger = getLogger;
|
|
11743
11851
|
exports.getScreenShareStream = getScreenShareStream;
|
|
11744
11852
|
exports.getSdkInfo = getSdkInfo;
|
|
11745
11853
|
exports.getVideoDevices = getVideoDevices;
|
|
11746
11854
|
exports.getVideoStream = getVideoStream;
|
|
11747
11855
|
exports.isStreamVideoLocalParticipant = isStreamVideoLocalParticipant;
|
|
11748
11856
|
exports.livestreamOrAudioRoomSortPreset = livestreamOrAudioRoomSortPreset;
|
|
11857
|
+
exports.logToConsole = logToConsole;
|
|
11749
11858
|
exports.name = name;
|
|
11750
11859
|
exports.noopComparator = noopComparator;
|
|
11751
11860
|
exports.pinned = pinned;
|
|
@@ -11754,6 +11863,7 @@ exports.publishingVideo = publishingVideo;
|
|
|
11754
11863
|
exports.reactionType = reactionType;
|
|
11755
11864
|
exports.role = role;
|
|
11756
11865
|
exports.screenSharing = screenSharing;
|
|
11866
|
+
exports.setLogger = setLogger;
|
|
11757
11867
|
exports.setSdkInfo = setSdkInfo;
|
|
11758
11868
|
exports.speakerLayoutSortPreset = speakerLayoutSortPreset;
|
|
11759
11869
|
exports.speaking = speaking;
|