livekit-client 1.1.8 → 1.2.1
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 +677 -187
- 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/PCTransport.d.ts +9 -0
- package/dist/src/room/PCTransport.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 +3 -3
- package/dist/src/room/participant/LocalParticipant.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/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/PCTransport.ts +39 -0
- package/src/room/RTCEngine.ts +44 -18
- package/src/room/Room.ts +30 -24
- package/src/room/events.ts +7 -0
- package/src/room/participant/LocalParticipant.ts +70 -10
- package/src/room/participant/RemoteParticipant.ts +12 -10
- package/src/room/participant/publishUtils.ts +1 -1
- 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/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/PCTransport.ts
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
import { debounce } from 'ts-debounce';
|
2
2
|
import log from '../logger';
|
3
3
|
|
4
|
+
/** @internal */
|
5
|
+
interface TrackBitrateInfo {
|
6
|
+
sid: string;
|
7
|
+
codec: string;
|
8
|
+
maxbr: number;
|
9
|
+
}
|
10
|
+
|
4
11
|
/** @internal */
|
5
12
|
export default class PCTransport {
|
6
13
|
pc: RTCPeerConnection;
|
@@ -11,6 +18,8 @@ export default class PCTransport {
|
|
11
18
|
|
12
19
|
renegotiate: boolean = false;
|
13
20
|
|
21
|
+
trackBitrates: TrackBitrateInfo[] = [];
|
22
|
+
|
14
23
|
onOffer?: (offer: RTCSessionDescriptionInit) => void;
|
15
24
|
|
16
25
|
constructor(config?: RTCConfiguration) {
|
@@ -78,10 +87,40 @@ export default class PCTransport {
|
|
78
87
|
// actually negotiate
|
79
88
|
log.debug('starting to negotiate');
|
80
89
|
const offer = await this.pc.createOffer(options);
|
90
|
+
|
91
|
+
// mung sdp for codec bitrate setting that can't apply by sendEncoding
|
92
|
+
this.trackBitrates.forEach((trackbr) => {
|
93
|
+
let sdp = offer.sdp ?? '';
|
94
|
+
const sidIndex = sdp.search(new RegExp(`msid.* ${trackbr.sid}`));
|
95
|
+
if (sidIndex < 0) {
|
96
|
+
return;
|
97
|
+
}
|
98
|
+
|
99
|
+
const mlineStart = sdp.substring(0, sidIndex).lastIndexOf('m=');
|
100
|
+
const mlineEnd = sdp.indexOf('m=', sidIndex);
|
101
|
+
const mediaSection = sdp.substring(mlineStart, mlineEnd);
|
102
|
+
|
103
|
+
const mungedMediaSection = mediaSection.replace(
|
104
|
+
new RegExp(`a=rtpmap:(\\d+) ${trackbr.codec}/\\d+`, 'i'),
|
105
|
+
`$&\r\na=fmtp:$1 x-google-max-bitrate=${trackbr.maxbr}`,
|
106
|
+
);
|
107
|
+
sdp = sdp.substring(0, mlineStart) + mungedMediaSection + sdp.substring(mlineEnd);
|
108
|
+
offer.sdp = sdp;
|
109
|
+
});
|
110
|
+
this.trackBitrates = [];
|
111
|
+
|
81
112
|
await this.pc.setLocalDescription(offer);
|
82
113
|
this.onOffer(offer);
|
83
114
|
}
|
84
115
|
|
116
|
+
setTrackCodecBitrate(sid: string, codec: string, maxbr: number) {
|
117
|
+
this.trackBitrates.push({
|
118
|
+
sid,
|
119
|
+
codec,
|
120
|
+
maxbr,
|
121
|
+
});
|
122
|
+
}
|
123
|
+
|
85
124
|
close() {
|
86
125
|
this.pc.close();
|
87
126
|
}
|
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,13 +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
|
}
|
366
352
|
log.trace('leave request', { leave });
|
367
353
|
};
|
368
354
|
}
|
369
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
|
+
|
370
390
|
private handleDataChannel = async ({ channel }: RTCDataChannelEvent) => {
|
371
391
|
if (!channel) {
|
372
392
|
return;
|
@@ -562,6 +582,12 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
562
582
|
await this.waitForPCConnected();
|
563
583
|
this.client.setReconnected();
|
564
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
|
+
|
565
591
|
// resume success
|
566
592
|
this.emit(EngineEvent.Resumed);
|
567
593
|
}
|
@@ -716,7 +742,7 @@ class SignalReconnectError extends Error {}
|
|
716
742
|
|
717
743
|
export type EngineEventCallbacks = {
|
718
744
|
connected: () => void;
|
719
|
-
disconnected: () => void;
|
745
|
+
disconnected: (reason?: DisconnectReason) => void;
|
720
746
|
resuming: () => void;
|
721
747
|
resumed: () => void;
|
722
748
|
restarting: () => void;
|