@stream-io/video-client 0.1.3 → 0.1.5
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 +19 -0
- package/dist/index.browser.es.js +401 -106
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +400 -105
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +401 -106
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +1 -1
- package/dist/src/StreamSfuClient.d.ts +2 -1
- package/dist/src/StreamVideoClient.d.ts +3 -4
- package/dist/src/coordinator/connection/client.d.ts +0 -6
- package/dist/src/gen/video/sfu/event/events.d.ts +45 -2
- package/dist/src/gen/video/sfu/models/models.d.ts +12 -0
- package/dist/src/gen/video/sfu/signal_rpc/signal.client.d.ts +9 -1
- package/dist/src/gen/video/sfu/signal_rpc/signal.d.ts +42 -0
- package/dist/src/rtc/Publisher.d.ts +10 -2
- package/dist/src/rtc/Subscriber.d.ts +8 -3
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/Call.ts +18 -9
- package/src/StreamSfuClient.ts +16 -5
- package/src/StreamVideoClient.ts +32 -30
- package/src/coordinator/connection/client.ts +0 -25
- package/src/gen/google/protobuf/struct.ts +1 -2
- package/src/gen/google/protobuf/timestamp.ts +1 -1
- package/src/gen/video/sfu/event/events.ts +165 -5
- package/src/gen/video/sfu/models/models.ts +13 -1
- package/src/gen/video/sfu/signal_rpc/signal.client.ts +27 -1
- package/src/gen/video/sfu/signal_rpc/signal.ts +194 -1
- package/src/rtc/Dispatcher.ts +1 -0
- package/src/rtc/Publisher.ts +69 -34
- package/src/rtc/Subscriber.ts +74 -7
- package/src/rtc/__tests__/Publisher.test.ts +82 -2
- package/src/rtc/__tests__/Subscriber.test.ts +84 -1
package/dist/index.es.js
CHANGED
|
@@ -4,7 +4,7 @@ import { ServiceType, stackIntercept } from '@protobuf-ts/runtime-rpc';
|
|
|
4
4
|
import axios, { AxiosHeaders } from 'axios';
|
|
5
5
|
export { AxiosError } from 'axios';
|
|
6
6
|
import { TwirpFetchTransport } from '@protobuf-ts/twirp-transport';
|
|
7
|
-
import { ReplaySubject, BehaviorSubject, takeWhile, pairwise, tap, debounce, timer, map as map$2, Observable, debounceTime, concatMap, from, shareReplay, merge, combineLatest
|
|
7
|
+
import { ReplaySubject, BehaviorSubject, takeWhile, filter, pairwise, tap, debounce, timer, map as map$2, Observable, debounceTime, concatMap, from, shareReplay, merge, combineLatest } from 'rxjs';
|
|
8
8
|
import * as SDP from 'sdp-transform';
|
|
9
9
|
import WebSocket from 'isomorphic-ws';
|
|
10
10
|
import { take, map as map$1, distinctUntilChanged } from 'rxjs/operators';
|
|
@@ -372,7 +372,6 @@ class Value$Type extends MessageType {
|
|
|
372
372
|
};
|
|
373
373
|
}
|
|
374
374
|
else {
|
|
375
|
-
Struct.fromJson(json);
|
|
376
375
|
target.kind = {
|
|
377
376
|
oneofKind: 'structValue',
|
|
378
377
|
structValue: Struct.fromJson(json),
|
|
@@ -828,6 +827,18 @@ var ErrorCode;
|
|
|
828
827
|
* @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_MIGRATION_FAILED = 202;
|
|
829
828
|
*/
|
|
830
829
|
ErrorCode[ErrorCode["PARTICIPANT_MIGRATION_FAILED"] = 202] = "PARTICIPANT_MIGRATION_FAILED";
|
|
830
|
+
/**
|
|
831
|
+
* @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_MIGRATING = 203;
|
|
832
|
+
*/
|
|
833
|
+
ErrorCode[ErrorCode["PARTICIPANT_MIGRATING"] = 203] = "PARTICIPANT_MIGRATING";
|
|
834
|
+
/**
|
|
835
|
+
* @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_RECONNECT_FAILED = 204;
|
|
836
|
+
*/
|
|
837
|
+
ErrorCode[ErrorCode["PARTICIPANT_RECONNECT_FAILED"] = 204] = "PARTICIPANT_RECONNECT_FAILED";
|
|
838
|
+
/**
|
|
839
|
+
* @generated from protobuf enum value: ERROR_CODE_PARTICIPANT_MEDIA_TRANSPORT_FAILURE = 205;
|
|
840
|
+
*/
|
|
841
|
+
ErrorCode[ErrorCode["PARTICIPANT_MEDIA_TRANSPORT_FAILURE"] = 205] = "PARTICIPANT_MEDIA_TRANSPORT_FAILURE";
|
|
831
842
|
/**
|
|
832
843
|
* @generated from protobuf enum value: ERROR_CODE_CALL_NOT_FOUND = 300;
|
|
833
844
|
*/
|
|
@@ -2404,10 +2415,122 @@ var models = /*#__PURE__*/Object.freeze({
|
|
|
2404
2415
|
});
|
|
2405
2416
|
|
|
2406
2417
|
/* eslint-disable */
|
|
2407
|
-
// @generated by protobuf-ts 2.
|
|
2418
|
+
// @generated by protobuf-ts 2.9.0 with parameter long_type_string,client_generic,server_none,eslint_disable
|
|
2408
2419
|
// @generated from protobuf file "video/sfu/signal_rpc/signal.proto" (package "stream.video.sfu.signal", syntax proto3)
|
|
2409
2420
|
// tslint:disable
|
|
2410
2421
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
2422
|
+
class ICERestartRequest$Type extends MessageType {
|
|
2423
|
+
constructor() {
|
|
2424
|
+
super('stream.video.sfu.signal.ICERestartRequest', [
|
|
2425
|
+
{ no: 1, name: 'session_id', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
|
|
2426
|
+
{
|
|
2427
|
+
no: 2,
|
|
2428
|
+
name: 'peer_type',
|
|
2429
|
+
kind: 'enum',
|
|
2430
|
+
T: () => ['stream.video.sfu.models.PeerType', PeerType, 'PEER_TYPE_'],
|
|
2431
|
+
},
|
|
2432
|
+
]);
|
|
2433
|
+
}
|
|
2434
|
+
create(value) {
|
|
2435
|
+
const message = { sessionId: '', peerType: 0 };
|
|
2436
|
+
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
2437
|
+
enumerable: false,
|
|
2438
|
+
value: this,
|
|
2439
|
+
});
|
|
2440
|
+
if (value !== undefined)
|
|
2441
|
+
reflectionMergePartial(this, message, value);
|
|
2442
|
+
return message;
|
|
2443
|
+
}
|
|
2444
|
+
internalBinaryRead(reader, length, options, target) {
|
|
2445
|
+
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
|
2446
|
+
while (reader.pos < end) {
|
|
2447
|
+
let [fieldNo, wireType] = reader.tag();
|
|
2448
|
+
switch (fieldNo) {
|
|
2449
|
+
case /* string session_id */ 1:
|
|
2450
|
+
message.sessionId = reader.string();
|
|
2451
|
+
break;
|
|
2452
|
+
case /* stream.video.sfu.models.PeerType peer_type */ 2:
|
|
2453
|
+
message.peerType = reader.int32();
|
|
2454
|
+
break;
|
|
2455
|
+
default:
|
|
2456
|
+
let u = options.readUnknownField;
|
|
2457
|
+
if (u === 'throw')
|
|
2458
|
+
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
2459
|
+
let d = reader.skip(wireType);
|
|
2460
|
+
if (u !== false)
|
|
2461
|
+
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
return message;
|
|
2465
|
+
}
|
|
2466
|
+
internalBinaryWrite(message, writer, options) {
|
|
2467
|
+
/* string session_id = 1; */
|
|
2468
|
+
if (message.sessionId !== '')
|
|
2469
|
+
writer.tag(1, WireType.LengthDelimited).string(message.sessionId);
|
|
2470
|
+
/* stream.video.sfu.models.PeerType peer_type = 2; */
|
|
2471
|
+
if (message.peerType !== 0)
|
|
2472
|
+
writer.tag(2, WireType.Varint).int32(message.peerType);
|
|
2473
|
+
let u = options.writeUnknownFields;
|
|
2474
|
+
if (u !== false)
|
|
2475
|
+
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
2476
|
+
return writer;
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
/**
|
|
2480
|
+
* @generated MessageType for protobuf message stream.video.sfu.signal.ICERestartRequest
|
|
2481
|
+
*/
|
|
2482
|
+
const ICERestartRequest = new ICERestartRequest$Type();
|
|
2483
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
2484
|
+
class ICERestartResponse$Type extends MessageType {
|
|
2485
|
+
constructor() {
|
|
2486
|
+
super('stream.video.sfu.signal.ICERestartResponse', [
|
|
2487
|
+
{ no: 1, name: 'error', kind: 'message', T: () => Error$2 },
|
|
2488
|
+
]);
|
|
2489
|
+
}
|
|
2490
|
+
create(value) {
|
|
2491
|
+
const message = {};
|
|
2492
|
+
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
2493
|
+
enumerable: false,
|
|
2494
|
+
value: this,
|
|
2495
|
+
});
|
|
2496
|
+
if (value !== undefined)
|
|
2497
|
+
reflectionMergePartial(this, message, value);
|
|
2498
|
+
return message;
|
|
2499
|
+
}
|
|
2500
|
+
internalBinaryRead(reader, length, options, target) {
|
|
2501
|
+
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
|
2502
|
+
while (reader.pos < end) {
|
|
2503
|
+
let [fieldNo, wireType] = reader.tag();
|
|
2504
|
+
switch (fieldNo) {
|
|
2505
|
+
case /* stream.video.sfu.models.Error error */ 1:
|
|
2506
|
+
message.error = Error$2.internalBinaryRead(reader, reader.uint32(), options, message.error);
|
|
2507
|
+
break;
|
|
2508
|
+
default:
|
|
2509
|
+
let u = options.readUnknownField;
|
|
2510
|
+
if (u === 'throw')
|
|
2511
|
+
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
2512
|
+
let d = reader.skip(wireType);
|
|
2513
|
+
if (u !== false)
|
|
2514
|
+
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
2515
|
+
}
|
|
2516
|
+
}
|
|
2517
|
+
return message;
|
|
2518
|
+
}
|
|
2519
|
+
internalBinaryWrite(message, writer, options) {
|
|
2520
|
+
/* stream.video.sfu.models.Error error = 1; */
|
|
2521
|
+
if (message.error)
|
|
2522
|
+
Error$2.internalBinaryWrite(message.error, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
|
2523
|
+
let u = options.writeUnknownFields;
|
|
2524
|
+
if (u !== false)
|
|
2525
|
+
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
2526
|
+
return writer;
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
/**
|
|
2530
|
+
* @generated MessageType for protobuf message stream.video.sfu.signal.ICERestartResponse
|
|
2531
|
+
*/
|
|
2532
|
+
const ICERestartResponse = new ICERestartResponse$Type();
|
|
2533
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
2411
2534
|
class UpdateMuteStatesRequest$Type extends MessageType {
|
|
2412
2535
|
constructor() {
|
|
2413
2536
|
super('stream.video.sfu.signal.UpdateMuteStatesRequest', [
|
|
@@ -3218,6 +3341,12 @@ const SignalServer = new ServiceType('stream.video.sfu.signal.SignalServer', [
|
|
|
3218
3341
|
I: UpdateMuteStatesRequest,
|
|
3219
3342
|
O: UpdateMuteStatesResponse,
|
|
3220
3343
|
},
|
|
3344
|
+
{
|
|
3345
|
+
name: 'IceRestart',
|
|
3346
|
+
options: {},
|
|
3347
|
+
I: ICERestartRequest,
|
|
3348
|
+
O: ICERestartResponse,
|
|
3349
|
+
},
|
|
3221
3350
|
]);
|
|
3222
3351
|
|
|
3223
3352
|
/**
|
|
@@ -3358,6 +3487,13 @@ class SfuEvent$Type extends MessageType {
|
|
|
3358
3487
|
oneof: 'eventPayload',
|
|
3359
3488
|
T: () => GoAway,
|
|
3360
3489
|
},
|
|
3490
|
+
{
|
|
3491
|
+
no: 21,
|
|
3492
|
+
name: 'ice_restart',
|
|
3493
|
+
kind: 'message',
|
|
3494
|
+
oneof: 'eventPayload',
|
|
3495
|
+
T: () => ICERestart,
|
|
3496
|
+
},
|
|
3361
3497
|
]);
|
|
3362
3498
|
}
|
|
3363
3499
|
create(value) {
|
|
@@ -3471,6 +3607,12 @@ class SfuEvent$Type extends MessageType {
|
|
|
3471
3607
|
goAway: GoAway.internalBinaryRead(reader, reader.uint32(), options, message.eventPayload.goAway),
|
|
3472
3608
|
};
|
|
3473
3609
|
break;
|
|
3610
|
+
case /* stream.video.sfu.event.ICERestart ice_restart */ 21:
|
|
3611
|
+
message.eventPayload = {
|
|
3612
|
+
oneofKind: 'iceRestart',
|
|
3613
|
+
iceRestart: ICERestart.internalBinaryRead(reader, reader.uint32(), options, message.eventPayload.iceRestart),
|
|
3614
|
+
};
|
|
3615
|
+
break;
|
|
3474
3616
|
default:
|
|
3475
3617
|
let u = options.readUnknownField;
|
|
3476
3618
|
if (u === 'throw')
|
|
@@ -3531,6 +3673,9 @@ class SfuEvent$Type extends MessageType {
|
|
|
3531
3673
|
/* stream.video.sfu.event.GoAway go_away = 20; */
|
|
3532
3674
|
if (message.eventPayload.oneofKind === 'goAway')
|
|
3533
3675
|
GoAway.internalBinaryWrite(message.eventPayload.goAway, writer.tag(20, WireType.LengthDelimited).fork(), options).join();
|
|
3676
|
+
/* stream.video.sfu.event.ICERestart ice_restart = 21; */
|
|
3677
|
+
if (message.eventPayload.oneofKind === 'iceRestart')
|
|
3678
|
+
ICERestart.internalBinaryWrite(message.eventPayload.iceRestart, writer.tag(21, WireType.LengthDelimited).fork(), options).join();
|
|
3534
3679
|
let u = options.writeUnknownFields;
|
|
3535
3680
|
if (u !== false)
|
|
3536
3681
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
@@ -3659,6 +3804,61 @@ class ICETrickle$Type extends MessageType {
|
|
|
3659
3804
|
*/
|
|
3660
3805
|
const ICETrickle = new ICETrickle$Type();
|
|
3661
3806
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
3807
|
+
class ICERestart$Type extends MessageType {
|
|
3808
|
+
constructor() {
|
|
3809
|
+
super('stream.video.sfu.event.ICERestart', [
|
|
3810
|
+
{
|
|
3811
|
+
no: 1,
|
|
3812
|
+
name: 'peer_type',
|
|
3813
|
+
kind: 'enum',
|
|
3814
|
+
T: () => ['stream.video.sfu.models.PeerType', PeerType, 'PEER_TYPE_'],
|
|
3815
|
+
},
|
|
3816
|
+
]);
|
|
3817
|
+
}
|
|
3818
|
+
create(value) {
|
|
3819
|
+
const message = { peerType: 0 };
|
|
3820
|
+
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
3821
|
+
enumerable: false,
|
|
3822
|
+
value: this,
|
|
3823
|
+
});
|
|
3824
|
+
if (value !== undefined)
|
|
3825
|
+
reflectionMergePartial(this, message, value);
|
|
3826
|
+
return message;
|
|
3827
|
+
}
|
|
3828
|
+
internalBinaryRead(reader, length, options, target) {
|
|
3829
|
+
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
|
3830
|
+
while (reader.pos < end) {
|
|
3831
|
+
let [fieldNo, wireType] = reader.tag();
|
|
3832
|
+
switch (fieldNo) {
|
|
3833
|
+
case /* stream.video.sfu.models.PeerType peer_type */ 1:
|
|
3834
|
+
message.peerType = reader.int32();
|
|
3835
|
+
break;
|
|
3836
|
+
default:
|
|
3837
|
+
let u = options.readUnknownField;
|
|
3838
|
+
if (u === 'throw')
|
|
3839
|
+
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
3840
|
+
let d = reader.skip(wireType);
|
|
3841
|
+
if (u !== false)
|
|
3842
|
+
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3845
|
+
return message;
|
|
3846
|
+
}
|
|
3847
|
+
internalBinaryWrite(message, writer, options) {
|
|
3848
|
+
/* stream.video.sfu.models.PeerType peer_type = 1; */
|
|
3849
|
+
if (message.peerType !== 0)
|
|
3850
|
+
writer.tag(1, WireType.Varint).int32(message.peerType);
|
|
3851
|
+
let u = options.writeUnknownFields;
|
|
3852
|
+
if (u !== false)
|
|
3853
|
+
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
3854
|
+
return writer;
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3857
|
+
/**
|
|
3858
|
+
* @generated MessageType for protobuf message stream.video.sfu.event.ICERestart
|
|
3859
|
+
*/
|
|
3860
|
+
const ICERestart = new ICERestart$Type();
|
|
3861
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
3662
3862
|
class SfuRequest$Type extends MessageType {
|
|
3663
3863
|
constructor() {
|
|
3664
3864
|
super('stream.video.sfu.event.SfuRequest', [
|
|
@@ -4012,10 +4212,21 @@ class JoinRequest$Type extends MessageType {
|
|
|
4012
4212
|
T: () => ClientDetails,
|
|
4013
4213
|
},
|
|
4014
4214
|
{ no: 5, name: 'migration', kind: 'message', T: () => Migration },
|
|
4215
|
+
{
|
|
4216
|
+
no: 6,
|
|
4217
|
+
name: 'fast_reconnect',
|
|
4218
|
+
kind: 'scalar',
|
|
4219
|
+
T: 8 /*ScalarType.BOOL*/,
|
|
4220
|
+
},
|
|
4015
4221
|
]);
|
|
4016
4222
|
}
|
|
4017
4223
|
create(value) {
|
|
4018
|
-
const message = {
|
|
4224
|
+
const message = {
|
|
4225
|
+
token: '',
|
|
4226
|
+
sessionId: '',
|
|
4227
|
+
subscriberSdp: '',
|
|
4228
|
+
fastReconnect: false,
|
|
4229
|
+
};
|
|
4019
4230
|
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
4020
4231
|
enumerable: false,
|
|
4021
4232
|
value: this,
|
|
@@ -4044,6 +4255,9 @@ class JoinRequest$Type extends MessageType {
|
|
|
4044
4255
|
case /* stream.video.sfu.event.Migration migration */ 5:
|
|
4045
4256
|
message.migration = Migration.internalBinaryRead(reader, reader.uint32(), options, message.migration);
|
|
4046
4257
|
break;
|
|
4258
|
+
case /* bool fast_reconnect */ 6:
|
|
4259
|
+
message.fastReconnect = reader.bool();
|
|
4260
|
+
break;
|
|
4047
4261
|
default:
|
|
4048
4262
|
let u = options.readUnknownField;
|
|
4049
4263
|
if (u === 'throw')
|
|
@@ -4071,6 +4285,9 @@ class JoinRequest$Type extends MessageType {
|
|
|
4071
4285
|
/* stream.video.sfu.event.Migration migration = 5; */
|
|
4072
4286
|
if (message.migration)
|
|
4073
4287
|
Migration.internalBinaryWrite(message.migration, writer.tag(5, WireType.LengthDelimited).fork(), options).join();
|
|
4288
|
+
/* bool fast_reconnect = 6; */
|
|
4289
|
+
if (message.fastReconnect !== false)
|
|
4290
|
+
writer.tag(6, WireType.Varint).bool(message.fastReconnect);
|
|
4074
4291
|
let u = options.writeUnknownFields;
|
|
4075
4292
|
if (u !== false)
|
|
4076
4293
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
@@ -4167,10 +4384,11 @@ class JoinResponse$Type extends MessageType {
|
|
|
4167
4384
|
constructor() {
|
|
4168
4385
|
super('stream.video.sfu.event.JoinResponse', [
|
|
4169
4386
|
{ no: 1, name: 'call_state', kind: 'message', T: () => CallState$1 },
|
|
4387
|
+
{ no: 2, name: 'reconnected', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },
|
|
4170
4388
|
]);
|
|
4171
4389
|
}
|
|
4172
4390
|
create(value) {
|
|
4173
|
-
const message = {};
|
|
4391
|
+
const message = { reconnected: false };
|
|
4174
4392
|
globalThis.Object.defineProperty(message, MESSAGE_TYPE, {
|
|
4175
4393
|
enumerable: false,
|
|
4176
4394
|
value: this,
|
|
@@ -4187,6 +4405,9 @@ class JoinResponse$Type extends MessageType {
|
|
|
4187
4405
|
case /* stream.video.sfu.models.CallState call_state */ 1:
|
|
4188
4406
|
message.callState = CallState$1.internalBinaryRead(reader, reader.uint32(), options, message.callState);
|
|
4189
4407
|
break;
|
|
4408
|
+
case /* bool reconnected */ 2:
|
|
4409
|
+
message.reconnected = reader.bool();
|
|
4410
|
+
break;
|
|
4190
4411
|
default:
|
|
4191
4412
|
let u = options.readUnknownField;
|
|
4192
4413
|
if (u === 'throw')
|
|
@@ -4202,6 +4423,9 @@ class JoinResponse$Type extends MessageType {
|
|
|
4202
4423
|
/* stream.video.sfu.models.CallState call_state = 1; */
|
|
4203
4424
|
if (message.callState)
|
|
4204
4425
|
CallState$1.internalBinaryWrite(message.callState, writer.tag(1, WireType.LengthDelimited).fork(), options).join();
|
|
4426
|
+
/* bool reconnected = 2; */
|
|
4427
|
+
if (message.reconnected !== false)
|
|
4428
|
+
writer.tag(2, WireType.Varint).bool(message.reconnected);
|
|
4205
4429
|
let u = options.writeUnknownFields;
|
|
4206
4430
|
if (u !== false)
|
|
4207
4431
|
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
@@ -5318,6 +5542,7 @@ var events = /*#__PURE__*/Object.freeze({
|
|
|
5318
5542
|
GoAway: GoAway,
|
|
5319
5543
|
HealthCheckRequest: HealthCheckRequest,
|
|
5320
5544
|
HealthCheckResponse: HealthCheckResponse,
|
|
5545
|
+
ICERestart: ICERestart,
|
|
5321
5546
|
ICETrickle: ICETrickle,
|
|
5322
5547
|
JoinRequest: JoinRequest,
|
|
5323
5548
|
JoinResponse: JoinResponse,
|
|
@@ -5434,6 +5659,13 @@ class SignalServerClient {
|
|
|
5434
5659
|
const method = this.methods[4], opt = this._transport.mergeOptions(options);
|
|
5435
5660
|
return stackIntercept('unary', this._transport, method, opt, input);
|
|
5436
5661
|
}
|
|
5662
|
+
/**
|
|
5663
|
+
* @generated from protobuf rpc: IceRestart(stream.video.sfu.signal.ICERestartRequest) returns (stream.video.sfu.signal.ICERestartResponse);
|
|
5664
|
+
*/
|
|
5665
|
+
iceRestart(input, options) {
|
|
5666
|
+
const method = this.methods[5], opt = this._transport.mergeOptions(options);
|
|
5667
|
+
return stackIntercept('unary', this._transport, method, opt, input);
|
|
5668
|
+
}
|
|
5437
5669
|
}
|
|
5438
5670
|
|
|
5439
5671
|
const defaultOptions = {
|
|
@@ -5668,7 +5900,7 @@ const logLevels = Object.freeze({
|
|
|
5668
5900
|
warn: 3,
|
|
5669
5901
|
error: 4,
|
|
5670
5902
|
});
|
|
5671
|
-
let logger$
|
|
5903
|
+
let logger$4;
|
|
5672
5904
|
let level = 'info';
|
|
5673
5905
|
const logToConsole = (logLevel, message, ...args) => {
|
|
5674
5906
|
let logMethod;
|
|
@@ -5692,7 +5924,7 @@ const logToConsole = (logLevel, message, ...args) => {
|
|
|
5692
5924
|
logMethod(message, ...args);
|
|
5693
5925
|
};
|
|
5694
5926
|
const setLogger = (l, lvl) => {
|
|
5695
|
-
logger$
|
|
5927
|
+
logger$4 = l;
|
|
5696
5928
|
if (lvl) {
|
|
5697
5929
|
setLogLevel(lvl);
|
|
5698
5930
|
}
|
|
@@ -5701,7 +5933,7 @@ const setLogLevel = (l) => {
|
|
|
5701
5933
|
level = l;
|
|
5702
5934
|
};
|
|
5703
5935
|
const getLogger = (withTags) => {
|
|
5704
|
-
const loggerMethod = logger$
|
|
5936
|
+
const loggerMethod = logger$4 || logToConsole;
|
|
5705
5937
|
const tags = (withTags || []).join(':');
|
|
5706
5938
|
const result = (logLevel, message, ...args) => {
|
|
5707
5939
|
if (logLevels[logLevel] >= logLevels[level]) {
|
|
@@ -5808,6 +6040,7 @@ const sfuEventKinds = {
|
|
|
5808
6040
|
error: undefined,
|
|
5809
6041
|
callGrantsUpdated: undefined,
|
|
5810
6042
|
goAway: undefined,
|
|
6043
|
+
iceRestart: undefined,
|
|
5811
6044
|
};
|
|
5812
6045
|
const isSfuEvent = (eventName) => {
|
|
5813
6046
|
return Object.prototype.hasOwnProperty.call(sfuEventKinds, eventName);
|
|
@@ -6033,6 +6266,7 @@ const muteTypeToTrackType = (muteType) => {
|
|
|
6033
6266
|
}
|
|
6034
6267
|
};
|
|
6035
6268
|
|
|
6269
|
+
const logger$3 = getLogger(['Publisher']);
|
|
6036
6270
|
/**
|
|
6037
6271
|
* The `Publisher` is responsible for publishing/unpublishing media streams to/from the SFU
|
|
6038
6272
|
* @internal
|
|
@@ -6044,11 +6278,13 @@ class Publisher {
|
|
|
6044
6278
|
* @param connectionConfig the connection configuration to use.
|
|
6045
6279
|
* @param sfuClient the SFU client to use.
|
|
6046
6280
|
* @param state the call state to use.
|
|
6281
|
+
* @param dispatcher the dispatcher to use.
|
|
6047
6282
|
* @param isDtxEnabled whether DTX is enabled.
|
|
6048
6283
|
* @param isRedEnabled whether RED is enabled.
|
|
6049
6284
|
* @param preferredVideoCodec the preferred video codec.
|
|
6285
|
+
* @param iceRestartDelay the delay in milliseconds to wait before restarting ICE once connection goes to `disconnected` state.
|
|
6050
6286
|
*/
|
|
6051
|
-
constructor({ connectionConfig, sfuClient, state, isDtxEnabled, isRedEnabled, preferredVideoCodec, }) {
|
|
6287
|
+
constructor({ connectionConfig, sfuClient, dispatcher, state, isDtxEnabled, isRedEnabled, preferredVideoCodec, iceRestartDelay = 2500, }) {
|
|
6052
6288
|
this.transceiverRegistry = {
|
|
6053
6289
|
[TrackType.AUDIO]: undefined,
|
|
6054
6290
|
[TrackType.VIDEO]: undefined,
|
|
@@ -6078,7 +6314,7 @@ class Publisher {
|
|
|
6078
6314
|
[TrackType.SCREEN_SHARE_AUDIO]: undefined,
|
|
6079
6315
|
[TrackType.UNSPECIFIED]: undefined,
|
|
6080
6316
|
};
|
|
6081
|
-
this.
|
|
6317
|
+
this.isIceRestarting = false;
|
|
6082
6318
|
this.createPeerConnection = (connectionConfig) => {
|
|
6083
6319
|
const pc = new RTCPeerConnection(connectionConfig);
|
|
6084
6320
|
pc.addEventListener('icecandidate', this.onIceCandidate);
|
|
@@ -6104,6 +6340,7 @@ class Publisher {
|
|
|
6104
6340
|
this.trackLayersCache[trackType] = undefined;
|
|
6105
6341
|
});
|
|
6106
6342
|
}
|
|
6343
|
+
this.unsubscribeOnIceRestart();
|
|
6107
6344
|
this.pc.removeEventListener('negotiationneeded', this.onNegotiationNeeded);
|
|
6108
6345
|
this.pc.close();
|
|
6109
6346
|
};
|
|
@@ -6134,7 +6371,7 @@ class Publisher {
|
|
|
6134
6371
|
* Once the track has ended, it will notify the SFU and update the state.
|
|
6135
6372
|
*/
|
|
6136
6373
|
const handleTrackEnded = () => __awaiter(this, void 0, void 0, function* () {
|
|
6137
|
-
|
|
6374
|
+
logger$3('info', `Track ${TrackType[trackType]} has ended, notifying the SFU`);
|
|
6138
6375
|
yield this.notifyTrackMuteStateChanged(mediaStream, track, trackType, true);
|
|
6139
6376
|
// clean-up, this event listener needs to run only once.
|
|
6140
6377
|
track.removeEventListener('ended', handleTrackEnded);
|
|
@@ -6157,11 +6394,11 @@ class Publisher {
|
|
|
6157
6394
|
: undefined,
|
|
6158
6395
|
sendEncodings: videoEncodings,
|
|
6159
6396
|
});
|
|
6160
|
-
|
|
6397
|
+
logger$3('debug', `Added ${TrackType[trackType]} transceiver`);
|
|
6161
6398
|
this.transceiverInitOrder.push(trackType);
|
|
6162
6399
|
this.transceiverRegistry[trackType] = transceiver;
|
|
6163
6400
|
if ('setCodecPreferences' in transceiver && codecPreferences) {
|
|
6164
|
-
|
|
6401
|
+
logger$3('info', `Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
|
|
6165
6402
|
transceiver.setCodecPreferences(codecPreferences);
|
|
6166
6403
|
}
|
|
6167
6404
|
}
|
|
@@ -6229,7 +6466,7 @@ class Publisher {
|
|
|
6229
6466
|
* Stops publishing all tracks and stop all tracks.
|
|
6230
6467
|
*/
|
|
6231
6468
|
this.stopPublishing = () => {
|
|
6232
|
-
|
|
6469
|
+
logger$3('debug', 'Stopping publishing all tracks');
|
|
6233
6470
|
this.pc.getSenders().forEach((s) => {
|
|
6234
6471
|
var _a;
|
|
6235
6472
|
(_a = s.track) === null || _a === void 0 ? void 0 : _a.stop();
|
|
@@ -6240,15 +6477,15 @@ class Publisher {
|
|
|
6240
6477
|
};
|
|
6241
6478
|
this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
|
|
6242
6479
|
var _a;
|
|
6243
|
-
|
|
6480
|
+
logger$3('info', 'Update publish quality, requested rids by SFU:', enabledRids);
|
|
6244
6481
|
const videoSender = (_a = this.transceiverRegistry[TrackType.VIDEO]) === null || _a === void 0 ? void 0 : _a.sender;
|
|
6245
6482
|
if (!videoSender) {
|
|
6246
|
-
|
|
6483
|
+
logger$3('warn', 'Update publish quality, no video sender found.');
|
|
6247
6484
|
return;
|
|
6248
6485
|
}
|
|
6249
6486
|
const params = videoSender.getParameters();
|
|
6250
6487
|
if (params.encodings.length === 0) {
|
|
6251
|
-
|
|
6488
|
+
logger$3('warn', 'Update publish quality, No suitable video encoding quality found');
|
|
6252
6489
|
return;
|
|
6253
6490
|
}
|
|
6254
6491
|
let changed = false;
|
|
@@ -6266,10 +6503,10 @@ class Publisher {
|
|
|
6266
6503
|
.join(', ');
|
|
6267
6504
|
if (changed) {
|
|
6268
6505
|
yield videoSender.setParameters(params);
|
|
6269
|
-
|
|
6506
|
+
logger$3('info', `Update publish quality, enabled rids: ${activeRids}`);
|
|
6270
6507
|
}
|
|
6271
6508
|
else {
|
|
6272
|
-
|
|
6509
|
+
logger$3('info', `Update publish quality, no change: ${activeRids}`);
|
|
6273
6510
|
}
|
|
6274
6511
|
});
|
|
6275
6512
|
/**
|
|
@@ -6293,7 +6530,7 @@ class Publisher {
|
|
|
6293
6530
|
this.onIceCandidate = (e) => __awaiter(this, void 0, void 0, function* () {
|
|
6294
6531
|
const { candidate } = e;
|
|
6295
6532
|
if (!candidate) {
|
|
6296
|
-
|
|
6533
|
+
logger$3('debug', 'null ice candidate');
|
|
6297
6534
|
return;
|
|
6298
6535
|
}
|
|
6299
6536
|
yield this.sfuClient.iceTrickle({
|
|
@@ -6322,7 +6559,12 @@ class Publisher {
|
|
|
6322
6559
|
* Restarts the ICE connection and renegotiates with the SFU.
|
|
6323
6560
|
*/
|
|
6324
6561
|
this.restartIce = () => __awaiter(this, void 0, void 0, function* () {
|
|
6325
|
-
|
|
6562
|
+
logger$3('debug', 'Restarting ICE connection');
|
|
6563
|
+
const signalingState = this.pc.signalingState;
|
|
6564
|
+
if (this.isIceRestarting || signalingState === 'have-local-offer') {
|
|
6565
|
+
logger$3('debug', 'ICE restart is already in progress');
|
|
6566
|
+
return;
|
|
6567
|
+
}
|
|
6326
6568
|
yield this.negotiate({ iceRestart: true });
|
|
6327
6569
|
});
|
|
6328
6570
|
this.onNegotiationNeeded = () => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -6334,6 +6576,8 @@ class Publisher {
|
|
|
6334
6576
|
* @param options the optional offer options to use.
|
|
6335
6577
|
*/
|
|
6336
6578
|
this.negotiate = (options) => __awaiter(this, void 0, void 0, function* () {
|
|
6579
|
+
var _b;
|
|
6580
|
+
this.isIceRestarting = (_b = options === null || options === void 0 ? void 0 : options.iceRestart) !== null && _b !== void 0 ? _b : false;
|
|
6337
6581
|
const offer = yield this.pc.createOffer(options);
|
|
6338
6582
|
offer.sdp = this.mungeCodecs(offer.sdp);
|
|
6339
6583
|
const trackInfos = this.getCurrentTrackInfos(offer.sdp);
|
|
@@ -6352,21 +6596,19 @@ class Publisher {
|
|
|
6352
6596
|
});
|
|
6353
6597
|
}
|
|
6354
6598
|
catch (e) {
|
|
6355
|
-
|
|
6599
|
+
logger$3('error', `setRemoteDescription error`, {
|
|
6356
6600
|
sdp: response.sdp,
|
|
6357
6601
|
error: e,
|
|
6358
6602
|
});
|
|
6359
6603
|
}
|
|
6604
|
+
this.isIceRestarting = false;
|
|
6360
6605
|
this.sfuClient.iceTrickleBuffer.publisherCandidates.subscribe((candidate) => __awaiter(this, void 0, void 0, function* () {
|
|
6361
6606
|
try {
|
|
6362
6607
|
const iceCandidate = JSON.parse(candidate.iceCandidate);
|
|
6363
6608
|
yield this.pc.addIceCandidate(iceCandidate);
|
|
6364
6609
|
}
|
|
6365
6610
|
catch (e) {
|
|
6366
|
-
|
|
6367
|
-
error: e,
|
|
6368
|
-
candidate,
|
|
6369
|
-
});
|
|
6611
|
+
logger$3('warn', `ICE candidate error`, [e, candidate]);
|
|
6370
6612
|
}
|
|
6371
6613
|
}));
|
|
6372
6614
|
});
|
|
@@ -6392,10 +6634,10 @@ class Publisher {
|
|
|
6392
6634
|
if (defaultMid)
|
|
6393
6635
|
return defaultMid;
|
|
6394
6636
|
if (!sdp) {
|
|
6395
|
-
|
|
6637
|
+
logger$3('warn', 'No SDP found. Returning empty mid');
|
|
6396
6638
|
return '';
|
|
6397
6639
|
}
|
|
6398
|
-
|
|
6640
|
+
logger$3('debug', `No 'mid' found for track. Trying to find it from the Offer SDP`);
|
|
6399
6641
|
const parsedSdp = SDP.parse(sdp);
|
|
6400
6642
|
const media = parsedSdp.media.find((m) => {
|
|
6401
6643
|
var _a, _b;
|
|
@@ -6404,12 +6646,12 @@ class Publisher {
|
|
|
6404
6646
|
((_b = (_a = m.msid) === null || _a === void 0 ? void 0 : _a.includes(track.id)) !== null && _b !== void 0 ? _b : true));
|
|
6405
6647
|
});
|
|
6406
6648
|
if (typeof (media === null || media === void 0 ? void 0 : media.mid) === 'undefined') {
|
|
6407
|
-
|
|
6649
|
+
logger$3('debug', `No mid found in SDP for track type ${track.kind} and id ${track.id}. Attempting to find a heuristic mid`);
|
|
6408
6650
|
const heuristicMid = this.transceiverInitOrder.indexOf(trackType);
|
|
6409
6651
|
if (heuristicMid !== -1) {
|
|
6410
6652
|
return String(heuristicMid);
|
|
6411
6653
|
}
|
|
6412
|
-
|
|
6654
|
+
logger$3('debug', 'No heuristic mid found. Returning empty mid');
|
|
6413
6655
|
return '';
|
|
6414
6656
|
}
|
|
6415
6657
|
return String(media.mid);
|
|
@@ -6435,7 +6677,7 @@ class Publisher {
|
|
|
6435
6677
|
else {
|
|
6436
6678
|
// we report the last known optimal layers for ended tracks
|
|
6437
6679
|
optimalLayers = this.trackLayersCache[trackType] || [];
|
|
6438
|
-
|
|
6680
|
+
logger$3('debug', `Track ${TrackType[trackType]} is ended. Announcing last known optimal layers`, optimalLayers);
|
|
6439
6681
|
}
|
|
6440
6682
|
const layers = optimalLayers.map((optimalLayer) => ({
|
|
6441
6683
|
rid: optimalLayer.rid || '',
|
|
@@ -6462,38 +6704,41 @@ class Publisher {
|
|
|
6462
6704
|
this.onIceCandidateError = (e) => {
|
|
6463
6705
|
const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
|
|
6464
6706
|
`${e.errorCode}: ${e.errorText}`;
|
|
6465
|
-
|
|
6707
|
+
logger$3('error', `ICE Candidate error`, errorMessage);
|
|
6466
6708
|
};
|
|
6467
6709
|
this.onIceConnectionStateChange = () => {
|
|
6468
6710
|
const state = this.pc.iceConnectionState;
|
|
6469
|
-
|
|
6711
|
+
logger$3('debug', `ICE Connection state changed to`, state);
|
|
6470
6712
|
if (state === 'failed') {
|
|
6471
|
-
|
|
6713
|
+
logger$3('warn', `Attempting to restart ICE`);
|
|
6472
6714
|
this.restartIce().catch((e) => {
|
|
6473
|
-
|
|
6715
|
+
logger$3('error', `ICE restart error`, e);
|
|
6474
6716
|
});
|
|
6475
6717
|
}
|
|
6476
6718
|
else if (state === 'disconnected') {
|
|
6477
6719
|
// when in `disconnected` state, the browser may recover automatically,
|
|
6478
6720
|
// hence, we delay the ICE restart
|
|
6479
|
-
|
|
6721
|
+
logger$3('warn', `Scheduling ICE restart in ${this.iceRestartDelay} ms.`);
|
|
6480
6722
|
setTimeout(() => {
|
|
6481
6723
|
// check if the state is still `disconnected` or `failed`
|
|
6482
6724
|
// as the connection may have recovered (or failed) in the meantime
|
|
6483
6725
|
if (this.pc.iceConnectionState === 'disconnected' ||
|
|
6484
6726
|
this.pc.iceConnectionState === 'failed') {
|
|
6485
6727
|
this.restartIce().catch((e) => {
|
|
6486
|
-
|
|
6728
|
+
logger$3('error', `ICE restart error`, e);
|
|
6487
6729
|
});
|
|
6488
6730
|
}
|
|
6489
|
-
|
|
6731
|
+
else {
|
|
6732
|
+
logger$3('debug', `Scheduled ICE restart: connection recovered, canceled.`);
|
|
6733
|
+
}
|
|
6734
|
+
}, this.iceRestartDelay);
|
|
6490
6735
|
}
|
|
6491
6736
|
};
|
|
6492
6737
|
this.onIceGatheringStateChange = () => {
|
|
6493
|
-
|
|
6738
|
+
logger$3('debug', `ICE Gathering State`, this.pc.iceGatheringState);
|
|
6494
6739
|
};
|
|
6495
6740
|
this.onSignalingStateChange = () => {
|
|
6496
|
-
|
|
6741
|
+
logger$3('debug', `Signaling state changed`, this.pc.signalingState);
|
|
6497
6742
|
};
|
|
6498
6743
|
this.ridToVideoQuality = (rid) => {
|
|
6499
6744
|
return rid === 'q'
|
|
@@ -6505,9 +6750,19 @@ class Publisher {
|
|
|
6505
6750
|
this.pc = this.createPeerConnection(connectionConfig);
|
|
6506
6751
|
this.sfuClient = sfuClient;
|
|
6507
6752
|
this.state = state;
|
|
6753
|
+
this.dispatcher = dispatcher;
|
|
6508
6754
|
this.isDtxEnabled = isDtxEnabled;
|
|
6509
6755
|
this.isRedEnabled = isRedEnabled;
|
|
6510
6756
|
this.preferredVideoCodec = preferredVideoCodec;
|
|
6757
|
+
this.iceRestartDelay = iceRestartDelay;
|
|
6758
|
+
this.unsubscribeOnIceRestart = dispatcher.on('iceRestart', (message) => __awaiter(this, void 0, void 0, function* () {
|
|
6759
|
+
if (message.eventPayload.oneofKind !== 'iceRestart')
|
|
6760
|
+
return;
|
|
6761
|
+
const { iceRestart } = message.eventPayload;
|
|
6762
|
+
if (iceRestart.peerType !== PeerType.PUBLISHER_UNSPECIFIED)
|
|
6763
|
+
return;
|
|
6764
|
+
yield this.restartIce();
|
|
6765
|
+
}));
|
|
6511
6766
|
}
|
|
6512
6767
|
}
|
|
6513
6768
|
|
|
@@ -6524,8 +6779,10 @@ class Subscriber {
|
|
|
6524
6779
|
* @param dispatcher the dispatcher to use.
|
|
6525
6780
|
* @param state the state of the call.
|
|
6526
6781
|
* @param connectionConfig the connection configuration to use.
|
|
6782
|
+
* @param iceRestartDelay the delay in milliseconds to wait before restarting ICE when connection goes to `disconnected` state.
|
|
6527
6783
|
*/
|
|
6528
|
-
constructor({ sfuClient, dispatcher, state, connectionConfig, }) {
|
|
6784
|
+
constructor({ sfuClient, dispatcher, state, connectionConfig, iceRestartDelay = 2500, }) {
|
|
6785
|
+
this.isIceRestarting = false;
|
|
6529
6786
|
/**
|
|
6530
6787
|
* Creates a new `RTCPeerConnection` instance with the given configuration.
|
|
6531
6788
|
*
|
|
@@ -6545,6 +6802,7 @@ class Subscriber {
|
|
|
6545
6802
|
*/
|
|
6546
6803
|
this.close = () => {
|
|
6547
6804
|
this.unregisterOnSubscriberOffer();
|
|
6805
|
+
this.unregisterOnIceRestart();
|
|
6548
6806
|
this.pc.close();
|
|
6549
6807
|
};
|
|
6550
6808
|
/**
|
|
@@ -6617,10 +6875,25 @@ class Subscriber {
|
|
|
6617
6875
|
/**
|
|
6618
6876
|
* Restarts the ICE connection and renegotiates with the SFU.
|
|
6619
6877
|
*/
|
|
6620
|
-
this.restartIce = () => {
|
|
6878
|
+
this.restartIce = () => __awaiter(this, void 0, void 0, function* () {
|
|
6621
6879
|
logger$2('debug', 'Restarting ICE connection');
|
|
6622
|
-
this.pc.
|
|
6623
|
-
|
|
6880
|
+
if (this.pc.signalingState === 'have-remote-offer') {
|
|
6881
|
+
logger$2('debug', 'ICE restart is already in progress');
|
|
6882
|
+
return;
|
|
6883
|
+
}
|
|
6884
|
+
const previousIsIceRestarting = this.isIceRestarting;
|
|
6885
|
+
try {
|
|
6886
|
+
this.isIceRestarting = true;
|
|
6887
|
+
yield this.sfuClient.iceRestart({
|
|
6888
|
+
peerType: PeerType.SUBSCRIBER,
|
|
6889
|
+
});
|
|
6890
|
+
}
|
|
6891
|
+
catch (e) {
|
|
6892
|
+
// restore the previous state, as our intent for restarting ICE failed
|
|
6893
|
+
this.isIceRestarting = previousIsIceRestarting;
|
|
6894
|
+
throw e;
|
|
6895
|
+
}
|
|
6896
|
+
});
|
|
6624
6897
|
this.handleOnTrack = (e) => {
|
|
6625
6898
|
const [primaryStream] = e.streams;
|
|
6626
6899
|
// example: `e3f6aaf8-b03d-4911-be36-83f47d37a76a:TRACK_TYPE_VIDEO`
|
|
@@ -6684,22 +6957,50 @@ class Subscriber {
|
|
|
6684
6957
|
yield this.pc.addIceCandidate(iceCandidate);
|
|
6685
6958
|
}
|
|
6686
6959
|
catch (e) {
|
|
6687
|
-
logger$2('
|
|
6960
|
+
logger$2('warn', `ICE candidate error`, [e, candidate]);
|
|
6688
6961
|
}
|
|
6689
6962
|
}));
|
|
6690
|
-
// apply ice candidates
|
|
6691
6963
|
const answer = yield this.pc.createAnswer();
|
|
6692
6964
|
yield this.pc.setLocalDescription(answer);
|
|
6693
6965
|
yield this.sfuClient.sendAnswer({
|
|
6694
6966
|
peerType: PeerType.SUBSCRIBER,
|
|
6695
6967
|
sdp: answer.sdp || '',
|
|
6696
6968
|
});
|
|
6969
|
+
this.isIceRestarting = false;
|
|
6697
6970
|
});
|
|
6698
6971
|
this.onIceConnectionStateChange = () => {
|
|
6699
|
-
|
|
6972
|
+
const state = this.pc.iceConnectionState;
|
|
6973
|
+
logger$2('debug', `ICE connection state changed`, state);
|
|
6974
|
+
// do nothing when ICE is restarting
|
|
6975
|
+
if (this.isIceRestarting)
|
|
6976
|
+
return;
|
|
6977
|
+
if (state === 'failed') {
|
|
6978
|
+
logger$2('warn', `Attempting to restart ICE`);
|
|
6979
|
+
this.restartIce().catch((e) => {
|
|
6980
|
+
logger$2('error', `ICE restart failed`, e);
|
|
6981
|
+
});
|
|
6982
|
+
}
|
|
6983
|
+
else if (state === 'disconnected') {
|
|
6984
|
+
// when in `disconnected` state, the browser may recover automatically,
|
|
6985
|
+
// hence, we delay the ICE restart
|
|
6986
|
+
logger$2('warn', `Scheduling ICE restart in ${this.iceRestartDelay} ms.`);
|
|
6987
|
+
setTimeout(() => {
|
|
6988
|
+
// check if the state is still `disconnected` or `failed`
|
|
6989
|
+
// as the connection may have recovered (or failed) in the meantime
|
|
6990
|
+
if (this.pc.iceConnectionState === 'disconnected' ||
|
|
6991
|
+
this.pc.iceConnectionState === 'failed') {
|
|
6992
|
+
this.restartIce().catch((e) => {
|
|
6993
|
+
logger$2('error', `ICE restart failed`, e);
|
|
6994
|
+
});
|
|
6995
|
+
}
|
|
6996
|
+
else {
|
|
6997
|
+
logger$2('debug', `Scheduled ICE restart: connection recovered, canceled.`);
|
|
6998
|
+
}
|
|
6999
|
+
}, 5000);
|
|
7000
|
+
}
|
|
6700
7001
|
};
|
|
6701
7002
|
this.onIceGatheringStateChange = () => {
|
|
6702
|
-
logger$2('
|
|
7003
|
+
logger$2('debug', `ICE gathering state changed`, this.pc.iceGatheringState);
|
|
6703
7004
|
};
|
|
6704
7005
|
this.onIceCandidateError = (e) => {
|
|
6705
7006
|
const errorMessage = e instanceof RTCPeerConnectionIceErrorEvent &&
|
|
@@ -6709,6 +7010,7 @@ class Subscriber {
|
|
|
6709
7010
|
this.sfuClient = sfuClient;
|
|
6710
7011
|
this.dispatcher = dispatcher;
|
|
6711
7012
|
this.state = state;
|
|
7013
|
+
this.iceRestartDelay = iceRestartDelay;
|
|
6712
7014
|
this.pc = this.createPeerConnection(connectionConfig);
|
|
6713
7015
|
this.unregisterOnSubscriberOffer = dispatcher.on('subscriberOffer', (message) => __awaiter(this, void 0, void 0, function* () {
|
|
6714
7016
|
if (message.eventPayload.oneofKind !== 'subscriberOffer')
|
|
@@ -6716,6 +7018,14 @@ class Subscriber {
|
|
|
6716
7018
|
const { subscriberOffer } = message.eventPayload;
|
|
6717
7019
|
yield this.negotiate(subscriberOffer);
|
|
6718
7020
|
}));
|
|
7021
|
+
this.unregisterOnIceRestart = dispatcher.on('iceRestart', (message) => __awaiter(this, void 0, void 0, function* () {
|
|
7022
|
+
if (message.eventPayload.oneofKind !== 'iceRestart')
|
|
7023
|
+
return;
|
|
7024
|
+
const { iceRestart } = message.eventPayload;
|
|
7025
|
+
if (iceRestart.peerType !== PeerType.SUBSCRIBER)
|
|
7026
|
+
return;
|
|
7027
|
+
yield this.restartIce();
|
|
7028
|
+
}));
|
|
6719
7029
|
}
|
|
6720
7030
|
}
|
|
6721
7031
|
|
|
@@ -6902,6 +7212,7 @@ class StreamSfuClient {
|
|
|
6902
7212
|
this.pingIntervalInMs = 10 * 1000;
|
|
6903
7213
|
this.unhealthyTimeoutInMs = this.pingIntervalInMs + 5 * 1000;
|
|
6904
7214
|
this.close = (code = 1000, reason = 'Requested signal connection close') => {
|
|
7215
|
+
this.logger('debug', 'Closing SFU WS connection', code, reason);
|
|
6905
7216
|
this.signalWs.close(code, reason);
|
|
6906
7217
|
this.unsubscribeIceTrickle();
|
|
6907
7218
|
clearInterval(this.keepAliveInterval);
|
|
@@ -6922,6 +7233,9 @@ class StreamSfuClient {
|
|
|
6922
7233
|
this.iceTrickle = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
6923
7234
|
return retryable(() => this.rpc.iceTrickle(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
6924
7235
|
});
|
|
7236
|
+
this.iceRestart = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
7237
|
+
return retryable(() => this.rpc.iceRestart(Object.assign(Object.assign({}, data), { sessionId: this.sessionId })), this.logger);
|
|
7238
|
+
});
|
|
6925
7239
|
this.updateMuteState = (trackType, muted) => __awaiter(this, void 0, void 0, function* () {
|
|
6926
7240
|
return this.updateMuteStates({
|
|
6927
7241
|
muteStates: [
|
|
@@ -6973,7 +7287,6 @@ class StreamSfuClient {
|
|
|
6973
7287
|
if (this.lastMessageTimestamp) {
|
|
6974
7288
|
const timeSinceLastMessage = new Date().getTime() - this.lastMessageTimestamp.getTime();
|
|
6975
7289
|
if (timeSinceLastMessage > this.unhealthyTimeoutInMs) {
|
|
6976
|
-
this.logger('debug', 'SFU connection unhealthy, closing');
|
|
6977
7290
|
this.close(4001, `SFU connection unhealthy. Didn't receive any healthcheck messages for ${this.unhealthyTimeoutInMs}ms`);
|
|
6978
7291
|
}
|
|
6979
7292
|
}
|
|
@@ -6984,10 +7297,9 @@ class StreamSfuClient {
|
|
|
6984
7297
|
this.edgeName = sfuServer.edge_name;
|
|
6985
7298
|
this.token = token;
|
|
6986
7299
|
this.logger = getLogger(['sfu-client']);
|
|
6987
|
-
const logger = this.logger;
|
|
6988
7300
|
const logInterceptor = {
|
|
6989
|
-
interceptUnary(next, method, input, options) {
|
|
6990
|
-
logger('trace', `Calling SFU RPC method ${method.name}`, {
|
|
7301
|
+
interceptUnary: (next, method, input, options) => {
|
|
7302
|
+
this.logger('trace', `Calling SFU RPC method ${method.name}`, {
|
|
6991
7303
|
input,
|
|
6992
7304
|
options,
|
|
6993
7305
|
});
|
|
@@ -9156,11 +9468,13 @@ class Call {
|
|
|
9156
9468
|
*/
|
|
9157
9469
|
this.leave = ({ reject = false } = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
9158
9470
|
var _a, _b, _c, _d;
|
|
9159
|
-
// TODO: handle case when leave is called during JOINING
|
|
9160
9471
|
const callingState = this.state.callingState;
|
|
9161
9472
|
if (callingState === CallingState.LEFT) {
|
|
9162
9473
|
throw new Error('Cannot leave call that has already been left.');
|
|
9163
9474
|
}
|
|
9475
|
+
if (callingState === CallingState.JOINING) {
|
|
9476
|
+
yield this.assertCallJoined();
|
|
9477
|
+
}
|
|
9164
9478
|
if (this.ringing) {
|
|
9165
9479
|
// I'm the one who started the call, so I should cancel it.
|
|
9166
9480
|
const hasOtherParticipants = this.state.remoteParticipants.length > 0;
|
|
@@ -9463,6 +9777,7 @@ class Call {
|
|
|
9463
9777
|
if (!this.publisher) {
|
|
9464
9778
|
this.publisher = new Publisher({
|
|
9465
9779
|
sfuClient,
|
|
9780
|
+
dispatcher: this.dispatcher,
|
|
9466
9781
|
state: this.state,
|
|
9467
9782
|
connectionConfig,
|
|
9468
9783
|
isDtxEnabled,
|
|
@@ -9499,6 +9814,7 @@ class Call {
|
|
|
9499
9814
|
subscriberSdp: sdp || '',
|
|
9500
9815
|
clientDetails: getClientDetails(),
|
|
9501
9816
|
migration,
|
|
9817
|
+
fastReconnect: false,
|
|
9502
9818
|
});
|
|
9503
9819
|
});
|
|
9504
9820
|
// 2. in parallel, wait for the SFU to send us the "joinResponse"
|
|
@@ -9564,13 +9880,6 @@ class Call {
|
|
|
9564
9880
|
}, timeout);
|
|
9565
9881
|
});
|
|
9566
9882
|
};
|
|
9567
|
-
this.assertCallJoined = () => {
|
|
9568
|
-
return new Promise((resolve) => {
|
|
9569
|
-
this.state.callingState$
|
|
9570
|
-
.pipe(takeWhile((state) => state !== CallingState.JOINED, true))
|
|
9571
|
-
.subscribe(() => resolve());
|
|
9572
|
-
});
|
|
9573
|
-
};
|
|
9574
9883
|
/**
|
|
9575
9884
|
* Starts publishing the given video stream to the call.
|
|
9576
9885
|
* The stream will be stopped if the user changes an input device, or if the user leaves the call.
|
|
@@ -9801,6 +10110,13 @@ class Call {
|
|
|
9801
10110
|
var _h;
|
|
9802
10111
|
return (_h = this.publisher) === null || _h === void 0 ? void 0 : _h.updateVideoPublishQuality(enabledRids);
|
|
9803
10112
|
});
|
|
10113
|
+
this.assertCallJoined = () => {
|
|
10114
|
+
return new Promise((resolve) => {
|
|
10115
|
+
this.state.callingState$
|
|
10116
|
+
.pipe(takeWhile((state) => state !== CallingState.JOINED, true), filter((s) => s === CallingState.JOINED))
|
|
10117
|
+
.subscribe(() => resolve());
|
|
10118
|
+
});
|
|
10119
|
+
};
|
|
9804
10120
|
/**
|
|
9805
10121
|
* Sends a reaction to the other call participants.
|
|
9806
10122
|
*
|
|
@@ -11324,7 +11640,7 @@ class WSConnectionFallback {
|
|
|
11324
11640
|
}
|
|
11325
11641
|
}
|
|
11326
11642
|
|
|
11327
|
-
const version = '0.1.
|
|
11643
|
+
const version = '0.1.5';
|
|
11328
11644
|
|
|
11329
11645
|
const logger = getLogger(['location']);
|
|
11330
11646
|
const HINT_URL = `https://hint.stream-io-video.com/`;
|
|
@@ -11387,14 +11703,6 @@ class StreamClient {
|
|
|
11387
11703
|
});
|
|
11388
11704
|
this._getConnectionID = () => { var _a, _b; return ((_a = this.wsConnection) === null || _a === void 0 ? void 0 : _a.connectionID) || ((_b = this.wsFallback) === null || _b === void 0 ? void 0 : _b.connectionID); };
|
|
11389
11705
|
this._hasConnectionID = () => Boolean(this._getConnectionID());
|
|
11390
|
-
/**
|
|
11391
|
-
* This will start a promise to hold API calls until `connectUser` is called, useful when user is set in `StreamVideoClient constructor`
|
|
11392
|
-
*/
|
|
11393
|
-
this.startWaitingForConnection = () => {
|
|
11394
|
-
this.waitForConnectPromise = new Promise((resolve) => {
|
|
11395
|
-
this.resolveConnectPromise = resolve;
|
|
11396
|
-
});
|
|
11397
|
-
};
|
|
11398
11706
|
/**
|
|
11399
11707
|
* connectUser - Set the current user and open a WebSocket connection
|
|
11400
11708
|
*
|
|
@@ -11429,11 +11737,6 @@ class StreamClient {
|
|
|
11429
11737
|
this._setUser(user);
|
|
11430
11738
|
const wsPromise = this.openConnection();
|
|
11431
11739
|
this.setUserPromise = Promise.all([setTokenPromise, wsPromise]).then((result) => result[1]);
|
|
11432
|
-
if (this.resolveConnectPromise) {
|
|
11433
|
-
this.resolveConnectPromise();
|
|
11434
|
-
this.waitForConnectPromise = undefined;
|
|
11435
|
-
this.resolveConnectPromise = undefined;
|
|
11436
|
-
}
|
|
11437
11740
|
try {
|
|
11438
11741
|
return yield this.setUserPromise;
|
|
11439
11742
|
}
|
|
@@ -11548,11 +11851,6 @@ class StreamClient {
|
|
|
11548
11851
|
});
|
|
11549
11852
|
this.anonymous = true;
|
|
11550
11853
|
yield this._setToken(user, tokenOrProvider, this.anonymous);
|
|
11551
|
-
if (this.resolveConnectPromise) {
|
|
11552
|
-
this.resolveConnectPromise();
|
|
11553
|
-
this.waitForConnectPromise = undefined;
|
|
11554
|
-
this.resolveConnectPromise = undefined;
|
|
11555
|
-
}
|
|
11556
11854
|
this._setUser(user);
|
|
11557
11855
|
// some endpoints require a connection_id to be resolved.
|
|
11558
11856
|
// as anonymous users aren't allowed to open WS connections, we just
|
|
@@ -11622,9 +11920,6 @@ class StreamClient {
|
|
|
11622
11920
|
this.doAxiosRequest = (type, url, data, options = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
11623
11921
|
var _h;
|
|
11624
11922
|
if (!options.publicEndpoint) {
|
|
11625
|
-
if (this.waitForConnectPromise) {
|
|
11626
|
-
yield this.waitForConnectPromise;
|
|
11627
|
-
}
|
|
11628
11923
|
yield Promise.all([
|
|
11629
11924
|
this.tokenManager.tokenReady(),
|
|
11630
11925
|
this.connectionIdPromise,
|
|
@@ -11962,6 +12257,7 @@ class StreamClient {
|
|
|
11962
12257
|
class StreamVideoClient {
|
|
11963
12258
|
constructor(apiKeyOrArgs, opts) {
|
|
11964
12259
|
var _a, _b;
|
|
12260
|
+
this.logLevel = 'warn';
|
|
11965
12261
|
this.eventHandlersToUnregister = [];
|
|
11966
12262
|
/**
|
|
11967
12263
|
* Disconnects the currently connected user from the client.
|
|
@@ -11972,7 +12268,7 @@ class StreamVideoClient {
|
|
|
11972
12268
|
* https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
|
|
11973
12269
|
*/
|
|
11974
12270
|
this.disconnectUser = (timeout) => __awaiter(this, void 0, void 0, function* () {
|
|
11975
|
-
if (!this.streamClient.user) {
|
|
12271
|
+
if (!this.streamClient.user && !this.connectionPromise) {
|
|
11976
12272
|
return;
|
|
11977
12273
|
}
|
|
11978
12274
|
const disconnectUser = () => this.streamClient.disconnectUser(timeout);
|
|
@@ -12149,14 +12445,16 @@ class StreamVideoClient {
|
|
|
12149
12445
|
this.streamClient.setUserAgent(this.streamClient.getUserAgent() +
|
|
12150
12446
|
`-video-${SdkType[sdkInfo.type].toLowerCase()}-sdk-${sdkInfo.major}.${sdkInfo.minor}.${sdkInfo.patch}`);
|
|
12151
12447
|
}
|
|
12152
|
-
this.user = apiKeyOrArgs.user;
|
|
12153
|
-
this.token = apiKeyOrArgs.token || apiKeyOrArgs.tokenProvider;
|
|
12154
|
-
if (this.user) {
|
|
12155
|
-
this.streamClient.startWaitingForConnection();
|
|
12156
|
-
}
|
|
12157
12448
|
}
|
|
12158
12449
|
this.writeableStateStore = new StreamVideoWriteableStateStore();
|
|
12159
12450
|
this.readOnlyStateStore = new StreamVideoReadOnlyStateStore(this.writeableStateStore);
|
|
12451
|
+
if (typeof apiKeyOrArgs !== 'string') {
|
|
12452
|
+
const user = apiKeyOrArgs.user;
|
|
12453
|
+
const token = apiKeyOrArgs.token || apiKeyOrArgs.tokenProvider;
|
|
12454
|
+
if (user) {
|
|
12455
|
+
this.connectUser(user, token);
|
|
12456
|
+
}
|
|
12457
|
+
}
|
|
12160
12458
|
}
|
|
12161
12459
|
/**
|
|
12162
12460
|
* Connects the given user to the client.
|
|
@@ -12169,24 +12467,21 @@ class StreamVideoClient {
|
|
|
12169
12467
|
connectUser(user, token) {
|
|
12170
12468
|
var _a;
|
|
12171
12469
|
return __awaiter(this, void 0, void 0, function* () {
|
|
12172
|
-
|
|
12173
|
-
|
|
12174
|
-
|
|
12175
|
-
throw new Error('Connect user is called without user');
|
|
12176
|
-
}
|
|
12177
|
-
if (userToConnect.type === 'anonymous') {
|
|
12178
|
-
userToConnect.id = '!anon';
|
|
12179
|
-
return this.connectAnonymousUser(userToConnect, tokenToUse);
|
|
12180
|
-
}
|
|
12181
|
-
if (userToConnect.type === 'guest') {
|
|
12182
|
-
const response = yield this.createGuestUser({
|
|
12183
|
-
user: Object.assign(Object.assign({}, userToConnect), { role: 'guest' }),
|
|
12184
|
-
});
|
|
12185
|
-
return this.connectUser(response.user, response.access_token);
|
|
12470
|
+
if (user.type === 'anonymous') {
|
|
12471
|
+
user.id = '!anon';
|
|
12472
|
+
return this.connectAnonymousUser(user, token);
|
|
12186
12473
|
}
|
|
12187
|
-
|
|
12188
|
-
return this.streamClient.connectUser(
|
|
12474
|
+
let connectUser = () => {
|
|
12475
|
+
return this.streamClient.connectUser(user, token);
|
|
12189
12476
|
};
|
|
12477
|
+
if (user.type === 'guest') {
|
|
12478
|
+
connectUser = () => __awaiter(this, void 0, void 0, function* () {
|
|
12479
|
+
const response = yield this.createGuestUser({
|
|
12480
|
+
user: Object.assign(Object.assign({}, user), { role: 'guest' }),
|
|
12481
|
+
});
|
|
12482
|
+
return this.streamClient.connectUser(response.user, response.access_token);
|
|
12483
|
+
});
|
|
12484
|
+
}
|
|
12190
12485
|
this.connectionPromise = this.disconnectionPromise
|
|
12191
12486
|
? this.disconnectionPromise.then(() => connectUser())
|
|
12192
12487
|
: connectUser();
|
|
@@ -12220,7 +12515,7 @@ class StreamVideoClient {
|
|
|
12220
12515
|
if (event.type !== 'call.created')
|
|
12221
12516
|
return;
|
|
12222
12517
|
const { call, members } = event;
|
|
12223
|
-
if (
|
|
12518
|
+
if (user.id === call.created_by.id) {
|
|
12224
12519
|
this.logger('warn', 'Received `call.created` sent by the current user');
|
|
12225
12520
|
return;
|
|
12226
12521
|
}
|
|
@@ -12238,7 +12533,7 @@ class StreamVideoClient {
|
|
|
12238
12533
|
if (event.type !== 'call.ring')
|
|
12239
12534
|
return;
|
|
12240
12535
|
const { call, members } = event;
|
|
12241
|
-
if (
|
|
12536
|
+
if (user.id === call.created_by.id) {
|
|
12242
12537
|
this.logger('debug', 'Received `call.ring` sent by the current user so ignoring the event');
|
|
12243
12538
|
return;
|
|
12244
12539
|
}
|