livekit-client 2.0.0 → 2.0.2
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 +8 -0
- package/dist/livekit-client.e2ee.worker.js +1 -1
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs +4 -4
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +122 -39
- 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/proto/livekit_models_pb.d.ts +9 -1
- package/dist/src/proto/livekit_models_pb.d.ts.map +1 -1
- package/dist/src/proto/livekit_rtc_pb.d.ts +38 -0
- package/dist/src/proto/livekit_rtc_pb.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +1 -2
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- 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/track/LocalAudioTrack.d.ts +8 -7
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrack.d.ts +10 -9
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrackPublication.d.ts +2 -2
- package/dist/src/room/track/LocalVideoTrack.d.ts +3 -3
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteAudioTrack.d.ts +2 -1
- package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteTrack.d.ts +2 -2
- package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts +2 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +3 -3
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/room/track/processor/types.d.ts +4 -0
- package/dist/src/room/track/processor/types.d.ts.map +1 -1
- package/dist/ts4.2/src/proto/livekit_models_pb.d.ts +9 -1
- package/dist/ts4.2/src/proto/livekit_rtc_pb.d.ts +38 -0
- package/dist/ts4.2/src/room/PCTransport.d.ts +1 -2
- package/dist/ts4.2/src/room/events.d.ts +8 -1
- package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +8 -7
- package/dist/ts4.2/src/room/track/LocalTrack.d.ts +10 -9
- package/dist/ts4.2/src/room/track/LocalTrackPublication.d.ts +2 -2
- package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +3 -3
- package/dist/ts4.2/src/room/track/RemoteAudioTrack.d.ts +2 -1
- package/dist/ts4.2/src/room/track/RemoteTrack.d.ts +2 -2
- package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +2 -1
- package/dist/ts4.2/src/room/track/Track.d.ts +3 -3
- package/dist/ts4.2/src/room/track/processor/types.d.ts +4 -0
- package/package.json +2 -2
- package/src/api/SignalClient.ts +1 -1
- package/src/e2ee/worker/e2ee.worker.ts +8 -4
- package/src/proto/livekit_models_pb.ts +12 -0
- package/src/proto/livekit_rtc_pb.ts +53 -0
- package/src/room/PCTransport.ts +3 -13
- package/src/room/PCTransportManager.ts +1 -2
- package/src/room/RTCEngine.ts +5 -0
- package/src/room/Room.ts +3 -0
- package/src/room/events.ts +8 -1
- package/src/room/participant/LocalParticipant.ts +0 -1
- package/src/room/track/LocalAudioTrack.ts +8 -11
- package/src/room/track/LocalTrack.ts +36 -23
- package/src/room/track/LocalVideoTrack.ts +3 -3
- package/src/room/track/RemoteAudioTrack.ts +1 -1
- package/src/room/track/RemoteTrack.ts +4 -2
- package/src/room/track/RemoteVideoTrack.ts +1 -1
- package/src/room/track/Track.ts +5 -3
- package/src/room/track/processor/types.ts +4 -0
@@ -84,7 +84,7 @@ onmessage = (ev) => {
|
|
84
84
|
}
|
85
85
|
break;
|
86
86
|
case 'removeTransform':
|
87
|
-
unsetCryptorParticipant(data.trackId);
|
87
|
+
unsetCryptorParticipant(data.trackId, data.participantIdentity);
|
88
88
|
break;
|
89
89
|
case 'updateCodec':
|
90
90
|
getTrackCryptor(data.participantIdentity, data.trackId).setVideoCodec(data.codec);
|
@@ -125,7 +125,9 @@ async function handleRatchetRequest(data: RatchetRequestMessage['data']) {
|
|
125
125
|
}
|
126
126
|
|
127
127
|
function getTrackCryptor(participantIdentity: string, trackId: string) {
|
128
|
-
let cryptor = participantCryptors.find(
|
128
|
+
let cryptor = participantCryptors.find(
|
129
|
+
(c) => c.getParticipantIdentity() === participantIdentity && c.getTrackId() === trackId,
|
130
|
+
);
|
129
131
|
if (!cryptor) {
|
130
132
|
workerLogger.info('creating new cryptor for', { participantIdentity });
|
131
133
|
if (!keyProviderOptions) {
|
@@ -172,8 +174,10 @@ function getSharedKeyHandler() {
|
|
172
174
|
return sharedKeyHandler;
|
173
175
|
}
|
174
176
|
|
175
|
-
function unsetCryptorParticipant(trackId: string) {
|
176
|
-
participantCryptors
|
177
|
+
function unsetCryptorParticipant(trackId: string, participantIdentity: string) {
|
178
|
+
participantCryptors
|
179
|
+
.find((c) => c.getParticipantIdentity() === participantIdentity && c.getTrackId() === trackId)
|
180
|
+
?.unsetParticipant();
|
177
181
|
}
|
178
182
|
|
179
183
|
function setEncryptionEnabled(enable: boolean, participantIdentity: string) {
|
@@ -301,6 +301,16 @@ export enum DisconnectReason {
|
|
301
301
|
* @generated from enum value: JOIN_FAILURE = 7;
|
302
302
|
*/
|
303
303
|
JOIN_FAILURE = 7,
|
304
|
+
|
305
|
+
/**
|
306
|
+
* @generated from enum value: MIGRATION = 8;
|
307
|
+
*/
|
308
|
+
MIGRATION = 8,
|
309
|
+
|
310
|
+
/**
|
311
|
+
* @generated from enum value: SIGNAL_CLOSE = 9;
|
312
|
+
*/
|
313
|
+
SIGNAL_CLOSE = 9,
|
304
314
|
}
|
305
315
|
// Retrieve enum metadata with: proto3.getEnumType(DisconnectReason)
|
306
316
|
proto3.util.setEnumType(DisconnectReason, "livekit.DisconnectReason", [
|
@@ -312,6 +322,8 @@ proto3.util.setEnumType(DisconnectReason, "livekit.DisconnectReason", [
|
|
312
322
|
{ no: 5, name: "ROOM_DELETED" },
|
313
323
|
{ no: 6, name: "STATE_MISMATCH" },
|
314
324
|
{ no: 7, name: "JOIN_FAILURE" },
|
325
|
+
{ no: 8, name: "MIGRATION" },
|
326
|
+
{ no: 9, name: "SIGNAL_CLOSE" },
|
315
327
|
]);
|
316
328
|
|
317
329
|
/**
|
@@ -1208,6 +1208,7 @@ export class LeaveRequest extends Message<LeaveRequest> {
|
|
1208
1208
|
/**
|
1209
1209
|
* sent when server initiates the disconnect due to server-restart
|
1210
1210
|
* indicates clients should attempt full-reconnect sequence
|
1211
|
+
* NOTE: `can_reconnect` obsoleted by `action` starting in protocol version 13
|
1211
1212
|
*
|
1212
1213
|
* @generated from field: bool can_reconnect = 1;
|
1213
1214
|
*/
|
@@ -1218,6 +1219,16 @@ export class LeaveRequest extends Message<LeaveRequest> {
|
|
1218
1219
|
*/
|
1219
1220
|
reason = DisconnectReason.UNKNOWN_REASON;
|
1220
1221
|
|
1222
|
+
/**
|
1223
|
+
* @generated from field: livekit.LeaveRequest.Action action = 3;
|
1224
|
+
*/
|
1225
|
+
action = LeaveRequest_Action.DISCONNECT;
|
1226
|
+
|
1227
|
+
/**
|
1228
|
+
* @generated from field: livekit.RegionSettings regions = 4;
|
1229
|
+
*/
|
1230
|
+
regions?: RegionSettings;
|
1231
|
+
|
1221
1232
|
constructor(data?: PartialMessage<LeaveRequest>) {
|
1222
1233
|
super();
|
1223
1234
|
proto3.util.initPartial(data, this);
|
@@ -1228,6 +1239,8 @@ export class LeaveRequest extends Message<LeaveRequest> {
|
|
1228
1239
|
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
1229
1240
|
{ no: 1, name: "can_reconnect", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
|
1230
1241
|
{ no: 2, name: "reason", kind: "enum", T: proto3.getEnumType(DisconnectReason) },
|
1242
|
+
{ no: 3, name: "action", kind: "enum", T: proto3.getEnumType(LeaveRequest_Action) },
|
1243
|
+
{ no: 4, name: "regions", kind: "message", T: RegionSettings },
|
1231
1244
|
]);
|
1232
1245
|
|
1233
1246
|
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): LeaveRequest {
|
@@ -1247,6 +1260,40 @@ export class LeaveRequest extends Message<LeaveRequest> {
|
|
1247
1260
|
}
|
1248
1261
|
}
|
1249
1262
|
|
1263
|
+
/**
|
1264
|
+
* indicates action clients should take on receiving this message
|
1265
|
+
*
|
1266
|
+
* @generated from enum livekit.LeaveRequest.Action
|
1267
|
+
*/
|
1268
|
+
export enum LeaveRequest_Action {
|
1269
|
+
/**
|
1270
|
+
* should disconnect
|
1271
|
+
*
|
1272
|
+
* @generated from enum value: DISCONNECT = 0;
|
1273
|
+
*/
|
1274
|
+
DISCONNECT = 0,
|
1275
|
+
|
1276
|
+
/**
|
1277
|
+
* should attempt a resume with `reconnect=1` in join URL
|
1278
|
+
*
|
1279
|
+
* @generated from enum value: RESUME = 1;
|
1280
|
+
*/
|
1281
|
+
RESUME = 1,
|
1282
|
+
|
1283
|
+
/**
|
1284
|
+
* should attempt a reconnect, i. e. no `reconnect=1`
|
1285
|
+
*
|
1286
|
+
* @generated from enum value: RECONNECT = 2;
|
1287
|
+
*/
|
1288
|
+
RECONNECT = 2,
|
1289
|
+
}
|
1290
|
+
// Retrieve enum metadata with: proto3.getEnumType(LeaveRequest_Action)
|
1291
|
+
proto3.util.setEnumType(LeaveRequest_Action, "livekit.LeaveRequest.Action", [
|
1292
|
+
{ no: 0, name: "DISCONNECT" },
|
1293
|
+
{ no: 1, name: "RESUME" },
|
1294
|
+
{ no: 2, name: "RECONNECT" },
|
1295
|
+
]);
|
1296
|
+
|
1250
1297
|
/**
|
1251
1298
|
* message to indicate published video track dimensions are changing
|
1252
1299
|
*
|
@@ -1947,6 +1994,11 @@ export class SyncState extends Message<SyncState> {
|
|
1947
1994
|
*/
|
1948
1995
|
offer?: SessionDescription;
|
1949
1996
|
|
1997
|
+
/**
|
1998
|
+
* @generated from field: repeated string track_sids_disabled = 6;
|
1999
|
+
*/
|
2000
|
+
trackSidsDisabled: string[] = [];
|
2001
|
+
|
1950
2002
|
constructor(data?: PartialMessage<SyncState>) {
|
1951
2003
|
super();
|
1952
2004
|
proto3.util.initPartial(data, this);
|
@@ -1960,6 +2012,7 @@ export class SyncState extends Message<SyncState> {
|
|
1960
2012
|
{ no: 3, name: "publish_tracks", kind: "message", T: TrackPublishedResponse, repeated: true },
|
1961
2013
|
{ no: 4, name: "data_channels", kind: "message", T: DataChannelInfo, repeated: true },
|
1962
2014
|
{ no: 5, name: "offer", kind: "message", T: SessionDescription },
|
2015
|
+
{ no: 6, name: "track_sids_disabled", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true },
|
1963
2016
|
]);
|
1964
2017
|
|
1965
2018
|
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): SyncState {
|
package/src/room/PCTransport.ts
CHANGED
@@ -5,7 +5,7 @@ import { debounce } from 'ts-debounce';
|
|
5
5
|
import log, { LoggerNames, getLogger } from '../logger';
|
6
6
|
import { NegotiationError, UnexpectedConnectionState } from './errors';
|
7
7
|
import type { LoggerOptions } from './types';
|
8
|
-
import { ddExtensionURI,
|
8
|
+
import { ddExtensionURI, isSVCCodec } from './utils';
|
9
9
|
|
10
10
|
/** @internal */
|
11
11
|
interface TrackBitrateInfo {
|
@@ -42,8 +42,6 @@ export default class PCTransport extends EventEmitter {
|
|
42
42
|
|
43
43
|
private config?: RTCConfiguration;
|
44
44
|
|
45
|
-
private mediaConstraints: Record<string, unknown>;
|
46
|
-
|
47
45
|
private log = log;
|
48
46
|
|
49
47
|
private loggerOptions: LoggerOptions;
|
@@ -76,24 +74,16 @@ export default class PCTransport extends EventEmitter {
|
|
76
74
|
|
77
75
|
onTrack?: (ev: RTCTrackEvent) => void;
|
78
76
|
|
79
|
-
constructor(
|
80
|
-
config?: RTCConfiguration,
|
81
|
-
mediaConstraints: Record<string, unknown> = {},
|
82
|
-
loggerOptions: LoggerOptions = {},
|
83
|
-
) {
|
77
|
+
constructor(config?: RTCConfiguration, loggerOptions: LoggerOptions = {}) {
|
84
78
|
super();
|
85
79
|
this.log = getLogger(loggerOptions.loggerName ?? LoggerNames.PCTransport);
|
86
80
|
this.loggerOptions = loggerOptions;
|
87
81
|
this.config = config;
|
88
|
-
this.mediaConstraints = mediaConstraints;
|
89
82
|
this._pc = this.createPC();
|
90
83
|
}
|
91
84
|
|
92
85
|
private createPC() {
|
93
|
-
const pc =
|
94
|
-
? // @ts-expect-error chrome allows additional media constraints to be passed into the RTCPeerConnection constructor
|
95
|
-
new RTCPeerConnection(this.config, this.mediaConstraints)
|
96
|
-
: new RTCPeerConnection(this.config);
|
86
|
+
const pc = new RTCPeerConnection(this.config);
|
97
87
|
|
98
88
|
pc.onicecandidate = (ev) => {
|
99
89
|
if (!ev.candidate) return;
|
@@ -71,8 +71,7 @@ export class PCTransportManager {
|
|
71
71
|
|
72
72
|
this.isPublisherConnectionRequired = !subscriberPrimary;
|
73
73
|
this.isSubscriberConnectionRequired = subscriberPrimary;
|
74
|
-
|
75
|
-
this.publisher = new PCTransport(rtcConfig, googConstraints, loggerOptions);
|
74
|
+
this.publisher = new PCTransport(rtcConfig, loggerOptions);
|
76
75
|
this.subscriber = new PCTransport(rtcConfig, loggerOptions);
|
77
76
|
|
78
77
|
this.publisher.onConnectionStateChange = this.updateState;
|
package/src/room/RTCEngine.ts
CHANGED
@@ -1271,11 +1271,15 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
1271
1271
|
*/
|
1272
1272
|
const autoSubscribe = this.signalOpts?.autoSubscribe ?? true;
|
1273
1273
|
const trackSids = new Array<string>();
|
1274
|
+
const trackSidsDisabled = new Array<string>();
|
1274
1275
|
|
1275
1276
|
remoteTracks.forEach((track) => {
|
1276
1277
|
if (track.isDesired !== autoSubscribe) {
|
1277
1278
|
trackSids.push(track.trackSid);
|
1278
1279
|
}
|
1280
|
+
if (!track.isEnabled) {
|
1281
|
+
trackSidsDisabled.push(track.trackSid);
|
1282
|
+
}
|
1279
1283
|
});
|
1280
1284
|
|
1281
1285
|
this.client.sendSyncState(
|
@@ -1299,6 +1303,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
1299
1303
|
}),
|
1300
1304
|
publishTracks: getTrackPublicationInfo(localTracks),
|
1301
1305
|
dataChannels: this.dataChannelsInfo(),
|
1306
|
+
trackSidsDisabled,
|
1302
1307
|
}),
|
1303
1308
|
);
|
1304
1309
|
}
|
package/src/room/Room.ts
CHANGED
@@ -1776,7 +1776,10 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
1776
1776
|
};
|
1777
1777
|
|
1778
1778
|
private onLocalTrackPublished = async (pub: LocalTrackPublication) => {
|
1779
|
+
pub.track?.getProcessor()?.onPublish?.(this);
|
1780
|
+
|
1779
1781
|
this.emit(RoomEvent.LocalTrackPublished, pub, this.localParticipant);
|
1782
|
+
|
1780
1783
|
if (pub.track instanceof LocalAudioTrack) {
|
1781
1784
|
const trackIsSilent = await pub.track.checkForSilence();
|
1782
1785
|
if (trackIsSilent) {
|
package/src/room/events.ts
CHANGED
@@ -27,7 +27,14 @@ export enum RoomEvent {
|
|
27
27
|
|
28
28
|
/**
|
29
29
|
* When disconnected from room. This fires when room.disconnect() is called or
|
30
|
-
* when an unrecoverable connection issue had occured
|
30
|
+
* when an unrecoverable connection issue had occured.
|
31
|
+
*
|
32
|
+
* DisconnectReason can be used to determine why the participant was disconnected. Notable reasons are
|
33
|
+
* - DUPLICATE_IDENTITY: another client with the same identity has joined the room
|
34
|
+
* - PARTICIPANT_REMOVED: participant was removed by RemoveParticipant API
|
35
|
+
* - ROOM_DELETED: the room has ended via DeleteRoom API
|
36
|
+
*
|
37
|
+
* args: ([[DisconnectReason]])
|
31
38
|
*/
|
32
39
|
Disconnected = 'disconnected',
|
33
40
|
|
@@ -6,17 +6,17 @@ import { isWeb, unwrapConstraint } from '../utils';
|
|
6
6
|
import LocalTrack from './LocalTrack';
|
7
7
|
import { Track } from './Track';
|
8
8
|
import type { AudioCaptureOptions } from './options';
|
9
|
-
import type { TrackProcessor } from './processor/types';
|
9
|
+
import type { AudioProcessorOptions, TrackProcessor } from './processor/types';
|
10
10
|
import { constraintsForOptions, detectSilence } from './utils';
|
11
11
|
|
12
|
-
export default class LocalAudioTrack extends LocalTrack {
|
12
|
+
export default class LocalAudioTrack extends LocalTrack<Track.Kind.Audio> {
|
13
13
|
/** @internal */
|
14
14
|
stopOnMute: boolean = false;
|
15
15
|
|
16
|
-
private audioContext?: AudioContext;
|
17
|
-
|
18
16
|
private prevStats?: AudioSenderStats;
|
19
17
|
|
18
|
+
protected processor?: TrackProcessor<Track.Kind.Audio, AudioProcessorOptions> | undefined;
|
19
|
+
|
20
20
|
/**
|
21
21
|
*
|
22
22
|
* @param mediaTrack
|
@@ -48,7 +48,7 @@ export default class LocalAudioTrack extends LocalTrack {
|
|
48
48
|
);
|
49
49
|
}
|
50
50
|
|
51
|
-
async mute(): Promise<
|
51
|
+
async mute(): Promise<typeof this> {
|
52
52
|
const unlock = await this.muteLock.lock();
|
53
53
|
try {
|
54
54
|
// disabled special handling as it will cause BT headsets to switch communication modes
|
@@ -64,7 +64,7 @@ export default class LocalAudioTrack extends LocalTrack {
|
|
64
64
|
}
|
65
65
|
}
|
66
66
|
|
67
|
-
async unmute(): Promise<
|
67
|
+
async unmute(): Promise<typeof this> {
|
68
68
|
const unlock = await this.muteLock.lock();
|
69
69
|
try {
|
70
70
|
const deviceHasChanged =
|
@@ -99,7 +99,7 @@ export default class LocalAudioTrack extends LocalTrack {
|
|
99
99
|
await this.restart(constraints);
|
100
100
|
}
|
101
101
|
|
102
|
-
protected async restart(constraints?: MediaTrackConstraints): Promise<
|
102
|
+
protected async restart(constraints?: MediaTrackConstraints): Promise<typeof this> {
|
103
103
|
const track = await super.restart(constraints);
|
104
104
|
this.checkForSilence();
|
105
105
|
return track;
|
@@ -139,7 +139,7 @@ export default class LocalAudioTrack extends LocalTrack {
|
|
139
139
|
this.prevStats = stats;
|
140
140
|
};
|
141
141
|
|
142
|
-
async setProcessor(processor: TrackProcessor<
|
142
|
+
async setProcessor(processor: TrackProcessor<Track.Kind.Audio, AudioProcessorOptions>) {
|
143
143
|
const unlock = await this.processorLock.lock();
|
144
144
|
try {
|
145
145
|
if (!this.audioContext) {
|
@@ -150,9 +150,6 @@ export default class LocalAudioTrack extends LocalTrack {
|
|
150
150
|
if (this.processor) {
|
151
151
|
await this.stopProcessor();
|
152
152
|
}
|
153
|
-
if (this.kind === 'unknown') {
|
154
|
-
throw TypeError('cannot set processor on track of unknown kind');
|
155
|
-
}
|
156
153
|
|
157
154
|
const processorOptions = {
|
158
155
|
kind: this.kind,
|
@@ -11,7 +11,9 @@ import type { TrackProcessor } from './processor/types';
|
|
11
11
|
|
12
12
|
const defaultDimensionsTimeout = 1000;
|
13
13
|
|
14
|
-
export default abstract class LocalTrack
|
14
|
+
export default abstract class LocalTrack<
|
15
|
+
TrackKind extends Track.Kind = Track.Kind,
|
16
|
+
> extends Track<TrackKind> {
|
15
17
|
/** @internal */
|
16
18
|
sender?: RTCRtpSender;
|
17
19
|
|
@@ -34,10 +36,12 @@ export default abstract class LocalTrack extends Track {
|
|
34
36
|
|
35
37
|
protected processorElement?: HTMLMediaElement;
|
36
38
|
|
37
|
-
protected processor?: TrackProcessor<
|
39
|
+
protected processor?: TrackProcessor<TrackKind, any>;
|
38
40
|
|
39
41
|
protected processorLock: Mutex;
|
40
42
|
|
43
|
+
protected audioContext?: AudioContext;
|
44
|
+
|
41
45
|
/**
|
42
46
|
*
|
43
47
|
* @param mediaTrack
|
@@ -47,7 +51,7 @@ export default abstract class LocalTrack extends Track {
|
|
47
51
|
*/
|
48
52
|
protected constructor(
|
49
53
|
mediaTrack: MediaStreamTrack,
|
50
|
-
kind:
|
54
|
+
kind: TrackKind,
|
51
55
|
constraints?: MediaTrackConstraints,
|
52
56
|
userProvidedTrack = false,
|
53
57
|
loggerOptions?: LoggerOptions,
|
@@ -128,21 +132,28 @@ export default abstract class LocalTrack extends Track {
|
|
128
132
|
this._constraints = newTrack.getConstraints();
|
129
133
|
}
|
130
134
|
let processedTrack: MediaStreamTrack | undefined;
|
131
|
-
if (this.processor && newTrack
|
132
|
-
this.
|
133
|
-
|
134
|
-
|
135
|
-
|
135
|
+
if (this.processor && newTrack) {
|
136
|
+
const unlock = await this.processorLock.lock();
|
137
|
+
try {
|
138
|
+
this.log.debug('restarting processor', this.logContext);
|
139
|
+
if (this.kind === 'unknown') {
|
140
|
+
throw TypeError('cannot set processor on track of unknown kind');
|
141
|
+
}
|
136
142
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
143
|
+
if (this.processorElement) {
|
144
|
+
attachToElement(newTrack, this.processorElement);
|
145
|
+
// ensure the processorElement itself stays muted
|
146
|
+
this.processorElement.muted = true;
|
147
|
+
}
|
148
|
+
await this.processor.restart({
|
149
|
+
track: newTrack,
|
150
|
+
kind: this.kind,
|
151
|
+
element: this.processorElement,
|
152
|
+
});
|
153
|
+
processedTrack = this.processor.processedTrack;
|
154
|
+
} finally {
|
155
|
+
unlock();
|
156
|
+
}
|
146
157
|
}
|
147
158
|
if (this.sender) {
|
148
159
|
await this.sender.replaceTrack(processedTrack ?? newTrack);
|
@@ -200,17 +211,17 @@ export default abstract class LocalTrack extends Track {
|
|
200
211
|
return DeviceManager.getInstance().normalizeDeviceId(kind, deviceId, groupId);
|
201
212
|
}
|
202
213
|
|
203
|
-
async mute()
|
214
|
+
async mute() {
|
204
215
|
this.setTrackMuted(true);
|
205
216
|
return this;
|
206
217
|
}
|
207
218
|
|
208
|
-
async unmute()
|
219
|
+
async unmute() {
|
209
220
|
this.setTrackMuted(false);
|
210
221
|
return this;
|
211
222
|
}
|
212
223
|
|
213
|
-
async replaceTrack(track: MediaStreamTrack, userProvidedTrack = true)
|
224
|
+
async replaceTrack(track: MediaStreamTrack, userProvidedTrack = true) {
|
214
225
|
if (!this.sender) {
|
215
226
|
throw new TrackInvalidError('unable to replace an unpublished track');
|
216
227
|
}
|
@@ -227,7 +238,7 @@ export default abstract class LocalTrack extends Track {
|
|
227
238
|
return this;
|
228
239
|
}
|
229
240
|
|
230
|
-
protected async restart(constraints?: MediaTrackConstraints)
|
241
|
+
protected async restart(constraints?: MediaTrackConstraints) {
|
231
242
|
if (!constraints) {
|
232
243
|
constraints = this._constraints;
|
233
244
|
}
|
@@ -408,7 +419,7 @@ export default abstract class LocalTrack extends Track {
|
|
408
419
|
* @param showProcessedStreamLocally
|
409
420
|
* @returns
|
410
421
|
*/
|
411
|
-
async setProcessor(processor: TrackProcessor<
|
422
|
+
async setProcessor(processor: TrackProcessor<TrackKind>, showProcessedStreamLocally = true) {
|
412
423
|
const unlock = await this.processorLock.lock();
|
413
424
|
try {
|
414
425
|
this.log.debug('setting up processor', this.logContext);
|
@@ -418,7 +429,8 @@ export default abstract class LocalTrack extends Track {
|
|
418
429
|
if (this.kind === 'unknown') {
|
419
430
|
throw TypeError('cannot set processor on track of unknown kind');
|
420
431
|
}
|
421
|
-
this.processorElement =
|
432
|
+
this.processorElement =
|
433
|
+
this.processorElement ?? (document.createElement(this.kind) as HTMLMediaElement);
|
422
434
|
|
423
435
|
attachToElement(this._mediaStreamTrack, this.processorElement);
|
424
436
|
this.processorElement.muted = true;
|
@@ -433,6 +445,7 @@ export default abstract class LocalTrack extends Track {
|
|
433
445
|
kind: this.kind,
|
434
446
|
track: this._mediaStreamTrack,
|
435
447
|
element: this.processorElement,
|
448
|
+
audioContext: this.audioContext,
|
436
449
|
};
|
437
450
|
|
438
451
|
await processor.init(processorOptions);
|
@@ -30,7 +30,7 @@ export class SimulcastTrackInfo {
|
|
30
30
|
|
31
31
|
const refreshSubscribedCodecAfterNewCodec = 5000;
|
32
32
|
|
33
|
-
export default class LocalVideoTrack extends LocalTrack {
|
33
|
+
export default class LocalVideoTrack extends LocalTrack<Track.Kind.Video> {
|
34
34
|
/* @internal */
|
35
35
|
signalClient?: SignalClient;
|
36
36
|
|
@@ -115,7 +115,7 @@ export default class LocalVideoTrack extends LocalTrack {
|
|
115
115
|
}
|
116
116
|
}
|
117
117
|
|
118
|
-
async mute(): Promise<
|
118
|
+
async mute(): Promise<typeof this> {
|
119
119
|
const unlock = await this.muteLock.lock();
|
120
120
|
try {
|
121
121
|
if (this.source === Track.Source.Camera && !this.isUserProvided) {
|
@@ -130,7 +130,7 @@ export default class LocalVideoTrack extends LocalTrack {
|
|
130
130
|
}
|
131
131
|
}
|
132
132
|
|
133
|
-
async unmute(): Promise<
|
133
|
+
async unmute(): Promise<typeof this> {
|
134
134
|
const unlock = await this.muteLock.lock();
|
135
135
|
try {
|
136
136
|
if (this.source === Track.Source.Camera && !this.isUserProvided) {
|
@@ -7,7 +7,7 @@ import RemoteTrack from './RemoteTrack';
|
|
7
7
|
import { Track } from './Track';
|
8
8
|
import type { AudioOutputOptions } from './options';
|
9
9
|
|
10
|
-
export default class RemoteAudioTrack extends RemoteTrack {
|
10
|
+
export default class RemoteAudioTrack extends RemoteTrack<Track.Kind.Audio> {
|
11
11
|
private prevStats?: AudioReceiverStats;
|
12
12
|
|
13
13
|
private elementVolume: number | undefined;
|
@@ -3,14 +3,16 @@ import { monitorFrequency } from '../stats';
|
|
3
3
|
import type { LoggerOptions } from '../types';
|
4
4
|
import { Track } from './Track';
|
5
5
|
|
6
|
-
export default abstract class RemoteTrack
|
6
|
+
export default abstract class RemoteTrack<
|
7
|
+
TrackKind extends Track.Kind = Track.Kind,
|
8
|
+
> extends Track<TrackKind> {
|
7
9
|
/** @internal */
|
8
10
|
receiver?: RTCRtpReceiver;
|
9
11
|
|
10
12
|
constructor(
|
11
13
|
mediaTrack: MediaStreamTrack,
|
12
14
|
sid: string,
|
13
|
-
kind:
|
15
|
+
kind: TrackKind,
|
14
16
|
receiver?: RTCRtpReceiver,
|
15
17
|
loggerOptions?: LoggerOptions,
|
16
18
|
) {
|
@@ -12,7 +12,7 @@ import type { AdaptiveStreamSettings } from './types';
|
|
12
12
|
|
13
13
|
const REACTION_DELAY = 100;
|
14
14
|
|
15
|
-
export default class RemoteVideoTrack extends RemoteTrack {
|
15
|
+
export default class RemoteVideoTrack extends RemoteTrack<Track.Kind.Video> {
|
16
16
|
private prevStats?: VideoReceiverStats;
|
17
17
|
|
18
18
|
private elementInfos: ElementInfo[] = [];
|
package/src/room/track/Track.ts
CHANGED
@@ -24,8 +24,10 @@ export enum VideoQuality {
|
|
24
24
|
MEDIUM = ProtoQuality.MEDIUM,
|
25
25
|
HIGH = ProtoQuality.HIGH,
|
26
26
|
}
|
27
|
-
export abstract class Track
|
28
|
-
|
27
|
+
export abstract class Track<
|
28
|
+
TrackKind extends Track.Kind = Track.Kind,
|
29
|
+
> extends (EventEmitter as new () => TypedEventEmitter<TrackEventCallbacks>) {
|
30
|
+
readonly kind: TrackKind;
|
29
31
|
|
30
32
|
attachedElements: HTMLMediaElement[] = [];
|
31
33
|
|
@@ -67,7 +69,7 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
|
|
67
69
|
|
68
70
|
protected constructor(
|
69
71
|
mediaTrack: MediaStreamTrack,
|
70
|
-
kind:
|
72
|
+
kind: TrackKind,
|
71
73
|
loggerOptions: LoggerOptions = {},
|
72
74
|
) {
|
73
75
|
super();
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import type Room from '../../Room';
|
1
2
|
import type { Track } from '../Track';
|
2
3
|
|
3
4
|
/**
|
@@ -7,6 +8,7 @@ export type ProcessorOptions<T extends Track.Kind> = {
|
|
7
8
|
kind: T;
|
8
9
|
track: MediaStreamTrack;
|
9
10
|
element?: HTMLMediaElement;
|
11
|
+
audioContext?: AudioContext;
|
10
12
|
};
|
11
13
|
|
12
14
|
/**
|
@@ -33,4 +35,6 @@ export interface TrackProcessor<
|
|
33
35
|
restart: (opts: U) => Promise<void>;
|
34
36
|
destroy: () => Promise<void>;
|
35
37
|
processedTrack?: MediaStreamTrack;
|
38
|
+
onPublish?: (room: Room) => Promise<void>;
|
39
|
+
onUnpublish?: () => Promise<void>;
|
36
40
|
}
|