@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.browser.es.js
CHANGED
|
@@ -4246,7 +4246,7 @@ var DebounceType;
|
|
|
4246
4246
|
DebounceType[DebounceType["SLOW"] = 1200] = "SLOW";
|
|
4247
4247
|
})(DebounceType || (DebounceType = {}));
|
|
4248
4248
|
const isStreamVideoLocalParticipant = (p) => {
|
|
4249
|
-
return !!p.
|
|
4249
|
+
return !!p.isLocalParticipant;
|
|
4250
4250
|
};
|
|
4251
4251
|
|
|
4252
4252
|
/******************************************************************************
|
|
@@ -5273,13 +5273,41 @@ const toggleDtx = (sdp, enable) => {
|
|
|
5273
5273
|
return sdp;
|
|
5274
5274
|
};
|
|
5275
5275
|
|
|
5276
|
+
let logger;
|
|
5277
|
+
const logToConsole = (logLevel, message, extraData, tags) => {
|
|
5278
|
+
let logMethod;
|
|
5279
|
+
if (logLevel === 'error') {
|
|
5280
|
+
logMethod = console.error;
|
|
5281
|
+
}
|
|
5282
|
+
else if (logLevel === 'warn') {
|
|
5283
|
+
logMethod = console.warn;
|
|
5284
|
+
}
|
|
5285
|
+
else {
|
|
5286
|
+
logMethod = console.log;
|
|
5287
|
+
}
|
|
5288
|
+
logMethod(logLevel, `${tags === null || tags === void 0 ? void 0 : tags.join(':')} - ${message}`, extraData ? extraData : '');
|
|
5289
|
+
};
|
|
5290
|
+
const setLogger = (l) => {
|
|
5291
|
+
logger = l;
|
|
5292
|
+
};
|
|
5293
|
+
const getLogger = (withTags) => {
|
|
5294
|
+
const loggerMethod = logger || (() => { });
|
|
5295
|
+
const result = (logLevel, messeage, extraData, tags) => {
|
|
5296
|
+
loggerMethod(logLevel, messeage, extraData, [
|
|
5297
|
+
...(tags || []),
|
|
5298
|
+
...(withTags || []),
|
|
5299
|
+
]);
|
|
5300
|
+
};
|
|
5301
|
+
return result;
|
|
5302
|
+
};
|
|
5303
|
+
|
|
5276
5304
|
const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
|
|
5305
|
+
const logger = getLogger(['codecs']);
|
|
5277
5306
|
if (!('getCapabilities' in RTCRtpSender)) {
|
|
5278
|
-
|
|
5307
|
+
logger === null || logger === void 0 ? void 0 : logger('warn', 'RTCRtpSender.getCapabilities is not supported');
|
|
5279
5308
|
return;
|
|
5280
5309
|
}
|
|
5281
5310
|
const cap = RTCRtpSender.getCapabilities(kind);
|
|
5282
|
-
console.log('s4e');
|
|
5283
5311
|
if (!cap)
|
|
5284
5312
|
return;
|
|
5285
5313
|
const matched = [];
|
|
@@ -5287,7 +5315,7 @@ const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
|
|
|
5287
5315
|
const unmatched = [];
|
|
5288
5316
|
cap.codecs.forEach((c) => {
|
|
5289
5317
|
const codec = c.mimeType.toLowerCase();
|
|
5290
|
-
|
|
5318
|
+
logger === null || logger === void 0 ? void 0 : logger('debug', `Found supported codec: ${codec}`);
|
|
5291
5319
|
const shouldRemoveCodec = codecToRemove && codec === `${kind}/${codecToRemove}`;
|
|
5292
5320
|
if (shouldRemoveCodec)
|
|
5293
5321
|
return;
|
|
@@ -5307,10 +5335,11 @@ const getPreferredCodecs = (kind, preferredCodec, codecToRemove) => {
|
|
|
5307
5335
|
}
|
|
5308
5336
|
return;
|
|
5309
5337
|
}
|
|
5310
|
-
console.log('matched', matched);
|
|
5311
5338
|
matched.push(c);
|
|
5312
5339
|
});
|
|
5313
|
-
|
|
5340
|
+
const result = [...matched, ...partialMatched, ...unmatched];
|
|
5341
|
+
logger === null || logger === void 0 ? void 0 : logger('info', `Preffered codecs: `, result);
|
|
5342
|
+
return result;
|
|
5314
5343
|
};
|
|
5315
5344
|
const getGenericSdp = (direction, isRedEnabled, preferredVideoCodec) => __awaiter(void 0, void 0, void 0, function* () {
|
|
5316
5345
|
var _a;
|
|
@@ -5376,17 +5405,19 @@ class Dispatcher {
|
|
|
5376
5405
|
constructor() {
|
|
5377
5406
|
this.subscribers = {};
|
|
5378
5407
|
this.dispatch = (message) => {
|
|
5408
|
+
var _a, _b;
|
|
5379
5409
|
const eventKind = message.eventPayload.oneofKind;
|
|
5380
5410
|
if (eventKind) {
|
|
5381
|
-
|
|
5382
|
-
|
|
5411
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'info', `Dispatching ${eventKind}`);
|
|
5412
|
+
(_b = this.logger) === null || _b === void 0 ? void 0 : _b.call(this, 'debug', `Event payload`, message.eventPayload[eventKind]);
|
|
5383
5413
|
const listeners = this.subscribers[eventKind];
|
|
5384
5414
|
listeners === null || listeners === void 0 ? void 0 : listeners.forEach((fn) => {
|
|
5415
|
+
var _a;
|
|
5385
5416
|
try {
|
|
5386
5417
|
fn(message);
|
|
5387
5418
|
}
|
|
5388
5419
|
catch (e) {
|
|
5389
|
-
|
|
5420
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'warn', 'Listener failed with error', e);
|
|
5390
5421
|
}
|
|
5391
5422
|
});
|
|
5392
5423
|
}
|
|
@@ -5410,6 +5441,7 @@ class Dispatcher {
|
|
|
5410
5441
|
this.subscribers = {};
|
|
5411
5442
|
}
|
|
5412
5443
|
};
|
|
5444
|
+
this.logger = getLogger(['sfu-client']);
|
|
5413
5445
|
}
|
|
5414
5446
|
}
|
|
5415
5447
|
|
|
@@ -5422,6 +5454,7 @@ class IceTrickleBuffer {
|
|
|
5422
5454
|
this.subscriberCandidates = new ReplaySubject();
|
|
5423
5455
|
this.publisherCandidates = new ReplaySubject();
|
|
5424
5456
|
this.push = (iceTrickle) => {
|
|
5457
|
+
var _a;
|
|
5425
5458
|
if (iceTrickle.peerType === PeerType.SUBSCRIBER) {
|
|
5426
5459
|
this.subscriberCandidates.next(iceTrickle);
|
|
5427
5460
|
}
|
|
@@ -5429,9 +5462,10 @@ class IceTrickleBuffer {
|
|
|
5429
5462
|
this.publisherCandidates.next(iceTrickle);
|
|
5430
5463
|
}
|
|
5431
5464
|
else {
|
|
5432
|
-
|
|
5465
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'warn', `ICETrickle, Unknown peer type`, iceTrickle);
|
|
5433
5466
|
}
|
|
5434
5467
|
};
|
|
5468
|
+
this.logger = getLogger(['sfu-client']);
|
|
5435
5469
|
}
|
|
5436
5470
|
}
|
|
5437
5471
|
|
|
@@ -5622,6 +5656,7 @@ class Publisher {
|
|
|
5622
5656
|
* @param opts
|
|
5623
5657
|
*/
|
|
5624
5658
|
this.publishStream = (mediaStream, track, trackType, opts = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
5659
|
+
var _a;
|
|
5625
5660
|
let transceiver = this.publisher
|
|
5626
5661
|
.getTransceivers()
|
|
5627
5662
|
.find((t) => {
|
|
@@ -5635,7 +5670,8 @@ class Publisher {
|
|
|
5635
5670
|
* Once the track has ended, it will notify the SFU and update the state.
|
|
5636
5671
|
*/
|
|
5637
5672
|
const handleTrackEnded = () => __awaiter(this, void 0, void 0, function* () {
|
|
5638
|
-
|
|
5673
|
+
var _b;
|
|
5674
|
+
(_b = this.logger) === null || _b === void 0 ? void 0 : _b.call(this, 'info', `Track ${TrackType[trackType]} has ended, notifying the SFU`);
|
|
5639
5675
|
yield this.notifyTrackMuteStateChanged(mediaStream, track, trackType, true);
|
|
5640
5676
|
// clean-up, this event listener needs to run only once.
|
|
5641
5677
|
track.removeEventListener('ended', handleTrackEnded);
|
|
@@ -5660,7 +5696,7 @@ class Publisher {
|
|
|
5660
5696
|
});
|
|
5661
5697
|
this.transceiverRegistry[trackType] = transceiver;
|
|
5662
5698
|
if ('setCodecPreferences' in transceiver && codecPreferences) {
|
|
5663
|
-
|
|
5699
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'info', `Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
|
|
5664
5700
|
transceiver.setCodecPreferences(codecPreferences);
|
|
5665
5701
|
}
|
|
5666
5702
|
}
|
|
@@ -5744,9 +5780,9 @@ class Publisher {
|
|
|
5744
5780
|
this.publisher.close();
|
|
5745
5781
|
};
|
|
5746
5782
|
this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
|
|
5747
|
-
var
|
|
5748
|
-
|
|
5749
|
-
const videoSender = (
|
|
5783
|
+
var _c, _d, _e, _f;
|
|
5784
|
+
(_c = this.logger) === null || _c === void 0 ? void 0 : _c.call(this, 'info', 'Update publish quality, requested rids by SFU:', enabledRids);
|
|
5785
|
+
const videoSender = (_d = this.transceiverRegistry[TrackType.VIDEO]) === null || _d === void 0 ? void 0 : _d.sender;
|
|
5750
5786
|
if (!videoSender)
|
|
5751
5787
|
return;
|
|
5752
5788
|
const params = videoSender.getParameters();
|
|
@@ -5761,10 +5797,10 @@ class Publisher {
|
|
|
5761
5797
|
});
|
|
5762
5798
|
if (changed) {
|
|
5763
5799
|
if (params.encodings.length === 0) {
|
|
5764
|
-
|
|
5800
|
+
(_e = this.logger) === null || _e === void 0 ? void 0 : _e.call(this, 'warn', 'No suitable video encoding quality found');
|
|
5765
5801
|
}
|
|
5766
5802
|
yield videoSender.setParameters(params);
|
|
5767
|
-
|
|
5803
|
+
(_f = this.logger) === null || _f === void 0 ? void 0 : _f.call(this, 'info', `Update publish quality, enabled rids: ${params.encodings
|
|
5768
5804
|
.filter((e) => e.active)
|
|
5769
5805
|
.map((e) => e.rid)
|
|
5770
5806
|
.join(', ')}`);
|
|
@@ -5781,9 +5817,10 @@ class Publisher {
|
|
|
5781
5817
|
}
|
|
5782
5818
|
};
|
|
5783
5819
|
this.onIceCandidate = (e) => __awaiter(this, void 0, void 0, function* () {
|
|
5820
|
+
var _g;
|
|
5784
5821
|
const { candidate } = e;
|
|
5785
5822
|
if (!candidate) {
|
|
5786
|
-
|
|
5823
|
+
(_g = this.logger) === null || _g === void 0 ? void 0 : _g.call(this, 'warn', 'null ice candidate');
|
|
5787
5824
|
return;
|
|
5788
5825
|
}
|
|
5789
5826
|
yield this.sfuClient.iceTrickle({
|
|
@@ -5792,7 +5829,8 @@ class Publisher {
|
|
|
5792
5829
|
});
|
|
5793
5830
|
});
|
|
5794
5831
|
this.onNegotiationNeeded = () => __awaiter(this, void 0, void 0, function* () {
|
|
5795
|
-
|
|
5832
|
+
var _h, _j;
|
|
5833
|
+
(_h = this.logger) === null || _h === void 0 ? void 0 : _h.call(this, 'info', 'AAA onNegotiationNeeded');
|
|
5796
5834
|
const offer = yield this.publisher.createOffer();
|
|
5797
5835
|
let sdp = offer.sdp;
|
|
5798
5836
|
if (sdp) {
|
|
@@ -5855,28 +5893,38 @@ class Publisher {
|
|
|
5855
5893
|
});
|
|
5856
5894
|
}
|
|
5857
5895
|
catch (e) {
|
|
5858
|
-
|
|
5896
|
+
(_j = this.logger) === null || _j === void 0 ? void 0 : _j.call(this, 'error', `Publisher: setRemoteDescription error`, {
|
|
5897
|
+
sdp: response.sdp,
|
|
5898
|
+
error: e,
|
|
5899
|
+
});
|
|
5859
5900
|
}
|
|
5860
5901
|
this.sfuClient.iceTrickleBuffer.publisherCandidates.subscribe((candidate) => __awaiter(this, void 0, void 0, function* () {
|
|
5902
|
+
var _k;
|
|
5861
5903
|
try {
|
|
5862
5904
|
const iceCandidate = JSON.parse(candidate.iceCandidate);
|
|
5863
5905
|
yield this.publisher.addIceCandidate(iceCandidate);
|
|
5864
5906
|
}
|
|
5865
5907
|
catch (e) {
|
|
5866
|
-
|
|
5908
|
+
(_k = this.logger) === null || _k === void 0 ? void 0 : _k.call(this, 'error', `Publisher: ICE candidate error`, {
|
|
5909
|
+
error: e,
|
|
5910
|
+
candidate,
|
|
5911
|
+
});
|
|
5867
5912
|
}
|
|
5868
5913
|
}));
|
|
5869
5914
|
});
|
|
5870
5915
|
this.onIceCandidateError = (e) => {
|
|
5916
|
+
var _a;
|
|
5871
5917
|
const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
|
|
5872
5918
|
`${e.errorCode}: ${e.errorText}`;
|
|
5873
|
-
|
|
5919
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Candidate error`, errorMessage);
|
|
5874
5920
|
};
|
|
5875
5921
|
this.onIceConnectionStateChange = () => {
|
|
5876
|
-
|
|
5922
|
+
var _a;
|
|
5923
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Connection state changed`, this.publisher.iceConnectionState);
|
|
5877
5924
|
};
|
|
5878
5925
|
this.onIceGatheringStateChange = () => {
|
|
5879
|
-
|
|
5926
|
+
var _a;
|
|
5927
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, 'error', `Publisher: ICE Gathering State`, this.publisher.iceGatheringState);
|
|
5880
5928
|
};
|
|
5881
5929
|
this.ridToVideoQuality = (rid) => {
|
|
5882
5930
|
return rid === 'q'
|
|
@@ -5909,12 +5957,13 @@ class Publisher {
|
|
|
5909
5957
|
}
|
|
5910
5958
|
|
|
5911
5959
|
const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, }) => {
|
|
5960
|
+
const logger = getLogger(['sfu-client']);
|
|
5912
5961
|
const subscriber = new RTCPeerConnection(connectionConfig);
|
|
5913
5962
|
attachDebugEventListeners(subscriber);
|
|
5914
5963
|
subscriber.addEventListener('icecandidate', (e) => __awaiter(void 0, void 0, void 0, function* () {
|
|
5915
5964
|
const { candidate } = e;
|
|
5916
5965
|
if (!candidate) {
|
|
5917
|
-
|
|
5966
|
+
logger === null || logger === void 0 ? void 0 : logger('warn', 'null ice candidate');
|
|
5918
5967
|
return;
|
|
5919
5968
|
}
|
|
5920
5969
|
yield sfuClient.iceTrickle({
|
|
@@ -5930,7 +5979,7 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
|
|
|
5930
5979
|
if (message.eventPayload.oneofKind !== 'subscriberOffer')
|
|
5931
5980
|
return;
|
|
5932
5981
|
const { subscriberOffer } = message.eventPayload;
|
|
5933
|
-
|
|
5982
|
+
logger === null || logger === void 0 ? void 0 : logger('info', 'Received subscriberOffer', subscriberOffer);
|
|
5934
5983
|
yield subscriber.setRemoteDescription({
|
|
5935
5984
|
type: 'offer',
|
|
5936
5985
|
sdp: subscriberOffer.sdp,
|
|
@@ -5941,7 +5990,10 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
|
|
|
5941
5990
|
yield subscriber.addIceCandidate(iceCandidate);
|
|
5942
5991
|
}
|
|
5943
5992
|
catch (e) {
|
|
5944
|
-
|
|
5993
|
+
logger === null || logger === void 0 ? void 0 : logger('error', `Subscriber: ICE candidate error`, {
|
|
5994
|
+
error: e,
|
|
5995
|
+
candidate,
|
|
5996
|
+
});
|
|
5945
5997
|
}
|
|
5946
5998
|
}));
|
|
5947
5999
|
// apply ice candidates
|
|
@@ -5964,31 +6016,33 @@ const createSubscriber = ({ sfuClient, dispatcher, connectionConfig, onTrack, })
|
|
|
5964
6016
|
return subscriber;
|
|
5965
6017
|
};
|
|
5966
6018
|
const attachDebugEventListeners = (subscriber) => {
|
|
6019
|
+
const logger = getLogger(['sfu-client']);
|
|
5967
6020
|
subscriber.addEventListener('icecandidateerror', (e) => {
|
|
5968
6021
|
const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
|
|
5969
6022
|
`${e.errorCode}: ${e.errorText}`;
|
|
5970
|
-
|
|
6023
|
+
logger === null || logger === void 0 ? void 0 : logger('error', `Subscriber: ICE Candidate error: ${errorMessage}`);
|
|
5971
6024
|
});
|
|
5972
6025
|
subscriber.addEventListener('iceconnectionstatechange', () => {
|
|
5973
|
-
|
|
6026
|
+
logger === null || logger === void 0 ? void 0 : logger('info', `Subscriber: ICE Connection state changed: ${subscriber.iceConnectionState}`);
|
|
5974
6027
|
});
|
|
5975
6028
|
subscriber.addEventListener('icegatheringstatechange', () => {
|
|
5976
|
-
|
|
6029
|
+
logger === null || logger === void 0 ? void 0 : logger('info', `Subscriber: ICE Gathering State: ${subscriber.iceGatheringState}`);
|
|
5977
6030
|
});
|
|
5978
6031
|
};
|
|
5979
6032
|
|
|
5980
6033
|
const createWebSocketSignalChannel = (opts) => {
|
|
6034
|
+
const logger = getLogger(['sfu-client']);
|
|
5981
6035
|
const { endpoint, onMessage } = opts;
|
|
5982
6036
|
const ws = new WebSocket(endpoint);
|
|
5983
6037
|
ws.binaryType = 'arraybuffer'; // do we need this?
|
|
5984
6038
|
ws.addEventListener('error', (e) => {
|
|
5985
|
-
|
|
6039
|
+
logger === null || logger === void 0 ? void 0 : logger('error', 'Signaling WS channel error', e);
|
|
5986
6040
|
});
|
|
5987
6041
|
ws.addEventListener('close', (e) => {
|
|
5988
|
-
|
|
6042
|
+
logger === null || logger === void 0 ? void 0 : logger('info', 'Signaling WS channel is closed', e);
|
|
5989
6043
|
});
|
|
5990
6044
|
ws.addEventListener('open', (e) => {
|
|
5991
|
-
|
|
6045
|
+
logger === null || logger === void 0 ? void 0 : logger('info', 'Signaling WS channel is open', e);
|
|
5992
6046
|
});
|
|
5993
6047
|
if (onMessage) {
|
|
5994
6048
|
ws.addEventListener('message', (e) => {
|
|
@@ -5999,7 +6053,7 @@ const createWebSocketSignalChannel = (opts) => {
|
|
|
5999
6053
|
onMessage(message);
|
|
6000
6054
|
}
|
|
6001
6055
|
catch (err) {
|
|
6002
|
-
|
|
6056
|
+
logger === null || logger === void 0 ? void 0 : logger('error', 'Failed to decode a message. Check whether the Proto models match.', { event: e, error: err });
|
|
6003
6057
|
}
|
|
6004
6058
|
});
|
|
6005
6059
|
}
|
|
@@ -6100,14 +6154,14 @@ function convertErrorToJson(err) {
|
|
|
6100
6154
|
* isOnline safely return the navigator.online value for browser env
|
|
6101
6155
|
* if navigator is not in global object, it always return true
|
|
6102
6156
|
*/
|
|
6103
|
-
function isOnline() {
|
|
6157
|
+
function isOnline(logger) {
|
|
6104
6158
|
const nav = typeof navigator !== 'undefined'
|
|
6105
6159
|
? navigator
|
|
6106
6160
|
: typeof window !== 'undefined' && window.navigator
|
|
6107
6161
|
? window.navigator
|
|
6108
6162
|
: undefined;
|
|
6109
6163
|
if (!nav) {
|
|
6110
|
-
|
|
6164
|
+
logger('warn', 'isOnline failed to access window.navigator and assume browser is online');
|
|
6111
6165
|
return true;
|
|
6112
6166
|
}
|
|
6113
6167
|
// RN navigator has undefined for onLine
|
|
@@ -6163,16 +6217,16 @@ class StreamSfuClient {
|
|
|
6163
6217
|
return retryable(() => this.rpc.updateSubscriptions({
|
|
6164
6218
|
sessionId: this.sessionId,
|
|
6165
6219
|
tracks: subscriptions,
|
|
6166
|
-
}));
|
|
6220
|
+
}), this.logger);
|
|
6167
6221
|
});
|
|
6168
6222
|
this.setPublisher = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6169
|
-
return retryable(() => this.rpc.setPublisher(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
6223
|
+
return retryable(() => this.rpc.setPublisher(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
6170
6224
|
});
|
|
6171
6225
|
this.sendAnswer = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6172
|
-
return retryable(() => this.rpc.sendAnswer(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
6226
|
+
return retryable(() => this.rpc.sendAnswer(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
6173
6227
|
});
|
|
6174
6228
|
this.iceTrickle = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6175
|
-
return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
6229
|
+
return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
6176
6230
|
});
|
|
6177
6231
|
this.updateMuteState = (trackType, muted) => __awaiter(this, void 0, void 0, function* () {
|
|
6178
6232
|
return this.updateMuteStates({
|
|
@@ -6185,7 +6239,7 @@ class StreamSfuClient {
|
|
|
6185
6239
|
});
|
|
6186
6240
|
});
|
|
6187
6241
|
this.updateMuteStates = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6188
|
-
return retryable(() => this.rpc.updateMuteStates(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })));
|
|
6242
|
+
return retryable(() => this.rpc.updateMuteStates(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
6189
6243
|
});
|
|
6190
6244
|
this.join = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6191
6245
|
const joinRequest = JoinRequest.create(Object.assign(Object.assign({}, data), { sessionId: this.sessionId, token: this.token }));
|
|
@@ -6206,7 +6260,7 @@ class StreamSfuClient {
|
|
|
6206
6260
|
clearInterval(this.keepAliveInterval);
|
|
6207
6261
|
}
|
|
6208
6262
|
this.keepAliveInterval = setInterval(() => {
|
|
6209
|
-
|
|
6263
|
+
this.logger('info', 'Sending healthCheckRequest to SFU');
|
|
6210
6264
|
const message = SfuRequest.create({
|
|
6211
6265
|
requestPayload: {
|
|
6212
6266
|
oneofKind: 'healthCheckRequest',
|
|
@@ -6224,7 +6278,7 @@ class StreamSfuClient {
|
|
|
6224
6278
|
if (this.lastMessageTimestamp) {
|
|
6225
6279
|
const timeSinceLastMessage = new Date().getTime() - this.lastMessageTimestamp.getTime();
|
|
6226
6280
|
if (timeSinceLastMessage > this.unhealthyTimeoutInMs) {
|
|
6227
|
-
|
|
6281
|
+
this.logger('error', 'SFU connection unhealthy, closing');
|
|
6228
6282
|
this.close(4001, `SFU connection unhealthy. Didn't receive any healthcheck messages for ${this.unhealthyTimeoutInMs}ms`);
|
|
6229
6283
|
}
|
|
6230
6284
|
}
|
|
@@ -6232,12 +6286,22 @@ class StreamSfuClient {
|
|
|
6232
6286
|
};
|
|
6233
6287
|
this.sessionId = sessionId || generateUUIDv4();
|
|
6234
6288
|
this.token = token;
|
|
6289
|
+
this.logger = getLogger(['sfu-client']);
|
|
6290
|
+
const logger = this.logger;
|
|
6291
|
+
const logInterceptor = {
|
|
6292
|
+
interceptUnary(next, method, input, options) {
|
|
6293
|
+
logger('info', `Calling SFU RPC method ${method.name}`);
|
|
6294
|
+
logger('debug', `Method call payload`, { input, options });
|
|
6295
|
+
return next(method, input, options);
|
|
6296
|
+
},
|
|
6297
|
+
};
|
|
6235
6298
|
this.rpc = createSignalClient({
|
|
6236
6299
|
baseUrl: url,
|
|
6237
6300
|
interceptors: [
|
|
6238
6301
|
withHeaders({
|
|
6239
6302
|
Authorization: `Bearer ${token}`,
|
|
6240
6303
|
}),
|
|
6304
|
+
logInterceptor,
|
|
6241
6305
|
],
|
|
6242
6306
|
});
|
|
6243
6307
|
// Special handling for the ICETrickle kind of events.
|
|
@@ -6279,7 +6343,7 @@ const MAX_RETRIES = 5;
|
|
|
6279
6343
|
* @param <I> the type of the request object.
|
|
6280
6344
|
* @param <O> the type of the response object.
|
|
6281
6345
|
*/
|
|
6282
|
-
const retryable = (rpc) => __awaiter(void 0, void 0, void 0, function* () {
|
|
6346
|
+
const retryable = (rpc, logger) => __awaiter(void 0, void 0, void 0, function* () {
|
|
6283
6347
|
var _a;
|
|
6284
6348
|
let retryAttempt = 0;
|
|
6285
6349
|
let rpcCallResult;
|
|
@@ -6289,9 +6353,11 @@ const retryable = (rpc) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
6289
6353
|
yield sleep(retryInterval(retryAttempt));
|
|
6290
6354
|
}
|
|
6291
6355
|
rpcCallResult = yield rpc();
|
|
6356
|
+
logger('info', `SFU RPC response received for ${rpcCallResult.method.name}`);
|
|
6357
|
+
logger('debug', `Response payload`, rpcCallResult);
|
|
6292
6358
|
// if the RPC call failed, log the error and retry
|
|
6293
6359
|
if (rpcCallResult.response.error) {
|
|
6294
|
-
|
|
6360
|
+
logger('error', 'SFU RPC Error:', rpcCallResult.response.error);
|
|
6295
6361
|
}
|
|
6296
6362
|
retryAttempt++;
|
|
6297
6363
|
} while (((_a = rpcCallResult.response.error) === null || _a === void 0 ? void 0 : _a.shouldRetry) &&
|
|
@@ -6974,7 +7040,7 @@ class CallState {
|
|
|
6974
7040
|
this.updateParticipant = (sessionId, patch) => {
|
|
6975
7041
|
const participant = this.findParticipantBySessionId(sessionId);
|
|
6976
7042
|
if (!participant) {
|
|
6977
|
-
|
|
7043
|
+
this.logger('warn', `Participant with sessionId ${sessionId} not found`);
|
|
6978
7044
|
return;
|
|
6979
7045
|
}
|
|
6980
7046
|
const thePatch = typeof patch === 'function' ? patch(participant) : patch;
|
|
@@ -7023,9 +7089,10 @@ class CallState {
|
|
|
7023
7089
|
return p;
|
|
7024
7090
|
}));
|
|
7025
7091
|
};
|
|
7092
|
+
this.logger = getLogger(['call-state']);
|
|
7026
7093
|
this.participants$ = this.participantsSubject.pipe(map$1((ps) => ps.sort(this.sortParticipantsBy)));
|
|
7027
7094
|
this.localParticipant$ = this.participants$.pipe(map$1((participants) => participants.find(isStreamVideoLocalParticipant)));
|
|
7028
|
-
this.remoteParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => !p.
|
|
7095
|
+
this.remoteParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => !p.isLocalParticipant)));
|
|
7029
7096
|
this.pinnedParticipants$ = this.participants$.pipe(map$1((participants) => participants.filter((p) => p.pinnedAt)));
|
|
7030
7097
|
this.dominantSpeaker$ = this.participants$.pipe(map$1((participants) => participants.find((p) => p.isDominantSpeaker)));
|
|
7031
7098
|
this.hasOngoingScreenShare$ = this.participants$.pipe(map$1((participants) => {
|
|
@@ -7179,13 +7246,13 @@ const watchCallRejected = (call) => {
|
|
|
7179
7246
|
const { call: eventCall } = event;
|
|
7180
7247
|
const { session: callSession } = eventCall;
|
|
7181
7248
|
if (!callSession) {
|
|
7182
|
-
|
|
7249
|
+
call.logger('warn', 'No call session provided. Ignoring call.rejected event.', event);
|
|
7183
7250
|
return;
|
|
7184
7251
|
}
|
|
7185
7252
|
const rejectedBy = callSession.rejected_by;
|
|
7186
7253
|
const { members, callingState } = call.state;
|
|
7187
7254
|
if (callingState !== CallingState.RINGING) {
|
|
7188
|
-
|
|
7255
|
+
call.logger('warn', 'Call is not in ringing mode (it is either accepted or rejected already). Ignoring call.rejected event.', event);
|
|
7189
7256
|
return;
|
|
7190
7257
|
}
|
|
7191
7258
|
if (call.isCreatedByMe) {
|
|
@@ -7193,13 +7260,13 @@ const watchCallRejected = (call) => {
|
|
|
7193
7260
|
.filter((m) => m.user_id !== call.currentUserId)
|
|
7194
7261
|
.every((m) => rejectedBy[m.user_id]);
|
|
7195
7262
|
if (everyoneElseRejected) {
|
|
7196
|
-
|
|
7263
|
+
call.logger('info', 'everyone rejected, leaving the call');
|
|
7197
7264
|
yield call.leave();
|
|
7198
7265
|
}
|
|
7199
7266
|
}
|
|
7200
7267
|
else {
|
|
7201
7268
|
if (rejectedBy[eventCall.created_by.id]) {
|
|
7202
|
-
|
|
7269
|
+
call.logger('info', 'call creator rejected, leaving call');
|
|
7203
7270
|
yield call.leave();
|
|
7204
7271
|
}
|
|
7205
7272
|
}
|
|
@@ -7607,7 +7674,7 @@ const watchCallSessionParticipantJoined = (state) => {
|
|
|
7607
7674
|
const { user } = event;
|
|
7608
7675
|
state.setMetadata((metadata) => {
|
|
7609
7676
|
if (!metadata || !metadata.session) {
|
|
7610
|
-
|
|
7677
|
+
state.logger('warn', `Received call.session_participant_joined event but the metadata structure is invalid.`, event);
|
|
7611
7678
|
return metadata;
|
|
7612
7679
|
}
|
|
7613
7680
|
const { session } = metadata;
|
|
@@ -7635,7 +7702,7 @@ const watchCallSessionParticipantLeft = (state) => {
|
|
|
7635
7702
|
const { user } = event;
|
|
7636
7703
|
state.setMetadata((metadata) => {
|
|
7637
7704
|
if (!metadata || !metadata.session) {
|
|
7638
|
-
|
|
7705
|
+
state.logger('warn', `Received call.session_participant_left event but the metadata structure is invalid.`, event);
|
|
7639
7706
|
return metadata;
|
|
7640
7707
|
}
|
|
7641
7708
|
const { session } = metadata;
|
|
@@ -7780,16 +7847,18 @@ const getLocationHint = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
7780
7847
|
const hintURL = `https://hint.stream-io-video.com/`;
|
|
7781
7848
|
const abortController = new AbortController();
|
|
7782
7849
|
const timeoutId = setTimeout(() => abortController.abort(), 1000);
|
|
7850
|
+
const logger = getLogger(['call']);
|
|
7783
7851
|
try {
|
|
7784
7852
|
const response = yield fetch(hintURL, {
|
|
7785
7853
|
method: 'HEAD',
|
|
7786
7854
|
signal: abortController.signal,
|
|
7787
7855
|
});
|
|
7788
7856
|
const awsPop = response.headers.get('x-amz-cf-pop') || 'ERR';
|
|
7857
|
+
logger === null || logger === void 0 ? void 0 : logger('info', `Location header: ${awsPop}`);
|
|
7789
7858
|
return awsPop.substring(0, 3); // AMS1-P2 -> AMS
|
|
7790
7859
|
}
|
|
7791
7860
|
catch (e) {
|
|
7792
|
-
|
|
7861
|
+
logger === null || logger === void 0 ? void 0 : logger('error', `Failed to get location hint from ${hintURL}`, e);
|
|
7793
7862
|
return 'ERR';
|
|
7794
7863
|
}
|
|
7795
7864
|
finally {
|
|
@@ -7828,6 +7897,7 @@ const getCascadingModeParams = () => {
|
|
|
7828
7897
|
* Creates a new StatsReporter instance that collects metrics about the ongoing call and reports them to the state store
|
|
7829
7898
|
*/
|
|
7830
7899
|
const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIntervalInMs = 2000, }) => {
|
|
7900
|
+
const logger = getLogger(['stats']);
|
|
7831
7901
|
const getRawStatsForTrack = (kind, selector) => __awaiter(void 0, void 0, void 0, function* () {
|
|
7832
7902
|
if (kind === 'subscriber' && subscriber) {
|
|
7833
7903
|
return subscriber.getStats(selector);
|
|
@@ -7836,7 +7906,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
|
|
|
7836
7906
|
return publisher.getStats(selector);
|
|
7837
7907
|
}
|
|
7838
7908
|
else {
|
|
7839
|
-
|
|
7909
|
+
logger('warn', `Can't retrieve RTC stats for ${kind}`);
|
|
7840
7910
|
return undefined;
|
|
7841
7911
|
}
|
|
7842
7912
|
});
|
|
@@ -7874,7 +7944,9 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
|
|
|
7874
7944
|
for (let participant of state.participants) {
|
|
7875
7945
|
if (!sessionIds.has(participant.sessionId))
|
|
7876
7946
|
continue;
|
|
7877
|
-
const kind = participant.
|
|
7947
|
+
const kind = participant.isLocalParticipant
|
|
7948
|
+
? 'publisher'
|
|
7949
|
+
: 'subscriber';
|
|
7878
7950
|
try {
|
|
7879
7951
|
const mergedStream = new MediaStream([
|
|
7880
7952
|
...(((_a = participant.videoStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()) || []),
|
|
@@ -7886,7 +7958,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
|
|
|
7886
7958
|
});
|
|
7887
7959
|
}
|
|
7888
7960
|
catch (e) {
|
|
7889
|
-
|
|
7961
|
+
logger('error', `Failed to collect stats for ${kind} if ${participant.userId}`, e);
|
|
7890
7962
|
}
|
|
7891
7963
|
}
|
|
7892
7964
|
}
|
|
@@ -7924,7 +7996,7 @@ const createStatsReporter = ({ subscriber, publisher, state, edgeName, pollingIn
|
|
|
7924
7996
|
if (pollingIntervalInMs > 0) {
|
|
7925
7997
|
const loop = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
7926
7998
|
yield run().catch((e) => {
|
|
7927
|
-
|
|
7999
|
+
logger('warn', 'Failed to collect stats', e);
|
|
7928
8000
|
});
|
|
7929
8001
|
timeoutId = setTimeout(loop, pollingIntervalInMs);
|
|
7930
8002
|
});
|
|
@@ -8467,6 +8539,9 @@ class Call {
|
|
|
8467
8539
|
if ([CallingState.JOINED, CallingState.JOINING].includes(this.state.callingState)) {
|
|
8468
8540
|
throw new Error(`Illegal State: Already joined.`);
|
|
8469
8541
|
}
|
|
8542
|
+
if (this.state.callingState === CallingState.LEFT) {
|
|
8543
|
+
throw new Error('Illegal State: Cannot join already left call. Create a new Call instance to join a call.');
|
|
8544
|
+
}
|
|
8470
8545
|
const previousCallingState = this.state.callingState;
|
|
8471
8546
|
this.state.setCallingState(CallingState.JOINING);
|
|
8472
8547
|
if ((data === null || data === void 0 ? void 0 : data.ring) && !this.ringing) {
|
|
@@ -8522,7 +8597,7 @@ class Call {
|
|
|
8522
8597
|
*/
|
|
8523
8598
|
const rejoin = () => __awaiter(this, void 0, void 0, function* () {
|
|
8524
8599
|
var _g, _h, _j;
|
|
8525
|
-
|
|
8600
|
+
this.logger('debug', `Rejoining call ${this.cid} (${this.reconnectAttempts})...`);
|
|
8526
8601
|
this.reconnectAttempts++;
|
|
8527
8602
|
this.state.setCallingState(CallingState.RECONNECTING);
|
|
8528
8603
|
// take a snapshot of the current "local participant" state
|
|
@@ -8534,7 +8609,7 @@ class Call {
|
|
|
8534
8609
|
sfuClient.close(); // clean up previous connection
|
|
8535
8610
|
yield sleep(retryInterval(this.reconnectAttempts));
|
|
8536
8611
|
yield this.join(data);
|
|
8537
|
-
|
|
8612
|
+
this.logger('info', `Rejoin: ${this.reconnectAttempts} successful!`);
|
|
8538
8613
|
if (localParticipant && !isReactNative()) {
|
|
8539
8614
|
const { audioStream, videoStream, screenShareStream: screenShare, } = localParticipant;
|
|
8540
8615
|
// restore previous publishing state
|
|
@@ -8545,7 +8620,7 @@ class Call {
|
|
|
8545
8620
|
if (screenShare)
|
|
8546
8621
|
yield this.publishScreenShareStream(screenShare);
|
|
8547
8622
|
}
|
|
8548
|
-
|
|
8623
|
+
this.logger('info', `Rejoin: state restored ${this.reconnectAttempts}`);
|
|
8549
8624
|
});
|
|
8550
8625
|
this.rejoinPromise = rejoin;
|
|
8551
8626
|
// reconnect if the connection was closed unexpectedly. example:
|
|
@@ -8565,12 +8640,12 @@ class Call {
|
|
|
8565
8640
|
return;
|
|
8566
8641
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
8567
8642
|
rejoin().catch(() => {
|
|
8568
|
-
|
|
8643
|
+
this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
|
|
8569
8644
|
this.state.setCallingState(CallingState.RECONNECTING_FAILED);
|
|
8570
8645
|
});
|
|
8571
8646
|
}
|
|
8572
8647
|
else {
|
|
8573
|
-
|
|
8648
|
+
this.logger('error', 'Reconnect attempts exceeded. Giving up...');
|
|
8574
8649
|
this.state.setCallingState(CallingState.RECONNECTING_FAILED);
|
|
8575
8650
|
}
|
|
8576
8651
|
});
|
|
@@ -8580,15 +8655,15 @@ class Call {
|
|
|
8580
8655
|
if (typeof window !== 'undefined' && window.addEventListener) {
|
|
8581
8656
|
const handleOnOffline = () => {
|
|
8582
8657
|
window.removeEventListener('offline', handleOnOffline);
|
|
8583
|
-
|
|
8658
|
+
this.logger('warn', 'Join: Going offline...');
|
|
8584
8659
|
this.state.setCallingState(CallingState.OFFLINE);
|
|
8585
8660
|
};
|
|
8586
8661
|
const handleOnOnline = () => {
|
|
8587
8662
|
window.removeEventListener('online', handleOnOnline);
|
|
8588
8663
|
if (this.state.callingState === CallingState.OFFLINE) {
|
|
8589
|
-
|
|
8664
|
+
this.logger('info', 'Join: Going online...');
|
|
8590
8665
|
rejoin().catch(() => {
|
|
8591
|
-
|
|
8666
|
+
this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
|
|
8592
8667
|
this.state.setCallingState(CallingState.RECONNECTING_FAILED);
|
|
8593
8668
|
});
|
|
8594
8669
|
}
|
|
@@ -8645,15 +8720,20 @@ class Call {
|
|
|
8645
8720
|
clientDetails.sdk = getSdkInfo();
|
|
8646
8721
|
// 1. wait for the signal server to be ready before sending "joinRequest"
|
|
8647
8722
|
sfuClient.signalReady
|
|
8648
|
-
.catch((err) =>
|
|
8723
|
+
.catch((err) => this.logger('error', 'Signal ready failed', err))
|
|
8649
8724
|
// prepare a generic SDP and send it to the SFU.
|
|
8650
8725
|
// this is a throw-away SDP that the SFU will use to determine
|
|
8651
8726
|
// the capabilities of the client (codec support, etc.)
|
|
8652
8727
|
.then(() => getGenericSdp('recvonly', isRedEnabled, this.streamClient.options.preferredVideoCodec))
|
|
8653
|
-
.then((sdp) =>
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
8728
|
+
.then((sdp) => {
|
|
8729
|
+
const joinRequest = {
|
|
8730
|
+
subscriberSdp: sdp || '',
|
|
8731
|
+
clientDetails,
|
|
8732
|
+
};
|
|
8733
|
+
this.logger('info', 'Sending join request to SFU');
|
|
8734
|
+
this.logger('debug', 'Join request payload', joinRequest);
|
|
8735
|
+
sfuClient.join(joinRequest);
|
|
8736
|
+
});
|
|
8657
8737
|
// 2. in parallel, wait for the SFU to send us the "joinResponse"
|
|
8658
8738
|
// this will throw an error if the SFU rejects the join request or
|
|
8659
8739
|
// fails to respond in time
|
|
@@ -8663,22 +8743,22 @@ class Call {
|
|
|
8663
8743
|
const startedAt = (callState === null || callState === void 0 ? void 0 : callState.startedAt)
|
|
8664
8744
|
? Timestamp.toDate(callState.startedAt)
|
|
8665
8745
|
: new Date();
|
|
8666
|
-
this.state.setParticipants(currentParticipants.map((participant) => (Object.assign(Object.assign({}, participant), {
|
|
8746
|
+
this.state.setParticipants(currentParticipants.map((participant) => (Object.assign(Object.assign({}, participant), { isLocalParticipant: participant.sessionId === sfuClient.sessionId, viewportVisibilityState: VisibilityState.UNKNOWN }))));
|
|
8667
8747
|
this.state.setParticipantCount((participantCount === null || participantCount === void 0 ? void 0 : participantCount.total) || 0);
|
|
8668
8748
|
this.state.setAnonymousParticipantCount((participantCount === null || participantCount === void 0 ? void 0 : participantCount.anonymous) || 0);
|
|
8669
8749
|
this.state.setStartedAt(startedAt);
|
|
8670
8750
|
this.reconnectAttempts = 0; // reset the reconnect attempts counter
|
|
8671
8751
|
this.state.setCallingState(CallingState.JOINED);
|
|
8672
|
-
|
|
8752
|
+
this.logger('info', `Joined call ${this.cid}`);
|
|
8673
8753
|
}
|
|
8674
8754
|
catch (err) {
|
|
8675
8755
|
// join failed, try to rejoin
|
|
8676
8756
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
|
8677
8757
|
yield rejoin();
|
|
8678
|
-
|
|
8758
|
+
this.logger('info', `Rejoin ${this.reconnectAttempts} successful!`);
|
|
8679
8759
|
}
|
|
8680
8760
|
else {
|
|
8681
|
-
|
|
8761
|
+
this.logger('error', `Rejoin failed for ${this.reconnectAttempts} times. Giving up.`);
|
|
8682
8762
|
this.state.setCallingState(CallingState.RECONNECTING_FAILED);
|
|
8683
8763
|
throw new Error('Join failed');
|
|
8684
8764
|
}
|
|
@@ -8703,7 +8783,8 @@ class Call {
|
|
|
8703
8783
|
}
|
|
8704
8784
|
const [videoTrack] = videoStream.getVideoTracks();
|
|
8705
8785
|
if (!videoTrack) {
|
|
8706
|
-
|
|
8786
|
+
this.logger('error', `There is no video track to publish in the stream.`);
|
|
8787
|
+
return;
|
|
8707
8788
|
}
|
|
8708
8789
|
yield this.publisher.publishStream(videoStream, videoTrack, TrackType.VIDEO, opts);
|
|
8709
8790
|
});
|
|
@@ -8726,7 +8807,8 @@ class Call {
|
|
|
8726
8807
|
}
|
|
8727
8808
|
const [audioTrack] = audioStream.getAudioTracks();
|
|
8728
8809
|
if (!audioTrack) {
|
|
8729
|
-
|
|
8810
|
+
this.logger('error', `There is no audio track in the stream to publish`);
|
|
8811
|
+
return;
|
|
8730
8812
|
}
|
|
8731
8813
|
yield this.publisher.publishStream(audioStream, audioTrack, TrackType.AUDIO);
|
|
8732
8814
|
});
|
|
@@ -8748,7 +8830,8 @@ class Call {
|
|
|
8748
8830
|
}
|
|
8749
8831
|
const [screenShareTrack] = screenShareStream.getVideoTracks();
|
|
8750
8832
|
if (!screenShareTrack) {
|
|
8751
|
-
|
|
8833
|
+
this.logger('error', `There is no video track in the screen share stream to publish`);
|
|
8834
|
+
return;
|
|
8752
8835
|
}
|
|
8753
8836
|
yield this.publisher.publishStream(screenShareStream, screenShareTrack, TrackType.SCREEN_SHARE);
|
|
8754
8837
|
});
|
|
@@ -8763,7 +8846,7 @@ class Call {
|
|
|
8763
8846
|
*/
|
|
8764
8847
|
this.stopPublish = (trackType) => __awaiter(this, void 0, void 0, function* () {
|
|
8765
8848
|
var _k;
|
|
8766
|
-
|
|
8849
|
+
this.logger('info', `stopPublish ${TrackType[trackType]}`);
|
|
8767
8850
|
yield ((_k = this.publisher) === null || _k === void 0 ? void 0 : _k.unpublishStream(trackType));
|
|
8768
8851
|
});
|
|
8769
8852
|
/**
|
|
@@ -8797,7 +8880,7 @@ class Call {
|
|
|
8797
8880
|
const subscriptions = [];
|
|
8798
8881
|
participants.forEach((p) => {
|
|
8799
8882
|
// we don't want to subscribe to our own tracks
|
|
8800
|
-
if (p.
|
|
8883
|
+
if (p.isLocalParticipant)
|
|
8801
8884
|
return;
|
|
8802
8885
|
// NOTE: audio tracks don't have to be requested explicitly
|
|
8803
8886
|
// as the SFU will implicitly subscribe us to all of them,
|
|
@@ -8912,20 +8995,21 @@ class Call {
|
|
|
8912
8995
|
const [primaryStream] = e.streams;
|
|
8913
8996
|
// example: `e3f6aaf8-b03d-4911-be36-83f47d37a76a:TRACK_TYPE_VIDEO`
|
|
8914
8997
|
const [trackId, trackType] = primaryStream.id.split(':');
|
|
8915
|
-
|
|
8998
|
+
this.logger('info', `Got remote ${trackType} track:`);
|
|
8999
|
+
this.logger('debug', `Track: `, e.track);
|
|
8916
9000
|
const participantToUpdate = this.state.participants.find((p) => p.trackLookupPrefix === trackId);
|
|
8917
9001
|
if (!participantToUpdate) {
|
|
8918
|
-
|
|
9002
|
+
this.logger('error', `'Received track for unknown participant: ${trackId}'`, e);
|
|
8919
9003
|
return;
|
|
8920
9004
|
}
|
|
8921
9005
|
e.track.addEventListener('mute', () => {
|
|
8922
|
-
|
|
9006
|
+
this.logger('info', `Track muted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
|
|
8923
9007
|
});
|
|
8924
9008
|
e.track.addEventListener('unmute', () => {
|
|
8925
|
-
|
|
9009
|
+
this.logger('info', `Track unmuted: ${participantToUpdate.userId} ${trackType}:${trackId}`);
|
|
8926
9010
|
});
|
|
8927
9011
|
e.track.addEventListener('ended', () => {
|
|
8928
|
-
|
|
9012
|
+
this.logger('info', `Track ended: ${participantToUpdate.userId} ${trackType}:${trackId}`);
|
|
8929
9013
|
});
|
|
8930
9014
|
const streamKindProp = {
|
|
8931
9015
|
TRACK_TYPE_AUDIO: 'audioStream',
|
|
@@ -8933,12 +9017,12 @@ class Call {
|
|
|
8933
9017
|
TRACK_TYPE_SCREEN_SHARE: 'screenShareStream',
|
|
8934
9018
|
}[trackType];
|
|
8935
9019
|
if (!streamKindProp) {
|
|
8936
|
-
|
|
9020
|
+
this.logger('error', `Unknown track type: ${trackType}`);
|
|
8937
9021
|
return;
|
|
8938
9022
|
}
|
|
8939
9023
|
const previousStream = participantToUpdate[streamKindProp];
|
|
8940
9024
|
if (previousStream) {
|
|
8941
|
-
|
|
9025
|
+
this.logger('info', `Cleaning up previous remote tracks: ${e.track.kind}`);
|
|
8942
9026
|
previousStream.getTracks().forEach((t) => {
|
|
8943
9027
|
t.stop();
|
|
8944
9028
|
previousStream.removeTrack(t);
|
|
@@ -9238,6 +9322,7 @@ class Call {
|
|
|
9238
9322
|
this.streamClient = streamClient;
|
|
9239
9323
|
this.clientStore = clientStore;
|
|
9240
9324
|
this.streamClientBasePath = `/call/${this.type}/${this.id}`;
|
|
9325
|
+
this.logger = getLogger(['call']);
|
|
9241
9326
|
const callTypeConfig = CallTypes.get(type);
|
|
9242
9327
|
const participantSorter = sortParticipantsBy || callTypeConfig.options.sortParticipantsBy;
|
|
9243
9328
|
if (participantSorter) {
|
|
@@ -9275,7 +9360,7 @@ class Call {
|
|
|
9275
9360
|
const hasPermission = this.permissionsContext.hasPermission(permission);
|
|
9276
9361
|
if (!hasPermission && this.publisher.isPublishing(trackType)) {
|
|
9277
9362
|
this.stopPublish(trackType).catch((err) => {
|
|
9278
|
-
|
|
9363
|
+
this.logger('error', `Error stopping publish ${trackType}`, err);
|
|
9279
9364
|
});
|
|
9280
9365
|
}
|
|
9281
9366
|
}
|
|
@@ -9496,12 +9581,12 @@ class StableWSConnection {
|
|
|
9496
9581
|
return;
|
|
9497
9582
|
const user = this.client.user;
|
|
9498
9583
|
if (!user) {
|
|
9499
|
-
|
|
9584
|
+
this.client.logger('error', `User not set, can't connect to WS`);
|
|
9500
9585
|
return;
|
|
9501
9586
|
}
|
|
9502
9587
|
const token = this.client._getToken();
|
|
9503
9588
|
if (!token) {
|
|
9504
|
-
|
|
9589
|
+
this.client.logger('error', `Token not set, can't connect authenticate`);
|
|
9505
9590
|
return;
|
|
9506
9591
|
}
|
|
9507
9592
|
const authMessage = {
|
|
@@ -9734,7 +9819,7 @@ class StableWSConnection {
|
|
|
9734
9819
|
addConnectionEventListeners(this.onlineStatusChanged);
|
|
9735
9820
|
}
|
|
9736
9821
|
_log(msg, extra = {}, level = 'info') {
|
|
9737
|
-
this.client.logger(level, 'connection:' + msg, Object.assign({
|
|
9822
|
+
this.client.logger(level, 'connection:' + msg, Object.assign({}, extra));
|
|
9738
9823
|
}
|
|
9739
9824
|
/**
|
|
9740
9825
|
* connect - Connect to the WS URL
|
|
@@ -10451,7 +10536,7 @@ class WSConnectionFallback {
|
|
|
10451
10536
|
addConnectionEventListeners(this._onlineStatusChanged);
|
|
10452
10537
|
}
|
|
10453
10538
|
_log(msg, extra = {}, level = 'info') {
|
|
10454
|
-
this.client.logger(level, 'WSConnectionFallback:' + msg, Object.assign({
|
|
10539
|
+
this.client.logger(level, 'WSConnectionFallback:' + msg, Object.assign({}, extra));
|
|
10455
10540
|
}
|
|
10456
10541
|
_setState(state) {
|
|
10457
10542
|
this._log(`_setState() - ${state}`);
|
|
@@ -10511,7 +10596,7 @@ class StreamClient {
|
|
|
10511
10596
|
* If the user id remains the same we don't throw error
|
|
10512
10597
|
*/
|
|
10513
10598
|
if (this.userID === user.id && this.setUserPromise) {
|
|
10514
|
-
|
|
10599
|
+
this.logger('warn', 'Consecutive calls to connectUser is detected, ideally you should only call this function once in your app.');
|
|
10515
10600
|
return this.setUserPromise;
|
|
10516
10601
|
}
|
|
10517
10602
|
if (this.userID) {
|
|
@@ -10519,7 +10604,7 @@ class StreamClient {
|
|
|
10519
10604
|
}
|
|
10520
10605
|
if ((this._isUsingServerAuth() || this.node) &&
|
|
10521
10606
|
!this.options.allowServerSideConnect) {
|
|
10522
|
-
|
|
10607
|
+
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.');
|
|
10523
10608
|
}
|
|
10524
10609
|
// we generate the client id client side
|
|
10525
10610
|
this.userID = user.id;
|
|
@@ -10582,16 +10667,12 @@ class StreamClient {
|
|
|
10582
10667
|
throw Error('UserWithId is not set on client, use client.connectUser or client.connectAnonymousUser instead');
|
|
10583
10668
|
}
|
|
10584
10669
|
if (((_d = this.wsConnection) === null || _d === void 0 ? void 0 : _d.isConnecting) && this.wsPromise) {
|
|
10585
|
-
this.logger('info', 'client:openConnection() - connection already in progress'
|
|
10586
|
-
tags: ['connection', 'client'],
|
|
10587
|
-
});
|
|
10670
|
+
this.logger('info', 'client:openConnection() - connection already in progress');
|
|
10588
10671
|
return this.wsPromise;
|
|
10589
10672
|
}
|
|
10590
10673
|
if ((((_e = this.wsConnection) === null || _e === void 0 ? void 0 : _e.isHealthy) || ((_f = this.wsFallback) === null || _f === void 0 ? void 0 : _f.isHealthy())) &&
|
|
10591
10674
|
this._hasConnectionID()) {
|
|
10592
|
-
this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists'
|
|
10593
|
-
tags: ['connection', 'client'],
|
|
10594
|
-
});
|
|
10675
|
+
this.logger('info', 'client:openConnection() - openConnection called twice, healthy connection already exists');
|
|
10595
10676
|
return Promise.resolve();
|
|
10596
10677
|
}
|
|
10597
10678
|
this.clientID = `${this.userID}--${randomId()}`;
|
|
@@ -10614,9 +10695,7 @@ class StreamClient {
|
|
|
10614
10695
|
* https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
|
10615
10696
|
*/
|
|
10616
10697
|
this.disconnectUser = (timeout) => __awaiter(this, void 0, void 0, function* () {
|
|
10617
|
-
this.logger('info', 'client:disconnect() - Disconnecting the client'
|
|
10618
|
-
tags: ['connection', 'client'],
|
|
10619
|
-
});
|
|
10698
|
+
this.logger('info', 'client:disconnect() - Disconnecting the client');
|
|
10620
10699
|
// remove the user specific fields
|
|
10621
10700
|
delete this.user;
|
|
10622
10701
|
delete this._user;
|
|
@@ -10706,7 +10785,8 @@ class StreamClient {
|
|
|
10706
10785
|
this.dispatchEvent = (event) => {
|
|
10707
10786
|
if (!event.received_at)
|
|
10708
10787
|
event.received_at = new Date();
|
|
10709
|
-
|
|
10788
|
+
this.logger('info', `Dispatching event: ${event.type}`);
|
|
10789
|
+
this.logger('debug', 'Event payload:', event);
|
|
10710
10790
|
this._callClientListeners(event);
|
|
10711
10791
|
};
|
|
10712
10792
|
this.handleEvent = (messageEvent) => {
|
|
@@ -10839,9 +10919,7 @@ class StreamClient {
|
|
|
10839
10919
|
if (!(key in this.listeners)) {
|
|
10840
10920
|
this.listeners[key] = [];
|
|
10841
10921
|
}
|
|
10842
|
-
this.logger('info', `Attaching listener for ${key} event
|
|
10843
|
-
tags: ['event', 'client'],
|
|
10844
|
-
});
|
|
10922
|
+
this.logger('info', `Attaching listener for ${key} event`);
|
|
10845
10923
|
this.listeners[key].push(callback);
|
|
10846
10924
|
return () => {
|
|
10847
10925
|
this.off(key, callback);
|
|
@@ -10859,29 +10937,26 @@ class StreamClient {
|
|
|
10859
10937
|
if (!(key in this.listeners)) {
|
|
10860
10938
|
this.listeners[key] = [];
|
|
10861
10939
|
}
|
|
10862
|
-
this.logger('info', `Removing listener for ${key} event
|
|
10863
|
-
tags: ['event', 'client'],
|
|
10864
|
-
});
|
|
10940
|
+
this.logger('info', `Removing listener for ${key} event`);
|
|
10865
10941
|
this.listeners[key] = this.listeners[key].filter((value) => value !== callback);
|
|
10866
10942
|
}
|
|
10867
10943
|
_logApiRequest(type, url, data, config) {
|
|
10868
|
-
this.logger('info', `client: ${type} - Request - ${url}
|
|
10869
|
-
|
|
10870
|
-
url,
|
|
10944
|
+
this.logger('info', `client: ${type} - Request - ${url}`);
|
|
10945
|
+
this.logger('debug', `client: ${type} - Request payload`, {
|
|
10871
10946
|
payload: data,
|
|
10872
10947
|
config,
|
|
10873
10948
|
});
|
|
10874
10949
|
}
|
|
10875
10950
|
_logApiResponse(type, url, response) {
|
|
10876
10951
|
this.logger('info', `client:${type} - Response - url: ${url} > status ${response.status}`, {
|
|
10877
|
-
|
|
10878
|
-
|
|
10952
|
+
response,
|
|
10953
|
+
});
|
|
10954
|
+
this.logger('debug', `client:${type} - Response payload`, {
|
|
10879
10955
|
response,
|
|
10880
10956
|
});
|
|
10881
10957
|
}
|
|
10882
10958
|
_logApiError(type, url, error) {
|
|
10883
10959
|
this.logger('error', `client:${type} - Error - url: ${url}`, {
|
|
10884
|
-
tags: ['api', 'api_response', 'client'],
|
|
10885
10960
|
url,
|
|
10886
10961
|
error,
|
|
10887
10962
|
});
|
|
@@ -10956,7 +11031,7 @@ class StreamClient {
|
|
|
10956
11031
|
if (this.wsFallback) {
|
|
10957
11032
|
return yield this.wsFallback.connect();
|
|
10958
11033
|
}
|
|
10959
|
-
|
|
11034
|
+
this.logger('info', 'StreamClient.connect: this.wsConnection.connect()');
|
|
10960
11035
|
// if WSFallback is enabled, ws connect should timeout faster so fallback can try
|
|
10961
11036
|
return yield this.wsConnection.connect(this.options.enableWSFallback
|
|
10962
11037
|
? this.defaultWSTimeoutWithFallback
|
|
@@ -10965,9 +11040,11 @@ class StreamClient {
|
|
|
10965
11040
|
catch (err) {
|
|
10966
11041
|
// run fallback only if it's WS/Network error and not a normal API error
|
|
10967
11042
|
// make sure browser is online before even trying the longpoll
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
11043
|
+
if (this.options.enableWSFallback &&
|
|
11044
|
+
// @ts-ignore
|
|
11045
|
+
isWSFailure(err) &&
|
|
11046
|
+
isOnline(this.logger)) {
|
|
11047
|
+
this.logger('warn', 'client:connect() - WS failed, fallback to longpoll');
|
|
10971
11048
|
this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });
|
|
10972
11049
|
this.wsConnection._destroyCurrentWSConnection();
|
|
10973
11050
|
this.wsConnection.disconnect().then(); // close WS so no retry
|
|
@@ -11002,7 +11079,7 @@ class StreamClient {
|
|
|
11002
11079
|
}
|
|
11003
11080
|
getUserAgent() {
|
|
11004
11081
|
return (this.userAgent ||
|
|
11005
|
-
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.
|
|
11082
|
+
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${"0.0.14"}`);
|
|
11006
11083
|
}
|
|
11007
11084
|
setUserAgent(userAgent) {
|
|
11008
11085
|
this.userAgent = userAgent;
|
|
@@ -11071,7 +11148,10 @@ class StreamClient {
|
|
|
11071
11148
|
*/
|
|
11072
11149
|
class StreamVideoClient {
|
|
11073
11150
|
constructor(apiKeyOrArgs, opts) {
|
|
11151
|
+
var _a, _b;
|
|
11152
|
+
this.logLevel = 'warn';
|
|
11074
11153
|
this.eventHandlersToUnregister = [];
|
|
11154
|
+
this.logLevels = ['debug', 'info', 'warn', 'error'];
|
|
11075
11155
|
/**
|
|
11076
11156
|
* Disconnects the currently connected user from the client.
|
|
11077
11157
|
*
|
|
@@ -11230,11 +11310,30 @@ class StreamVideoClient {
|
|
|
11230
11310
|
this.connectionPromise.finally(() => (this.connectionPromise = undefined));
|
|
11231
11311
|
return this.connectionPromise;
|
|
11232
11312
|
});
|
|
11313
|
+
this.filterLogs = (logMethod) => {
|
|
11314
|
+
return (logLevel, messeage, extraData, tags) => {
|
|
11315
|
+
if (this.logLevels.indexOf(logLevel) >=
|
|
11316
|
+
this.logLevels.indexOf(this.logLevel)) {
|
|
11317
|
+
logMethod(logLevel, messeage, extraData, tags);
|
|
11318
|
+
}
|
|
11319
|
+
};
|
|
11320
|
+
};
|
|
11321
|
+
let defaultLogger = logToConsole;
|
|
11233
11322
|
if (typeof apiKeyOrArgs === 'string') {
|
|
11234
|
-
this.
|
|
11323
|
+
this.logLevel = (opts === null || opts === void 0 ? void 0 : opts.logLevel) || this.logLevel;
|
|
11324
|
+
this.logger = (opts === null || opts === void 0 ? void 0 : opts.logger) || defaultLogger;
|
|
11235
11325
|
}
|
|
11236
11326
|
else {
|
|
11237
|
-
this.
|
|
11327
|
+
this.logLevel = ((_a = apiKeyOrArgs.options) === null || _a === void 0 ? void 0 : _a.logLevel) || this.logLevel;
|
|
11328
|
+
this.logger = ((_b = apiKeyOrArgs.options) === null || _b === void 0 ? void 0 : _b.logger) || defaultLogger;
|
|
11329
|
+
}
|
|
11330
|
+
setLogger(this.filterLogs(defaultLogger));
|
|
11331
|
+
const clientLogger = getLogger(['client']);
|
|
11332
|
+
if (typeof apiKeyOrArgs === 'string') {
|
|
11333
|
+
this.streamClient = new StreamClient(apiKeyOrArgs, Object.assign(Object.assign({ persistUserOnConnectionFailure: true }, opts), { logLevel: this.logLevel, logger: clientLogger }));
|
|
11334
|
+
}
|
|
11335
|
+
else {
|
|
11336
|
+
this.streamClient = new StreamClient(apiKeyOrArgs.apiKey, Object.assign(Object.assign({ persistUserOnConnectionFailure: true }, apiKeyOrArgs.options), { logLevel: this.logLevel, logger: clientLogger }));
|
|
11238
11337
|
this.user = apiKeyOrArgs.user;
|
|
11239
11338
|
this.token = apiKeyOrArgs.token || apiKeyOrArgs.tokenProvider;
|
|
11240
11339
|
if (this.user) {
|
|
@@ -11296,7 +11395,7 @@ class StreamVideoClient {
|
|
|
11296
11395
|
},
|
|
11297
11396
|
sort: [{ field: 'cid', direction: 1 }],
|
|
11298
11397
|
}).catch((err) => {
|
|
11299
|
-
|
|
11398
|
+
this.logger('error', 'Failed to re-watch calls', err);
|
|
11300
11399
|
});
|
|
11301
11400
|
}
|
|
11302
11401
|
}
|
|
@@ -11306,7 +11405,7 @@ class StreamVideoClient {
|
|
|
11306
11405
|
return;
|
|
11307
11406
|
const { call, members } = event;
|
|
11308
11407
|
if (userToConnect.id === call.created_by.id) {
|
|
11309
|
-
|
|
11408
|
+
this.logger('warn', 'Received `call.created` sent by the current user');
|
|
11310
11409
|
return;
|
|
11311
11410
|
}
|
|
11312
11411
|
this.writeableStateStore.registerCall(new Call({
|
|
@@ -11323,7 +11422,7 @@ class StreamVideoClient {
|
|
|
11323
11422
|
return;
|
|
11324
11423
|
const { call, members } = event;
|
|
11325
11424
|
if (userToConnect.id === call.created_by.id) {
|
|
11326
|
-
|
|
11425
|
+
this.logger('warn', 'Received `call.ring` sent by the current user');
|
|
11327
11426
|
return;
|
|
11328
11427
|
}
|
|
11329
11428
|
// The call might already be tracked by the client,
|
|
@@ -11390,7 +11489,10 @@ const getDevices = (constraints) => {
|
|
|
11390
11489
|
});
|
|
11391
11490
|
})
|
|
11392
11491
|
.catch((error) => {
|
|
11393
|
-
|
|
11492
|
+
const logger = getLogger(['devices']);
|
|
11493
|
+
if (logger) {
|
|
11494
|
+
logger('error', 'Failed to get devices', error);
|
|
11495
|
+
}
|
|
11394
11496
|
subscriber.error(error);
|
|
11395
11497
|
});
|
|
11396
11498
|
});
|
|
@@ -11461,11 +11563,15 @@ const getAudioOutputDevices = () => {
|
|
|
11461
11563
|
return audioDevices$.pipe(map$2((values) => values.filter((d) => d.kind === 'audiooutput')));
|
|
11462
11564
|
};
|
|
11463
11565
|
const getStream = (constraints) => __awaiter(void 0, void 0, void 0, function* () {
|
|
11566
|
+
var _a;
|
|
11464
11567
|
try {
|
|
11465
11568
|
return yield navigator.mediaDevices.getUserMedia(constraints);
|
|
11466
11569
|
}
|
|
11467
11570
|
catch (e) {
|
|
11468
|
-
|
|
11571
|
+
(_a = getLogger(['devices'])) === null || _a === void 0 ? void 0 : _a('error', `Failed get user media`, {
|
|
11572
|
+
error: e,
|
|
11573
|
+
constraints: constraints,
|
|
11574
|
+
});
|
|
11469
11575
|
throw e;
|
|
11470
11576
|
}
|
|
11471
11577
|
});
|
|
@@ -11508,11 +11614,12 @@ const getVideoStream = (trackConstraints) => __awaiter(void 0, void 0, void 0, f
|
|
|
11508
11614
|
* @param options any additional options to pass to the [`getDisplayMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia) API.
|
|
11509
11615
|
*/
|
|
11510
11616
|
const getScreenShareStream = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
11617
|
+
var _b;
|
|
11511
11618
|
try {
|
|
11512
11619
|
return yield navigator.mediaDevices.getDisplayMedia(Object.assign({ video: true, audio: false }, options));
|
|
11513
11620
|
}
|
|
11514
11621
|
catch (e) {
|
|
11515
|
-
|
|
11622
|
+
(_b = getLogger(['devices'])) === null || _b === void 0 ? void 0 : _b('error', 'Failed to get screen share stream', e);
|
|
11516
11623
|
throw e;
|
|
11517
11624
|
}
|
|
11518
11625
|
});
|
|
@@ -11695,5 +11802,5 @@ var browsers = /*#__PURE__*/Object.freeze({
|
|
|
11695
11802
|
isSafari: isSafari
|
|
11696
11803
|
});
|
|
11697
11804
|
|
|
11698
|
-
export { APIErrorCodeEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CreateDeviceRequestPushProviderEnum, DebounceType, ErrorFromResponse, OwnCapability, RecordSettingsModeEnum, RecordSettingsQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, events as SfuEvents, models as SfuModels, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsModeEnum, TranscriptionSettingsRequestModeEnum, VideoSettingsCameraFacingEnum, VideoSettingsRequestCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, disposeOfMediaStream, dominantSpeaker, getAudioDevices, getAudioOutputDevices, getAudioStream, getScreenShareStream, getSdkInfo, getVideoDevices, getVideoStream, isStreamVideoLocalParticipant, livestreamOrAudioRoomSortPreset, name, noopComparator, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setSdkInfo, speakerLayoutSortPreset, speaking, watchForAddedDefaultAudioDevice, watchForAddedDefaultAudioOutputDevice, watchForAddedDefaultVideoDevice, watchForDisconnectedAudioDevice, watchForDisconnectedAudioOutputDevice, watchForDisconnectedVideoDevice };
|
|
11805
|
+
export { APIErrorCodeEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CreateDeviceRequestPushProviderEnum, DebounceType, ErrorFromResponse, OwnCapability, RecordSettingsModeEnum, RecordSettingsQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, events as SfuEvents, models as SfuModels, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoWriteableStateStore, TranscriptionSettingsModeEnum, TranscriptionSettingsRequestModeEnum, VideoSettingsCameraFacingEnum, VideoSettingsRequestCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, disposeOfMediaStream, dominantSpeaker, getAudioDevices, getAudioOutputDevices, getAudioStream, getLogger, getScreenShareStream, getSdkInfo, getVideoDevices, getVideoStream, isStreamVideoLocalParticipant, livestreamOrAudioRoomSortPreset, logToConsole, name, noopComparator, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setLogger, setSdkInfo, speakerLayoutSortPreset, speaking, watchForAddedDefaultAudioDevice, watchForAddedDefaultAudioOutputDevice, watchForAddedDefaultVideoDevice, watchForDisconnectedAudioDevice, watchForDisconnectedAudioOutputDevice, watchForDisconnectedVideoDevice };
|
|
11699
11806
|
//# sourceMappingURL=index.browser.es.js.map
|