livekit-client 1.1.7 → 1.2.0
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/README.md +1 -0
- package/dist/livekit-client.esm.mjs +667 -176
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/api/SignalClient.d.ts +4 -1
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/options.d.ts +1 -0
- package/dist/src/options.d.ts.map +1 -1
- package/dist/src/proto/livekit_models.d.ts +234 -0
- package/dist/src/proto/livekit_models.d.ts.map +1 -1
- package/dist/src/proto/livekit_rtc.d.ts +944 -6
- package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +3 -2
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +3 -3
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +8 -1
- package/dist/src/room/events.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/Participant.d.ts.map +1 -1
- package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrack.d.ts +2 -0
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteTrackPublication.d.ts +4 -1
- package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +7 -0
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/room/track/TrackPublication.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/api/SignalClient.ts +21 -6
- package/src/index.ts +6 -2
- package/src/options.ts +1 -0
- package/src/proto/livekit_models.ts +179 -4
- package/src/proto/livekit_rtc.ts +14 -1
- package/src/room/RTCEngine.ts +45 -18
- package/src/room/Room.ts +46 -25
- package/src/room/events.ts +7 -0
- package/src/room/participant/LocalParticipant.ts +45 -7
- package/src/room/participant/Participant.ts +2 -0
- package/src/room/participant/RemoteParticipant.ts +16 -10
- package/src/room/track/LocalAudioTrack.ts +16 -12
- package/src/room/track/LocalTrack.ts +41 -25
- package/src/room/track/LocalVideoTrack.ts +15 -11
- package/src/room/track/RemoteTrack.ts +1 -0
- package/src/room/track/RemoteTrackPublication.ts +37 -11
- package/src/room/track/Track.ts +12 -0
- package/src/room/track/TrackPublication.ts +2 -0
- package/dist/src/api/RequestQueue.d.ts +0 -13
- package/dist/src/api/RequestQueue.d.ts.map +0 -1
- package/src/api/RequestQueue.ts +0 -53
@@ -213,6 +213,68 @@ export function clientConfigSettingToJSON(object: ClientConfigSetting): string {
|
|
213
213
|
}
|
214
214
|
}
|
215
215
|
|
216
|
+
export enum DisconnectReason {
|
217
|
+
UNKNOWN_REASON = 0,
|
218
|
+
CLIENT_INITIATED = 1,
|
219
|
+
DUPLICATE_IDENTITY = 2,
|
220
|
+
SERVER_SHUTDOWN = 3,
|
221
|
+
PARTICIPANT_REMOVED = 4,
|
222
|
+
ROOM_DELETED = 5,
|
223
|
+
STATE_MISMATCH = 6,
|
224
|
+
UNRECOGNIZED = -1,
|
225
|
+
}
|
226
|
+
|
227
|
+
export function disconnectReasonFromJSON(object: any): DisconnectReason {
|
228
|
+
switch (object) {
|
229
|
+
case 0:
|
230
|
+
case 'UNKNOWN_REASON':
|
231
|
+
return DisconnectReason.UNKNOWN_REASON;
|
232
|
+
case 1:
|
233
|
+
case 'CLIENT_INITIATED':
|
234
|
+
return DisconnectReason.CLIENT_INITIATED;
|
235
|
+
case 2:
|
236
|
+
case 'DUPLICATE_IDENTITY':
|
237
|
+
return DisconnectReason.DUPLICATE_IDENTITY;
|
238
|
+
case 3:
|
239
|
+
case 'SERVER_SHUTDOWN':
|
240
|
+
return DisconnectReason.SERVER_SHUTDOWN;
|
241
|
+
case 4:
|
242
|
+
case 'PARTICIPANT_REMOVED':
|
243
|
+
return DisconnectReason.PARTICIPANT_REMOVED;
|
244
|
+
case 5:
|
245
|
+
case 'ROOM_DELETED':
|
246
|
+
return DisconnectReason.ROOM_DELETED;
|
247
|
+
case 6:
|
248
|
+
case 'STATE_MISMATCH':
|
249
|
+
return DisconnectReason.STATE_MISMATCH;
|
250
|
+
case -1:
|
251
|
+
case 'UNRECOGNIZED':
|
252
|
+
default:
|
253
|
+
return DisconnectReason.UNRECOGNIZED;
|
254
|
+
}
|
255
|
+
}
|
256
|
+
|
257
|
+
export function disconnectReasonToJSON(object: DisconnectReason): string {
|
258
|
+
switch (object) {
|
259
|
+
case DisconnectReason.UNKNOWN_REASON:
|
260
|
+
return 'UNKNOWN_REASON';
|
261
|
+
case DisconnectReason.CLIENT_INITIATED:
|
262
|
+
return 'CLIENT_INITIATED';
|
263
|
+
case DisconnectReason.DUPLICATE_IDENTITY:
|
264
|
+
return 'DUPLICATE_IDENTITY';
|
265
|
+
case DisconnectReason.SERVER_SHUTDOWN:
|
266
|
+
return 'SERVER_SHUTDOWN';
|
267
|
+
case DisconnectReason.PARTICIPANT_REMOVED:
|
268
|
+
return 'PARTICIPANT_REMOVED';
|
269
|
+
case DisconnectReason.ROOM_DELETED:
|
270
|
+
return 'ROOM_DELETED';
|
271
|
+
case DisconnectReason.STATE_MISMATCH:
|
272
|
+
return 'STATE_MISMATCH';
|
273
|
+
default:
|
274
|
+
return 'UNKNOWN';
|
275
|
+
}
|
276
|
+
}
|
277
|
+
|
216
278
|
export interface Room {
|
217
279
|
sid: string;
|
218
280
|
name: string;
|
@@ -315,6 +377,7 @@ export interface SimulcastCodecInfo {
|
|
315
377
|
mimeType: string;
|
316
378
|
mid: string;
|
317
379
|
cid: string;
|
380
|
+
layers: VideoLayer[];
|
318
381
|
}
|
319
382
|
|
320
383
|
export interface TrackInfo {
|
@@ -499,12 +562,17 @@ export interface ClientConfiguration {
|
|
499
562
|
video?: VideoConfiguration;
|
500
563
|
screen?: VideoConfiguration;
|
501
564
|
resumeConnection: ClientConfigSetting;
|
565
|
+
disabledCodecs?: DisabledCodecs;
|
502
566
|
}
|
503
567
|
|
504
568
|
export interface VideoConfiguration {
|
505
569
|
hardwareEncoder: ClientConfigSetting;
|
506
570
|
}
|
507
571
|
|
572
|
+
export interface DisabledCodecs {
|
573
|
+
codecs: Codec[];
|
574
|
+
}
|
575
|
+
|
508
576
|
export interface RTPStats {
|
509
577
|
startTime?: Date;
|
510
578
|
endTime?: Date;
|
@@ -531,7 +599,9 @@ export interface RTPStats {
|
|
531
599
|
jitterMax: number;
|
532
600
|
gapHistogram: { [key: number]: number };
|
533
601
|
nacks: number;
|
602
|
+
nackAcks: number;
|
534
603
|
nackMisses: number;
|
604
|
+
nackRepeated: number;
|
535
605
|
plis: number;
|
536
606
|
lastPli?: Date;
|
537
607
|
firs: number;
|
@@ -1015,7 +1085,7 @@ export const ParticipantInfo = {
|
|
1015
1085
|
};
|
1016
1086
|
|
1017
1087
|
function createBaseSimulcastCodecInfo(): SimulcastCodecInfo {
|
1018
|
-
return { mimeType: '', mid: '', cid: '' };
|
1088
|
+
return { mimeType: '', mid: '', cid: '', layers: [] };
|
1019
1089
|
}
|
1020
1090
|
|
1021
1091
|
export const SimulcastCodecInfo = {
|
@@ -1029,6 +1099,9 @@ export const SimulcastCodecInfo = {
|
|
1029
1099
|
if (message.cid !== '') {
|
1030
1100
|
writer.uint32(26).string(message.cid);
|
1031
1101
|
}
|
1102
|
+
for (const v of message.layers) {
|
1103
|
+
VideoLayer.encode(v!, writer.uint32(34).fork()).ldelim();
|
1104
|
+
}
|
1032
1105
|
return writer;
|
1033
1106
|
},
|
1034
1107
|
|
@@ -1048,6 +1121,9 @@ export const SimulcastCodecInfo = {
|
|
1048
1121
|
case 3:
|
1049
1122
|
message.cid = reader.string();
|
1050
1123
|
break;
|
1124
|
+
case 4:
|
1125
|
+
message.layers.push(VideoLayer.decode(reader, reader.uint32()));
|
1126
|
+
break;
|
1051
1127
|
default:
|
1052
1128
|
reader.skipType(tag & 7);
|
1053
1129
|
break;
|
@@ -1061,6 +1137,9 @@ export const SimulcastCodecInfo = {
|
|
1061
1137
|
mimeType: isSet(object.mimeType) ? String(object.mimeType) : '',
|
1062
1138
|
mid: isSet(object.mid) ? String(object.mid) : '',
|
1063
1139
|
cid: isSet(object.cid) ? String(object.cid) : '',
|
1140
|
+
layers: Array.isArray(object?.layers)
|
1141
|
+
? object.layers.map((e: any) => VideoLayer.fromJSON(e))
|
1142
|
+
: [],
|
1064
1143
|
};
|
1065
1144
|
},
|
1066
1145
|
|
@@ -1069,6 +1148,11 @@ export const SimulcastCodecInfo = {
|
|
1069
1148
|
message.mimeType !== undefined && (obj.mimeType = message.mimeType);
|
1070
1149
|
message.mid !== undefined && (obj.mid = message.mid);
|
1071
1150
|
message.cid !== undefined && (obj.cid = message.cid);
|
1151
|
+
if (message.layers) {
|
1152
|
+
obj.layers = message.layers.map((e) => (e ? VideoLayer.toJSON(e) : undefined));
|
1153
|
+
} else {
|
1154
|
+
obj.layers = [];
|
1155
|
+
}
|
1072
1156
|
return obj;
|
1073
1157
|
},
|
1074
1158
|
|
@@ -1077,6 +1161,7 @@ export const SimulcastCodecInfo = {
|
|
1077
1161
|
message.mimeType = object.mimeType ?? '';
|
1078
1162
|
message.mid = object.mid ?? '';
|
1079
1163
|
message.cid = object.cid ?? '';
|
1164
|
+
message.layers = object.layers?.map((e) => VideoLayer.fromPartial(e)) || [];
|
1080
1165
|
return message;
|
1081
1166
|
},
|
1082
1167
|
};
|
@@ -1820,7 +1905,7 @@ export const ClientInfo = {
|
|
1820
1905
|
};
|
1821
1906
|
|
1822
1907
|
function createBaseClientConfiguration(): ClientConfiguration {
|
1823
|
-
return { video: undefined, screen: undefined, resumeConnection: 0 };
|
1908
|
+
return { video: undefined, screen: undefined, resumeConnection: 0, disabledCodecs: undefined };
|
1824
1909
|
}
|
1825
1910
|
|
1826
1911
|
export const ClientConfiguration = {
|
@@ -1834,6 +1919,9 @@ export const ClientConfiguration = {
|
|
1834
1919
|
if (message.resumeConnection !== 0) {
|
1835
1920
|
writer.uint32(24).int32(message.resumeConnection);
|
1836
1921
|
}
|
1922
|
+
if (message.disabledCodecs !== undefined) {
|
1923
|
+
DisabledCodecs.encode(message.disabledCodecs, writer.uint32(34).fork()).ldelim();
|
1924
|
+
}
|
1837
1925
|
return writer;
|
1838
1926
|
},
|
1839
1927
|
|
@@ -1853,6 +1941,9 @@ export const ClientConfiguration = {
|
|
1853
1941
|
case 3:
|
1854
1942
|
message.resumeConnection = reader.int32() as any;
|
1855
1943
|
break;
|
1944
|
+
case 4:
|
1945
|
+
message.disabledCodecs = DisabledCodecs.decode(reader, reader.uint32());
|
1946
|
+
break;
|
1856
1947
|
default:
|
1857
1948
|
reader.skipType(tag & 7);
|
1858
1949
|
break;
|
@@ -1868,6 +1959,9 @@ export const ClientConfiguration = {
|
|
1868
1959
|
resumeConnection: isSet(object.resumeConnection)
|
1869
1960
|
? clientConfigSettingFromJSON(object.resumeConnection)
|
1870
1961
|
: 0,
|
1962
|
+
disabledCodecs: isSet(object.disabledCodecs)
|
1963
|
+
? DisabledCodecs.fromJSON(object.disabledCodecs)
|
1964
|
+
: undefined,
|
1871
1965
|
};
|
1872
1966
|
},
|
1873
1967
|
|
@@ -1879,6 +1973,10 @@ export const ClientConfiguration = {
|
|
1879
1973
|
(obj.screen = message.screen ? VideoConfiguration.toJSON(message.screen) : undefined);
|
1880
1974
|
message.resumeConnection !== undefined &&
|
1881
1975
|
(obj.resumeConnection = clientConfigSettingToJSON(message.resumeConnection));
|
1976
|
+
message.disabledCodecs !== undefined &&
|
1977
|
+
(obj.disabledCodecs = message.disabledCodecs
|
1978
|
+
? DisabledCodecs.toJSON(message.disabledCodecs)
|
1979
|
+
: undefined);
|
1882
1980
|
return obj;
|
1883
1981
|
},
|
1884
1982
|
|
@@ -1895,6 +1993,10 @@ export const ClientConfiguration = {
|
|
1895
1993
|
? VideoConfiguration.fromPartial(object.screen)
|
1896
1994
|
: undefined;
|
1897
1995
|
message.resumeConnection = object.resumeConnection ?? 0;
|
1996
|
+
message.disabledCodecs =
|
1997
|
+
object.disabledCodecs !== undefined && object.disabledCodecs !== null
|
1998
|
+
? DisabledCodecs.fromPartial(object.disabledCodecs)
|
1999
|
+
: undefined;
|
1898
2000
|
return message;
|
1899
2001
|
},
|
1900
2002
|
};
|
@@ -1951,6 +2053,59 @@ export const VideoConfiguration = {
|
|
1951
2053
|
},
|
1952
2054
|
};
|
1953
2055
|
|
2056
|
+
function createBaseDisabledCodecs(): DisabledCodecs {
|
2057
|
+
return { codecs: [] };
|
2058
|
+
}
|
2059
|
+
|
2060
|
+
export const DisabledCodecs = {
|
2061
|
+
encode(message: DisabledCodecs, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
2062
|
+
for (const v of message.codecs) {
|
2063
|
+
Codec.encode(v!, writer.uint32(10).fork()).ldelim();
|
2064
|
+
}
|
2065
|
+
return writer;
|
2066
|
+
},
|
2067
|
+
|
2068
|
+
decode(input: _m0.Reader | Uint8Array, length?: number): DisabledCodecs {
|
2069
|
+
const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
|
2070
|
+
let end = length === undefined ? reader.len : reader.pos + length;
|
2071
|
+
const message = createBaseDisabledCodecs();
|
2072
|
+
while (reader.pos < end) {
|
2073
|
+
const tag = reader.uint32();
|
2074
|
+
switch (tag >>> 3) {
|
2075
|
+
case 1:
|
2076
|
+
message.codecs.push(Codec.decode(reader, reader.uint32()));
|
2077
|
+
break;
|
2078
|
+
default:
|
2079
|
+
reader.skipType(tag & 7);
|
2080
|
+
break;
|
2081
|
+
}
|
2082
|
+
}
|
2083
|
+
return message;
|
2084
|
+
},
|
2085
|
+
|
2086
|
+
fromJSON(object: any): DisabledCodecs {
|
2087
|
+
return {
|
2088
|
+
codecs: Array.isArray(object?.codecs) ? object.codecs.map((e: any) => Codec.fromJSON(e)) : [],
|
2089
|
+
};
|
2090
|
+
},
|
2091
|
+
|
2092
|
+
toJSON(message: DisabledCodecs): unknown {
|
2093
|
+
const obj: any = {};
|
2094
|
+
if (message.codecs) {
|
2095
|
+
obj.codecs = message.codecs.map((e) => (e ? Codec.toJSON(e) : undefined));
|
2096
|
+
} else {
|
2097
|
+
obj.codecs = [];
|
2098
|
+
}
|
2099
|
+
return obj;
|
2100
|
+
},
|
2101
|
+
|
2102
|
+
fromPartial<I extends Exact<DeepPartial<DisabledCodecs>, I>>(object: I): DisabledCodecs {
|
2103
|
+
const message = createBaseDisabledCodecs();
|
2104
|
+
message.codecs = object.codecs?.map((e) => Codec.fromPartial(e)) || [];
|
2105
|
+
return message;
|
2106
|
+
},
|
2107
|
+
};
|
2108
|
+
|
1954
2109
|
function createBaseRTPStats(): RTPStats {
|
1955
2110
|
return {
|
1956
2111
|
startTime: undefined,
|
@@ -1978,7 +2133,9 @@ function createBaseRTPStats(): RTPStats {
|
|
1978
2133
|
jitterMax: 0,
|
1979
2134
|
gapHistogram: {},
|
1980
2135
|
nacks: 0,
|
2136
|
+
nackAcks: 0,
|
1981
2137
|
nackMisses: 0,
|
2138
|
+
nackRepeated: 0,
|
1982
2139
|
plis: 0,
|
1983
2140
|
lastPli: undefined,
|
1984
2141
|
firs: 0,
|
@@ -2072,9 +2229,15 @@ export const RTPStats = {
|
|
2072
2229
|
if (message.nacks !== 0) {
|
2073
2230
|
writer.uint32(200).uint32(message.nacks);
|
2074
2231
|
}
|
2232
|
+
if (message.nackAcks !== 0) {
|
2233
|
+
writer.uint32(296).uint32(message.nackAcks);
|
2234
|
+
}
|
2075
2235
|
if (message.nackMisses !== 0) {
|
2076
2236
|
writer.uint32(208).uint32(message.nackMisses);
|
2077
2237
|
}
|
2238
|
+
if (message.nackRepeated !== 0) {
|
2239
|
+
writer.uint32(304).uint32(message.nackRepeated);
|
2240
|
+
}
|
2078
2241
|
if (message.plis !== 0) {
|
2079
2242
|
writer.uint32(216).uint32(message.plis);
|
2080
2243
|
}
|
@@ -2193,9 +2356,15 @@ export const RTPStats = {
|
|
2193
2356
|
case 25:
|
2194
2357
|
message.nacks = reader.uint32();
|
2195
2358
|
break;
|
2359
|
+
case 37:
|
2360
|
+
message.nackAcks = reader.uint32();
|
2361
|
+
break;
|
2196
2362
|
case 26:
|
2197
2363
|
message.nackMisses = reader.uint32();
|
2198
2364
|
break;
|
2365
|
+
case 38:
|
2366
|
+
message.nackRepeated = reader.uint32();
|
2367
|
+
break;
|
2199
2368
|
case 27:
|
2200
2369
|
message.plis = reader.uint32();
|
2201
2370
|
break;
|
@@ -2273,7 +2442,9 @@ export const RTPStats = {
|
|
2273
2442
|
)
|
2274
2443
|
: {},
|
2275
2444
|
nacks: isSet(object.nacks) ? Number(object.nacks) : 0,
|
2445
|
+
nackAcks: isSet(object.nackAcks) ? Number(object.nackAcks) : 0,
|
2276
2446
|
nackMisses: isSet(object.nackMisses) ? Number(object.nackMisses) : 0,
|
2447
|
+
nackRepeated: isSet(object.nackRepeated) ? Number(object.nackRepeated) : 0,
|
2277
2448
|
plis: isSet(object.plis) ? Number(object.plis) : 0,
|
2278
2449
|
lastPli: isSet(object.lastPli) ? fromJsonTimestamp(object.lastPli) : undefined,
|
2279
2450
|
firs: isSet(object.firs) ? Number(object.firs) : 0,
|
@@ -2327,7 +2498,9 @@ export const RTPStats = {
|
|
2327
2498
|
});
|
2328
2499
|
}
|
2329
2500
|
message.nacks !== undefined && (obj.nacks = Math.round(message.nacks));
|
2501
|
+
message.nackAcks !== undefined && (obj.nackAcks = Math.round(message.nackAcks));
|
2330
2502
|
message.nackMisses !== undefined && (obj.nackMisses = Math.round(message.nackMisses));
|
2503
|
+
message.nackRepeated !== undefined && (obj.nackRepeated = Math.round(message.nackRepeated));
|
2331
2504
|
message.plis !== undefined && (obj.plis = Math.round(message.plis));
|
2332
2505
|
message.lastPli !== undefined && (obj.lastPli = message.lastPli.toISOString());
|
2333
2506
|
message.firs !== undefined && (obj.firs = Math.round(message.firs));
|
@@ -2376,7 +2549,9 @@ export const RTPStats = {
|
|
2376
2549
|
return acc;
|
2377
2550
|
}, {});
|
2378
2551
|
message.nacks = object.nacks ?? 0;
|
2552
|
+
message.nackAcks = object.nackAcks ?? 0;
|
2379
2553
|
message.nackMisses = object.nackMisses ?? 0;
|
2554
|
+
message.nackRepeated = object.nackRepeated ?? 0;
|
2380
2555
|
message.plis = object.plis ?? 0;
|
2381
2556
|
message.lastPli = object.lastPli ?? undefined;
|
2382
2557
|
message.firs = object.firs ?? 0;
|
@@ -2480,9 +2655,9 @@ const btoa: (bin: string) => string =
|
|
2480
2655
|
globalThis.btoa || ((bin) => globalThis.Buffer.from(bin, 'binary').toString('base64'));
|
2481
2656
|
function base64FromBytes(arr: Uint8Array): string {
|
2482
2657
|
const bin: string[] = [];
|
2483
|
-
|
2658
|
+
for (const byte of arr) {
|
2484
2659
|
bin.push(String.fromCharCode(byte));
|
2485
|
-
}
|
2660
|
+
}
|
2486
2661
|
return btoa(bin.join(''));
|
2487
2662
|
}
|
2488
2663
|
|
package/src/proto/livekit_rtc.ts
CHANGED
@@ -9,6 +9,7 @@ import {
|
|
9
9
|
ClientConfiguration,
|
10
10
|
TrackInfo,
|
11
11
|
VideoQuality,
|
12
|
+
DisconnectReason,
|
12
13
|
ConnectionQuality,
|
13
14
|
VideoLayer,
|
14
15
|
ParticipantTracks,
|
@@ -19,6 +20,8 @@ import {
|
|
19
20
|
trackSourceToJSON,
|
20
21
|
videoQualityFromJSON,
|
21
22
|
videoQualityToJSON,
|
23
|
+
disconnectReasonFromJSON,
|
24
|
+
disconnectReasonToJSON,
|
22
25
|
connectionQualityFromJSON,
|
23
26
|
connectionQualityToJSON,
|
24
27
|
} from './livekit_models';
|
@@ -283,6 +286,7 @@ export interface LeaveRequest {
|
|
283
286
|
* indicates clients should attempt full-reconnect sequence
|
284
287
|
*/
|
285
288
|
canReconnect: boolean;
|
289
|
+
reason: DisconnectReason;
|
286
290
|
}
|
287
291
|
|
288
292
|
/** message to indicate published video track dimensions are changing */
|
@@ -1836,7 +1840,7 @@ export const UpdateTrackSettings = {
|
|
1836
1840
|
};
|
1837
1841
|
|
1838
1842
|
function createBaseLeaveRequest(): LeaveRequest {
|
1839
|
-
return { canReconnect: false };
|
1843
|
+
return { canReconnect: false, reason: 0 };
|
1840
1844
|
}
|
1841
1845
|
|
1842
1846
|
export const LeaveRequest = {
|
@@ -1844,6 +1848,9 @@ export const LeaveRequest = {
|
|
1844
1848
|
if (message.canReconnect === true) {
|
1845
1849
|
writer.uint32(8).bool(message.canReconnect);
|
1846
1850
|
}
|
1851
|
+
if (message.reason !== 0) {
|
1852
|
+
writer.uint32(16).int32(message.reason);
|
1853
|
+
}
|
1847
1854
|
return writer;
|
1848
1855
|
},
|
1849
1856
|
|
@@ -1857,6 +1864,9 @@ export const LeaveRequest = {
|
|
1857
1864
|
case 1:
|
1858
1865
|
message.canReconnect = reader.bool();
|
1859
1866
|
break;
|
1867
|
+
case 2:
|
1868
|
+
message.reason = reader.int32() as any;
|
1869
|
+
break;
|
1860
1870
|
default:
|
1861
1871
|
reader.skipType(tag & 7);
|
1862
1872
|
break;
|
@@ -1868,18 +1878,21 @@ export const LeaveRequest = {
|
|
1868
1878
|
fromJSON(object: any): LeaveRequest {
|
1869
1879
|
return {
|
1870
1880
|
canReconnect: isSet(object.canReconnect) ? Boolean(object.canReconnect) : false,
|
1881
|
+
reason: isSet(object.reason) ? disconnectReasonFromJSON(object.reason) : 0,
|
1871
1882
|
};
|
1872
1883
|
},
|
1873
1884
|
|
1874
1885
|
toJSON(message: LeaveRequest): unknown {
|
1875
1886
|
const obj: any = {};
|
1876
1887
|
message.canReconnect !== undefined && (obj.canReconnect = message.canReconnect);
|
1888
|
+
message.reason !== undefined && (obj.reason = disconnectReasonToJSON(message.reason));
|
1877
1889
|
return obj;
|
1878
1890
|
},
|
1879
1891
|
|
1880
1892
|
fromPartial<I extends Exact<DeepPartial<LeaveRequest>, I>>(object: I): LeaveRequest {
|
1881
1893
|
const message = createBaseLeaveRequest();
|
1882
1894
|
message.canReconnect = object.canReconnect ?? false;
|
1895
|
+
message.reason = object.reason ?? 0;
|
1883
1896
|
return message;
|
1884
1897
|
},
|
1885
1898
|
};
|
package/src/room/RTCEngine.ts
CHANGED
@@ -7,6 +7,7 @@ import {
|
|
7
7
|
ClientConfiguration,
|
8
8
|
DataPacket,
|
9
9
|
DataPacket_Kind,
|
10
|
+
DisconnectReason,
|
10
11
|
SpeakerInfo,
|
11
12
|
TrackInfo,
|
12
13
|
UserPacket,
|
@@ -276,23 +277,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
276
277
|
this.emit(EngineEvent.MediaTrackAdded, track, ev.stream);
|
277
278
|
};
|
278
279
|
}
|
279
|
-
// data channels
|
280
|
-
this.lossyDC = this.publisher.pc.createDataChannel(lossyDataChannel, {
|
281
|
-
// will drop older packets that arrive
|
282
|
-
ordered: true,
|
283
|
-
maxRetransmits: 0,
|
284
|
-
});
|
285
|
-
this.reliableDC = this.publisher.pc.createDataChannel(reliableDataChannel, {
|
286
|
-
ordered: true,
|
287
|
-
});
|
288
280
|
|
289
|
-
|
290
|
-
this.lossyDC.onmessage = this.handleDataMessage;
|
291
|
-
this.reliableDC.onmessage = this.handleDataMessage;
|
292
|
-
|
293
|
-
// handle datachannel errors
|
294
|
-
this.lossyDC.onerror = this.handleDataError;
|
295
|
-
this.reliableDC.onerror = this.handleDataError;
|
281
|
+
this.createDataChannels();
|
296
282
|
|
297
283
|
// configure signaling client
|
298
284
|
this.client.onAnswer = async (sd) => {
|
@@ -360,12 +346,47 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
360
346
|
this.fullReconnectOnNext = true;
|
361
347
|
this.primaryPC = undefined;
|
362
348
|
} else {
|
363
|
-
this.emit(EngineEvent.Disconnected);
|
349
|
+
this.emit(EngineEvent.Disconnected, leave?.reason);
|
364
350
|
this.close();
|
365
351
|
}
|
352
|
+
log.trace('leave request', { leave });
|
366
353
|
};
|
367
354
|
}
|
368
355
|
|
356
|
+
private createDataChannels() {
|
357
|
+
if (!this.publisher) {
|
358
|
+
return;
|
359
|
+
}
|
360
|
+
|
361
|
+
// clear old data channel callbacks if recreate
|
362
|
+
if (this.lossyDC) {
|
363
|
+
this.lossyDC.onmessage = null;
|
364
|
+
this.lossyDC.onerror = null;
|
365
|
+
}
|
366
|
+
if (this.reliableDC) {
|
367
|
+
this.reliableDC.onmessage = null;
|
368
|
+
this.reliableDC.onerror = null;
|
369
|
+
}
|
370
|
+
|
371
|
+
// create data channels
|
372
|
+
this.lossyDC = this.publisher.pc.createDataChannel(lossyDataChannel, {
|
373
|
+
// will drop older packets that arrive
|
374
|
+
ordered: true,
|
375
|
+
maxRetransmits: 0,
|
376
|
+
});
|
377
|
+
this.reliableDC = this.publisher.pc.createDataChannel(reliableDataChannel, {
|
378
|
+
ordered: true,
|
379
|
+
});
|
380
|
+
|
381
|
+
// also handle messages over the pub channel, for backwards compatibility
|
382
|
+
this.lossyDC.onmessage = this.handleDataMessage;
|
383
|
+
this.reliableDC.onmessage = this.handleDataMessage;
|
384
|
+
|
385
|
+
// handle datachannel errors
|
386
|
+
this.lossyDC.onerror = this.handleDataError;
|
387
|
+
this.reliableDC.onerror = this.handleDataError;
|
388
|
+
}
|
389
|
+
|
369
390
|
private handleDataChannel = async ({ channel }: RTCDataChannelEvent) => {
|
370
391
|
if (!channel) {
|
371
392
|
return;
|
@@ -561,6 +582,12 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
561
582
|
await this.waitForPCConnected();
|
562
583
|
this.client.setReconnected();
|
563
584
|
|
585
|
+
// recreate publish datachannel if it's id is null
|
586
|
+
// (for safari https://bugs.webkit.org/show_bug.cgi?id=184688)
|
587
|
+
if (this.reliableDC?.readyState === 'open' && this.reliableDC.id === null) {
|
588
|
+
this.createDataChannels();
|
589
|
+
}
|
590
|
+
|
564
591
|
// resume success
|
565
592
|
this.emit(EngineEvent.Resumed);
|
566
593
|
}
|
@@ -715,7 +742,7 @@ class SignalReconnectError extends Error {}
|
|
715
742
|
|
716
743
|
export type EngineEventCallbacks = {
|
717
744
|
connected: () => void;
|
718
|
-
disconnected: () => void;
|
745
|
+
disconnected: (reason?: DisconnectReason) => void;
|
719
746
|
resuming: () => void;
|
720
747
|
resumed: () => void;
|
721
748
|
restarting: () => void;
|
package/src/room/Room.ts
CHANGED
@@ -5,6 +5,7 @@ import log from '../logger';
|
|
5
5
|
import { RoomConnectOptions, RoomOptions } from '../options';
|
6
6
|
import {
|
7
7
|
DataPacket_Kind,
|
8
|
+
DisconnectReason,
|
8
9
|
ParticipantInfo,
|
9
10
|
ParticipantInfo_State,
|
10
11
|
ParticipantPermission,
|
@@ -150,8 +151,8 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
150
151
|
this.onTrackAdded(mediaTrack, stream, receiver);
|
151
152
|
},
|
152
153
|
)
|
153
|
-
.on(EngineEvent.Disconnected, () => {
|
154
|
-
this.handleDisconnect();
|
154
|
+
.on(EngineEvent.Disconnected, (reason?: DisconnectReason) => {
|
155
|
+
this.handleDisconnect(this.options.stopLocalTrackOnUnpublish, reason);
|
155
156
|
})
|
156
157
|
.on(EngineEvent.ActiveSpeakersUpdate, this.handleActiveSpeakersUpdate)
|
157
158
|
.on(EngineEvent.DataPacketReceived, this.handleDataPacket)
|
@@ -288,7 +289,17 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
288
289
|
|
289
290
|
// populate remote participants, these should not trigger new events
|
290
291
|
joinResponse.otherParticipants.forEach((info) => {
|
291
|
-
|
292
|
+
if (
|
293
|
+
info.sid !== this.localParticipant.sid &&
|
294
|
+
info.identity !== this.localParticipant.identity
|
295
|
+
) {
|
296
|
+
this.getOrCreateParticipant(info.sid, info);
|
297
|
+
} else {
|
298
|
+
log.warn('received info to create local participant as remote participant', {
|
299
|
+
info,
|
300
|
+
localParticipant: this.localParticipant,
|
301
|
+
});
|
302
|
+
}
|
292
303
|
});
|
293
304
|
|
294
305
|
this.name = joinResponse.room!.name;
|
@@ -347,7 +358,8 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
347
358
|
/**
|
348
359
|
* disconnects the room, emits [[RoomEvent.Disconnected]]
|
349
360
|
*/
|
350
|
-
disconnect = (stopTracks = true) => {
|
361
|
+
disconnect = async (stopTracks = true) => {
|
362
|
+
log.info('disconnect from room', { identity: this.localParticipant.identity });
|
351
363
|
if (this.state === ConnectionState.Connecting) {
|
352
364
|
// try aborting pending connection attempt
|
353
365
|
log.warn('abort connection attempt');
|
@@ -356,14 +368,14 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
356
368
|
}
|
357
369
|
// send leave
|
358
370
|
if (this.engine?.client.isConnected) {
|
359
|
-
this.engine.client.sendLeave();
|
371
|
+
await this.engine.client.sendLeave();
|
360
372
|
}
|
361
373
|
// close engine (also closes client)
|
362
374
|
if (this.engine) {
|
363
375
|
this.engine.close();
|
364
376
|
}
|
365
377
|
|
366
|
-
this.handleDisconnect(stopTracks);
|
378
|
+
this.handleDisconnect(stopTracks, DisconnectReason.CLIENT_INITIATED);
|
367
379
|
/* @ts-ignore */
|
368
380
|
this.engine = undefined;
|
369
381
|
};
|
@@ -541,21 +553,27 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
541
553
|
// at that time, ICE connectivity has not been established so the track is not
|
542
554
|
// technically subscribed.
|
543
555
|
// We'll defer these events until when the room is connected or eventually disconnected.
|
544
|
-
if (this.
|
545
|
-
|
556
|
+
if (this.connectFuture) {
|
557
|
+
this.connectFuture.promise.then(() => {
|
546
558
|
this.onTrackAdded(mediaTrack, stream, receiver);
|
547
|
-
}
|
559
|
+
});
|
548
560
|
return;
|
549
561
|
}
|
550
562
|
if (this.state === ConnectionState.Disconnected) {
|
551
563
|
log.warn('skipping incoming track after Room disconnected');
|
564
|
+
return;
|
552
565
|
}
|
553
566
|
const parts = unpackStreamId(stream.id);
|
554
567
|
const participantId = parts[0];
|
555
568
|
let trackId = parts[1];
|
556
569
|
if (!trackId || trackId === '') trackId = mediaTrack.id;
|
557
570
|
|
571
|
+
if (participantId === this.localParticipant.sid) {
|
572
|
+
log.warn('tried to create RemoteParticipant for local participant');
|
573
|
+
return;
|
574
|
+
}
|
558
575
|
const participant = this.getOrCreateParticipant(participantId);
|
576
|
+
|
559
577
|
let adaptiveStreamSettings: AdaptiveStreamSettings | undefined;
|
560
578
|
if (this.options.adaptiveStream) {
|
561
579
|
if (typeof this.options.adaptiveStream === 'object') {
|
@@ -629,7 +647,10 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
629
647
|
);
|
630
648
|
};
|
631
649
|
|
632
|
-
private handleDisconnect(shouldStopTracks = true) {
|
650
|
+
private handleDisconnect(shouldStopTracks = true, reason?: DisconnectReason) {
|
651
|
+
if (this.state === ConnectionState.Disconnected) {
|
652
|
+
return;
|
653
|
+
}
|
633
654
|
this.participants.forEach((p) => {
|
634
655
|
p.tracks.forEach((pub) => {
|
635
656
|
p.unpublishTrack(pub.trackSid);
|
@@ -645,6 +666,9 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
645
666
|
pub.track?.stop();
|
646
667
|
}
|
647
668
|
});
|
669
|
+
this.localParticipant.tracks.clear();
|
670
|
+
this.localParticipant.videoTracks.clear();
|
671
|
+
this.localParticipant.audioTracks.clear();
|
648
672
|
|
649
673
|
this.participants.clear();
|
650
674
|
this.activeSpeakers = [];
|
@@ -657,7 +681,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
657
681
|
navigator.mediaDevices?.removeEventListener('devicechange', this.handleDeviceChange);
|
658
682
|
}
|
659
683
|
this.setAndEmitConnectionState(ConnectionState.Disconnected);
|
660
|
-
this.emit(RoomEvent.Disconnected);
|
684
|
+
this.emit(RoomEvent.Disconnected, reason);
|
661
685
|
}
|
662
686
|
|
663
687
|
private handleParticipantUpdates = (participantInfos: ParticipantInfo[]) => {
|
@@ -806,18 +830,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
806
830
|
return;
|
807
831
|
}
|
808
832
|
|
809
|
-
pub.
|
810
|
-
participant.emit(
|
811
|
-
ParticipantEvent.TrackSubscriptionPermissionChanged,
|
812
|
-
pub,
|
813
|
-
pub.subscriptionStatus,
|
814
|
-
);
|
815
|
-
this.emitWhenConnected(
|
816
|
-
RoomEvent.TrackSubscriptionPermissionChanged,
|
817
|
-
pub,
|
818
|
-
pub.subscriptionStatus,
|
819
|
-
participant,
|
820
|
-
);
|
833
|
+
pub.setAllowed(update.allowed);
|
821
834
|
};
|
822
835
|
|
823
836
|
private handleDataPacket = (userPacket: UserPacket, kind: DataPacket_Kind) => {
|
@@ -954,7 +967,15 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
954
967
|
participant,
|
955
968
|
);
|
956
969
|
},
|
957
|
-
)
|
970
|
+
)
|
971
|
+
.on(ParticipantEvent.TrackSubscriptionPermissionChanged, (pub, status) => {
|
972
|
+
this.emitWhenConnected(
|
973
|
+
RoomEvent.TrackSubscriptionPermissionChanged,
|
974
|
+
pub,
|
975
|
+
status,
|
976
|
+
participant,
|
977
|
+
);
|
978
|
+
});
|
958
979
|
|
959
980
|
// update info at the end after callbacks have been set up
|
960
981
|
if (info) {
|
@@ -1075,7 +1096,7 @@ export default Room;
|
|
1075
1096
|
export type RoomEventCallbacks = {
|
1076
1097
|
reconnecting: () => void;
|
1077
1098
|
reconnected: () => void;
|
1078
|
-
disconnected: () => void;
|
1099
|
+
disconnected: (reason?: DisconnectReason) => void;
|
1079
1100
|
/** @deprecated stateChanged has been renamed to connectionStateChanged */
|
1080
1101
|
stateChanged: (state: ConnectionState) => void;
|
1081
1102
|
connectionStateChanged: (state: ConnectionState) => void;
|