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