@fishjam-cloud/ts-client 0.8.1 → 0.10.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.
Files changed (57) hide show
  1. package/dist/index.d.mts +1308 -0
  2. package/dist/index.mjs +1 -0
  3. package/package.json +23 -33
  4. package/dist/src/FishjamClient.d.ts +0 -511
  5. package/dist/src/FishjamClient.js +0 -669
  6. package/dist/src/auth.d.ts +0 -3
  7. package/dist/src/auth.js +0 -8
  8. package/dist/src/connectEventsHandler.d.ts +0 -2
  9. package/dist/src/connectEventsHandler.js +0 -22
  10. package/dist/src/index.d.ts +0 -7
  11. package/dist/src/index.js +0 -3
  12. package/dist/src/protos/fishjam/peer_notifications.d.ts +0 -51
  13. package/dist/src/protos/fishjam/peer_notifications.js +0 -309
  14. package/dist/src/protos/index.d.ts +0 -1
  15. package/dist/src/protos/index.js +0 -1
  16. package/dist/src/reconnection.d.ts +0 -27
  17. package/dist/src/reconnection.js +0 -119
  18. package/dist/src/webrtc/CommandsQueue.d.ts +0 -23
  19. package/dist/src/webrtc/CommandsQueue.js +0 -87
  20. package/dist/src/webrtc/ConnectionManager.d.ts +0 -27
  21. package/dist/src/webrtc/ConnectionManager.js +0 -65
  22. package/dist/src/webrtc/bitrate.d.ts +0 -12
  23. package/dist/src/webrtc/bitrate.js +0 -12
  24. package/dist/src/webrtc/deferred.d.ts +0 -8
  25. package/dist/src/webrtc/deferred.js +0 -17
  26. package/dist/src/webrtc/index.d.ts +0 -3
  27. package/dist/src/webrtc/index.js +0 -1
  28. package/dist/src/webrtc/internal.d.ts +0 -26
  29. package/dist/src/webrtc/internal.js +0 -34
  30. package/dist/src/webrtc/mediaEvent.d.ts +0 -10
  31. package/dist/src/webrtc/mediaEvent.js +0 -16
  32. package/dist/src/webrtc/tracks/Local.d.ts +0 -50
  33. package/dist/src/webrtc/tracks/Local.js +0 -280
  34. package/dist/src/webrtc/tracks/LocalTrack.d.ts +0 -62
  35. package/dist/src/webrtc/tracks/LocalTrack.js +0 -225
  36. package/dist/src/webrtc/tracks/LocalTrackManager.d.ts +0 -38
  37. package/dist/src/webrtc/tracks/LocalTrackManager.js +0 -77
  38. package/dist/src/webrtc/tracks/Remote.d.ts +0 -38
  39. package/dist/src/webrtc/tracks/Remote.js +0 -200
  40. package/dist/src/webrtc/tracks/RemoteTrack.d.ts +0 -39
  41. package/dist/src/webrtc/tracks/RemoteTrack.js +0 -64
  42. package/dist/src/webrtc/tracks/TrackCommon.d.ts +0 -8
  43. package/dist/src/webrtc/tracks/TrackCommon.js +0 -1
  44. package/dist/src/webrtc/tracks/bandwidth.d.ts +0 -1
  45. package/dist/src/webrtc/tracks/bandwidth.js +0 -27
  46. package/dist/src/webrtc/tracks/encodings.d.ts +0 -1
  47. package/dist/src/webrtc/tracks/encodings.js +0 -5
  48. package/dist/src/webrtc/tracks/muteTrackUtils.d.ts +0 -3
  49. package/dist/src/webrtc/tracks/muteTrackUtils.js +0 -19
  50. package/dist/src/webrtc/tracks/transceivers.d.ts +0 -2
  51. package/dist/src/webrtc/tracks/transceivers.js +0 -91
  52. package/dist/src/webrtc/types.d.ts +0 -314
  53. package/dist/src/webrtc/types.js +0 -2
  54. package/dist/src/webrtc/voiceActivityDetection.d.ts +0 -2
  55. package/dist/src/webrtc/voiceActivityDetection.js +0 -2
  56. package/dist/src/webrtc/webRTCEndpoint.d.ts +0 -297
  57. package/dist/src/webrtc/webRTCEndpoint.js +0 -686
@@ -1,225 +0,0 @@
1
- import { generateCustomEvent } from '../mediaEvent';
2
- import { defaultBitrates, defaultSimulcastBitrates, UNLIMITED_BANDWIDTH } from '../bitrate';
3
- import { getEncodingParameters } from './encodings';
4
- import { createTransceiverConfig } from './transceivers';
5
- import { emitMutableEvents, getActionType } from './muteTrackUtils';
6
- /**
7
- * This is a wrapper over `TrackContext` that adds additional properties such as:
8
- * - `MLineId`: required to generate sdpOffer
9
- * - `MediaStreamTrackId`: required to generate sdpOffer and match RTCRtpSender
10
- * - `RTCRtpSender`: required to manage RTCPeerConnection track, e.g.:
11
- * - enable/disable encoding
12
- * - remove from connection
13
- * - replace track
14
- * - set track bandwidth
15
- *
16
- * In the future, this object could potentially be merged with `TrackContextImpl`.
17
- *
18
- * # Lifecycle, state transitions
19
- *
20
- * I identified the following states
21
- * - Before creating `Connection` object
22
- * - connection === null
23
- * - sender === null
24
- * - mLineId === null
25
- * - After creating `Connection` object, during `onOfferData` handler
26
- * // TODO: Verify if the track acquires a sender at this point or if it's only for past tracks
27
- * - connection !== null
28
- * - sender !== null
29
- * - mLineId === null
30
- * - After establishing connection, during `onSdpAnswer`, track is being sent
31
- * - connection !== null
32
- * - sender !== null
33
- * - mLineId !== null
34
- */
35
- export class LocalTrack {
36
- id;
37
- mediaStreamTrackId = null;
38
- mLineId = null;
39
- trackContext;
40
- sender = null;
41
- encodings;
42
- metadataParser;
43
- connection;
44
- constructor(connection, id, trackContext, metadataParser) {
45
- this.connection = connection;
46
- this.id = id;
47
- this.trackContext = trackContext;
48
- // todo maybe we could remove this object and use sender.getParameters().encodings.encodingParameter.active instead
49
- this.encodings = { h: true, m: true, l: true };
50
- if (trackContext.track?.id) {
51
- this.mediaStreamTrackId = trackContext.track?.id;
52
- }
53
- this.metadataParser = metadataParser;
54
- }
55
- updateSender = () => {
56
- if (this.mediaStreamTrackId && this.connection) {
57
- this.sender = this.connection.findSender(this.mediaStreamTrackId);
58
- }
59
- };
60
- updateConnection = (connection) => {
61
- this.connection = connection;
62
- };
63
- disableTrackEncoding = async (encoding) => {
64
- if (!this.sender)
65
- throw new Error(`RTCRtpSender for track ${this.id} not found`);
66
- const params = this.sender.getParameters();
67
- const encodings = params.encodings;
68
- const encodingParameter = encodings.find((en) => en.rid == encoding);
69
- if (!encodingParameter)
70
- throw new Error(`RTCRtpEncodingParameters for track ${this.id} not found`);
71
- encodingParameter.active = false;
72
- this.encodings[encoding] = false;
73
- await this.sender.setParameters(params);
74
- };
75
- addTrackToConnection = () => {
76
- if (!this.trackContext.track)
77
- throw Error(`MediaStreamTrack for track ${this.id} does not exist`);
78
- if (!this.connection)
79
- throw new Error(`There is no active RTCPeerConnection`);
80
- const transceiverConfig = createTransceiverConfig(this.trackContext);
81
- this.updateEncodings();
82
- this.connection.addTransceiver(this.trackContext.track, transceiverConfig);
83
- };
84
- // 1
85
- updateEncodings = () => {
86
- if (this.trackContext?.track?.kind === 'video' && this.trackContext.simulcastConfig?.activeEncodings) {
87
- const activeEncodings = this.trackContext.simulcastConfig.activeEncodings;
88
- this.encodings.l = activeEncodings.some((e) => e === 'l');
89
- this.encodings.m = activeEncodings.some((e) => e === 'm');
90
- this.encodings.h = activeEncodings.some((e) => e === 'h');
91
- }
92
- };
93
- removeFromConnection = () => {
94
- if (!this.sender)
95
- throw new Error(`RTCRtpSender for track ${this.id} not found`);
96
- if (!this.connection)
97
- throw new Error(`There is no active RTCPeerConnection`);
98
- this.connection.removeTrack(this.sender);
99
- };
100
- replaceTrack = async (newTrack, webrtc) => {
101
- const trackId = this.id;
102
- const stream = this.trackContext.stream;
103
- const oldTrack = this.trackContext.track;
104
- if (!this.sender)
105
- throw Error('There is no RTCRtpSender for this track id!');
106
- stream?.getTracks().forEach((track) => {
107
- stream?.removeTrack(track);
108
- });
109
- if (newTrack) {
110
- stream?.addTrack(newTrack);
111
- }
112
- this.trackContext.track = newTrack;
113
- this.mediaStreamTrackId = newTrack?.id ?? null;
114
- const action = getActionType(this.trackContext.track, newTrack);
115
- if (action === 'mute' || action === 'unmute') {
116
- emitMutableEvents(action, webrtc, trackId);
117
- }
118
- try {
119
- await this.sender.replaceTrack(newTrack);
120
- }
121
- catch (_error) {
122
- // rollback: emit opposite events and revert internal state
123
- if (action === 'mute') {
124
- emitMutableEvents('unmute', webrtc, trackId);
125
- }
126
- else if (action === 'unmute') {
127
- emitMutableEvents('mute', webrtc, trackId);
128
- }
129
- this.trackContext.track = oldTrack;
130
- this.mediaStreamTrackId = oldTrack?.id ?? null;
131
- }
132
- };
133
- setTrackBandwidth = (bandwidth) => {
134
- if (!this.sender)
135
- throw new Error(`RTCRtpSender for track ${this.id} not found`);
136
- const parameters = this.sender.getParameters();
137
- parameters.encodings = getEncodingParameters(parameters, bandwidth);
138
- return this.sender.setParameters(parameters);
139
- };
140
- setEncodingBandwidth(rid, bandwidth) {
141
- if (!this.sender)
142
- throw new Error(`RTCRtpSender for track ${this.id} not found`);
143
- const parameters = this.sender.getParameters();
144
- const encoding = parameters.encodings.find((encoding) => encoding.rid === rid);
145
- if (!encoding) {
146
- return Promise.reject(`Encoding with rid '${rid}' doesn't exist`);
147
- }
148
- else if (bandwidth === 0) {
149
- delete encoding.maxBitrate;
150
- }
151
- else {
152
- encoding.maxBitrate = bandwidth * 1024;
153
- }
154
- return this.sender.setParameters(parameters);
155
- }
156
- updateTrackMetadata = (metadata) => {
157
- const trackContext = this.trackContext;
158
- try {
159
- trackContext.metadata = this.metadataParser(metadata);
160
- trackContext.rawMetadata = metadata;
161
- trackContext.metadataParsingError = undefined;
162
- }
163
- catch (error) {
164
- trackContext.metadata = undefined;
165
- trackContext.metadataParsingError = error;
166
- throw error;
167
- }
168
- };
169
- enableTrackEncoding = (encoding) => {
170
- if (!this.sender)
171
- throw new Error(`RTCRtpSender for track ${this.id} not found`);
172
- const params = this.sender.getParameters();
173
- const encodingParameters = params.encodings.find((en) => en.rid == encoding);
174
- if (!encodingParameters)
175
- throw new Error(`RTCRtEncodingParameters ${encoding} for track ${this.id} not found`);
176
- encodingParameters.active = true;
177
- this.encodings[encoding] = true;
178
- return this.sender.setParameters(params);
179
- };
180
- getDisabledEncodings = () => {
181
- return Object.entries(this.encodings)
182
- .filter(([_, value]) => !value)
183
- .map(([encoding]) => encoding)
184
- .reduce((acc, encoding) => [...acc, encoding], []);
185
- };
186
- setMLineId = (mLineId) => {
187
- this.mLineId = mLineId;
188
- };
189
- isNotSimulcastTrack = (encodings) => encodings.length === 1 && !encodings[0].rid;
190
- getTrackBitrates = () => {
191
- const trackContext = this.trackContext;
192
- const kind = this.trackContext.track?.kind;
193
- if (!trackContext.track) {
194
- if (!trackContext.trackKind) {
195
- throw new Error('trackContext.trackKind is empty');
196
- }
197
- return defaultBitrates[trackContext.trackKind];
198
- }
199
- if (!this.sender)
200
- throw new Error(`RTCRtpSender for track ${this.id} not found`);
201
- const encodings = this.sender.getParameters().encodings;
202
- if (this.isNotSimulcastTrack(encodings)) {
203
- return encodings[0].maxBitrate || (kind ? defaultBitrates[kind] : UNLIMITED_BANDWIDTH);
204
- }
205
- else if (kind === 'audio') {
206
- throw 'Audio track cannot have multiple encodings';
207
- }
208
- return encodings
209
- .filter((encoding) => encoding.rid)
210
- .reduce((acc, encoding) => {
211
- const rid = encoding.rid;
212
- acc[rid] = encoding.maxBitrate || defaultSimulcastBitrates[rid];
213
- return acc;
214
- }, {});
215
- };
216
- createTrackVariantBitratesEvent = () => {
217
- return generateCustomEvent({
218
- type: 'trackVariantBitrates',
219
- data: {
220
- trackId: this.id,
221
- variantBitrates: this.getTrackBitrates(),
222
- },
223
- });
224
- };
225
- }
@@ -1,38 +0,0 @@
1
- import type { SimulcastConfig, TrackBandwidthLimit } from '../types';
2
- import { type MediaEvent } from '../mediaEvent';
3
- import type { ConnectionManager } from '../ConnectionManager';
4
- import type { Local } from './Local';
5
- import type { WebRTCEndpoint } from '../webRTCEndpoint';
6
- /**
7
- * This class is responsible for handling asynchronous operations related to track management.
8
- * It contains methods and state associated with handling a single operation
9
- * (adding, removing, and replacing a track).
10
- * It facilitates the preparation of events that will later be handled by the `CommandsQueue`.
11
- * It informs the `CommandsQueue` whether the previous task has been completed
12
- *
13
- * Adding and removing tracks requires renegotiation.
14
- *
15
- * Replacing a track relies on `ongoingTrackReplacement`, which probably could be removed
16
- * and replaced with a Promise, because it does not require renegotiation.
17
- */
18
- export declare class LocalTrackManager<EndpointMetadata, TrackMetadata> {
19
- connection?: ConnectionManager;
20
- private readonly local;
21
- ongoingTrackReplacement: boolean;
22
- /**
23
- * Indicates if an ongoing renegotiation is active.
24
- * During renegotiation, both parties are expected to actively exchange events: renegotiateTracks, offerData, sdpOffer, sdpAnswer.
25
- */
26
- ongoingRenegotiation: boolean;
27
- private readonly sendMediaEvent;
28
- constructor(local: Local<EndpointMetadata, TrackMetadata>, sendMediaEvent: (mediaEvent: MediaEvent) => void);
29
- isNegotiationInProgress: () => boolean;
30
- cleanUp: () => void;
31
- parseAddTrack: (track: MediaStreamTrack, simulcastConfig: SimulcastConfig, maxBandwidth: TrackBandwidthLimit) => void;
32
- addTrackHandler: (trackId: string, track: MediaStreamTrack, stream: MediaStream, trackMetadata: TrackMetadata | undefined, simulcastConfig: SimulcastConfig, maxBandwidth: TrackBandwidthLimit) => void;
33
- removeTrackHandler: (trackId: string) => void;
34
- replaceTrackHandler: (webrtc: WebRTCEndpoint<EndpointMetadata, TrackMetadata>, trackId: string, newTrack: MediaStreamTrack | null) => Promise<void>;
35
- getEndpointId: () => string;
36
- updateConnection: (connection: ConnectionManager) => void;
37
- updateSenders: () => void;
38
- }
@@ -1,77 +0,0 @@
1
- import { generateCustomEvent } from '../mediaEvent';
2
- /**
3
- * This class is responsible for handling asynchronous operations related to track management.
4
- * It contains methods and state associated with handling a single operation
5
- * (adding, removing, and replacing a track).
6
- * It facilitates the preparation of events that will later be handled by the `CommandsQueue`.
7
- * It informs the `CommandsQueue` whether the previous task has been completed
8
- *
9
- * Adding and removing tracks requires renegotiation.
10
- *
11
- * Replacing a track relies on `ongoingTrackReplacement`, which probably could be removed
12
- * and replaced with a Promise, because it does not require renegotiation.
13
- */
14
- export class LocalTrackManager {
15
- connection;
16
- local;
17
- ongoingTrackReplacement = false;
18
- /**
19
- * Indicates if an ongoing renegotiation is active.
20
- * During renegotiation, both parties are expected to actively exchange events: renegotiateTracks, offerData, sdpOffer, sdpAnswer.
21
- */
22
- ongoingRenegotiation = false;
23
- sendMediaEvent;
24
- constructor(local, sendMediaEvent) {
25
- this.local = local;
26
- this.sendMediaEvent = sendMediaEvent;
27
- }
28
- isNegotiationInProgress = () => {
29
- return this.ongoingRenegotiation || this.ongoingTrackReplacement;
30
- };
31
- cleanUp = () => {
32
- this.ongoingTrackReplacement = false;
33
- this.ongoingRenegotiation = false;
34
- };
35
- parseAddTrack = (track, simulcastConfig, maxBandwidth) => {
36
- if (this.getEndpointId() === '') {
37
- throw new Error('Cannot add tracks before being accepted by the server');
38
- }
39
- if (!simulcastConfig.enabled && !(typeof maxBandwidth === 'number')) {
40
- throw new Error('Invalid type of `maxBandwidth` argument for a non-simulcast track, expected: number');
41
- }
42
- if (this.connection?.isTrackInUse(track)) {
43
- throw new Error("This track was already added to peerConnection, it can't be added again!");
44
- }
45
- };
46
- addTrackHandler = (trackId, track, stream, trackMetadata, simulcastConfig, maxBandwidth) => {
47
- this.ongoingRenegotiation = true;
48
- const trackManager = this.local.addTrack(this.connection, trackId, track, stream, trackMetadata, simulcastConfig, maxBandwidth);
49
- if (this.connection) {
50
- trackManager.addTrackToConnection();
51
- }
52
- const mediaEvent = generateCustomEvent({ type: 'renegotiateTracks' });
53
- this.sendMediaEvent(mediaEvent);
54
- };
55
- removeTrackHandler = (trackId) => {
56
- if (!this.connection)
57
- throw new Error(`There is no active RTCPeerConnection`);
58
- this.ongoingRenegotiation = true;
59
- this.local.removeTrack(trackId);
60
- };
61
- replaceTrackHandler = async (webrtc, trackId, newTrack) => {
62
- this.ongoingTrackReplacement = true;
63
- try {
64
- await this.local.replaceTrack(webrtc, trackId, newTrack);
65
- }
66
- finally {
67
- this.ongoingTrackReplacement = false;
68
- }
69
- };
70
- getEndpointId = () => this.local.getEndpoint().id;
71
- updateConnection = (connection) => {
72
- this.connection = connection;
73
- };
74
- updateSenders = () => {
75
- this.local.updateSenders();
76
- };
77
- }
@@ -1,38 +0,0 @@
1
- import type { Encoding, EncodingReason, MetadataParser, MLineId, SimulcastConfig, TrackContext, WebRTCEndpointEvents } from '../types';
2
- import { RemoteTrack } from './RemoteTrack';
3
- import type { EndpointWithTrackContext } from '../internal';
4
- import { type MediaEvent } from '../mediaEvent';
5
- import type { EndpointId, TrackId } from './TrackCommon';
6
- type SDPTrack = {
7
- metadata: null;
8
- simulcastConfig: SimulcastConfig;
9
- };
10
- export declare class Remote<EndpointMetadata, TrackMetadata> {
11
- private readonly remoteTracks;
12
- private readonly remoteEndpoints;
13
- private readonly endpointMetadataParser;
14
- private readonly trackMetadataParser;
15
- private readonly emit;
16
- private readonly sendMediaEvent;
17
- constructor(emit: <E extends keyof Required<WebRTCEndpointEvents<EndpointMetadata, TrackMetadata>>>(event: E, ...args: Parameters<Required<WebRTCEndpointEvents<EndpointMetadata, TrackMetadata>>[E]>) => void, sendMediaEvent: (mediaEvent: MediaEvent) => void, endpointMetadataParser: MetadataParser<EndpointMetadata>, trackMetadataParser: MetadataParser<TrackMetadata>);
18
- getTrackByMid: (mid: string) => RemoteTrack<EndpointMetadata, TrackMetadata>;
19
- addTracks: (endpointId: EndpointId, tracks: Record<TrackId, SDPTrack>, trackIdToMetadata: Record<TrackId, any>) => void;
20
- removeTracks: (trackIds: TrackId[]) => void;
21
- removeRemoteTrack: (trackId: TrackId) => void;
22
- addRemoteEndpoint: (endpoint: any, sendNotification?: boolean) => void;
23
- private addEndpoint;
24
- updateRemoteEndpoint: (data: any) => void;
25
- private updateEndpointMetadata;
26
- removeRemoteEndpoint: (endpointId: EndpointId) => void;
27
- updateRemoteTrack: (data: any) => void;
28
- private updateTrackMetadata;
29
- disableRemoteTrackEncoding: (trackId: TrackId, encoding: Encoding) => void;
30
- enableRemoteTrackEncoding: (trackId: TrackId, encoding: Encoding) => void;
31
- setRemoteTrackEncoding: (trackId: TrackId, encoding: Encoding, reason: EncodingReason) => void;
32
- setRemoteTrackVadStatus: (trackId: TrackId, vadStatus: string) => void;
33
- getRemoteTrackContexts: () => Record<string, TrackContext<EndpointMetadata, TrackMetadata>>;
34
- getRemoteEndpoints: () => Record<string, EndpointWithTrackContext<EndpointMetadata, TrackMetadata>>;
35
- setTargetRemoteTrackEncoding: (trackId: TrackId, variant: Encoding) => void;
36
- updateMLineIds: (midToTrackId: Record<MLineId, TrackId>) => void;
37
- }
38
- export {};
@@ -1,200 +0,0 @@
1
- import { RemoteTrack } from './RemoteTrack';
2
- import { TrackContextImpl } from '../internal';
3
- import { isVadStatus } from '../voiceActivityDetection';
4
- import { generateCustomEvent } from '../mediaEvent';
5
- export class Remote {
6
- remoteTracks = {};
7
- remoteEndpoints = {};
8
- endpointMetadataParser;
9
- trackMetadataParser;
10
- emit;
11
- sendMediaEvent;
12
- constructor(emit, sendMediaEvent, endpointMetadataParser, trackMetadataParser) {
13
- this.emit = emit;
14
- this.sendMediaEvent = sendMediaEvent;
15
- this.endpointMetadataParser = endpointMetadataParser;
16
- this.trackMetadataParser = trackMetadataParser;
17
- }
18
- getTrackByMid = (mid) => {
19
- const remoteTrack = Object.values(this.remoteTracks).find((remote) => remote.mLineId === mid);
20
- if (!remoteTrack)
21
- throw new Error(`Remote track with ${mid} not found`);
22
- return remoteTrack;
23
- };
24
- addTracks = (endpointId, tracks, trackIdToMetadata) => {
25
- const endpoint = this.remoteEndpoints[endpointId];
26
- if (!endpoint)
27
- throw new Error(`Endpoint ${endpointId} not found`);
28
- Object.entries(tracks || {})
29
- .map(([trackId, { simulcastConfig }]) => {
30
- const trackContext = new TrackContextImpl(endpoint, trackId, trackIdToMetadata[trackId], simulcastConfig, this.trackMetadataParser);
31
- return new RemoteTrack(trackId, trackContext);
32
- })
33
- .forEach((remoteTrack) => {
34
- this.remoteTracks[remoteTrack.id] = remoteTrack;
35
- endpoint.tracks.set(remoteTrack.id, remoteTrack.trackContext);
36
- this.emit('trackAdded', remoteTrack.trackContext);
37
- });
38
- };
39
- removeTracks = (trackIds) => {
40
- trackIds.forEach((trackId) => {
41
- this.removeRemoteTrack(trackId);
42
- });
43
- };
44
- removeRemoteTrack = (trackId) => {
45
- const remoteTrack = this.remoteTracks[trackId];
46
- if (!remoteTrack)
47
- throw new Error(`Track ${trackId} not found`);
48
- const remoteEndpoint = this.remoteEndpoints[remoteTrack.trackContext.endpoint.id];
49
- if (!remoteEndpoint)
50
- throw new Error(`Endpoint ${remoteTrack.trackContext.endpoint.id} not found`);
51
- remoteEndpoint.tracks.delete(trackId);
52
- delete this.remoteTracks[trackId];
53
- this.emit('trackRemoved', remoteTrack.trackContext);
54
- };
55
- addRemoteEndpoint = (endpoint, sendNotification = true) => {
56
- const newEndpoint = {
57
- id: endpoint.id,
58
- type: endpoint.type,
59
- metadata: { peer: undefined, server: undefined },
60
- rawMetadata: { peer: undefined, server: undefined },
61
- metadataParsingError: undefined,
62
- tracks: new Map(),
63
- };
64
- // mutation in place
65
- this.updateEndpointMetadata(newEndpoint, endpoint?.metadata?.peer);
66
- this.addEndpoint(newEndpoint);
67
- this.addTracks(newEndpoint.id, endpoint.tracks, endpoint.trackIdToMetadata);
68
- if (sendNotification) {
69
- this.emit('endpointAdded', endpoint);
70
- }
71
- };
72
- addEndpoint = (endpoint) => {
73
- this.remoteEndpoints[endpoint.id] = endpoint;
74
- };
75
- updateRemoteEndpoint = (data) => {
76
- const endpoint = this.remoteEndpoints[data.id];
77
- if (!endpoint)
78
- throw new Error(`Endpoint ${data.id} not found`);
79
- // mutation in place
80
- this.updateEndpointMetadata(endpoint, data.metadata.peer);
81
- this.emit('endpointUpdated', endpoint);
82
- };
83
- updateEndpointMetadata = (endpoint, metadata) => {
84
- try {
85
- endpoint.metadata.peer = this.endpointMetadataParser(metadata);
86
- endpoint.metadataParsingError = undefined;
87
- }
88
- catch (error) {
89
- endpoint.metadata.peer = undefined;
90
- endpoint.metadataParsingError = error;
91
- }
92
- endpoint.rawMetadata.peer = metadata;
93
- };
94
- removeRemoteEndpoint = (endpointId) => {
95
- const endpoint = this.remoteEndpoints[endpointId];
96
- if (!endpoint)
97
- throw new Error(`Endpoint ${endpointId} not found`);
98
- const trackIds = [...endpoint.tracks.values()].map(({ trackId }) => trackId);
99
- this.removeTracks(trackIds);
100
- delete this.remoteEndpoints[endpointId];
101
- this.emit('endpointRemoved', endpoint);
102
- };
103
- updateRemoteTrack = (data) => {
104
- const endpointId = data.endpointId;
105
- const endpoint = this.remoteEndpoints[endpointId];
106
- if (!endpoint)
107
- throw new Error(`Endpoint ${endpointId} not found`);
108
- const trackId = data.trackId;
109
- const remoteTrack = this.remoteTracks[trackId];
110
- if (!remoteTrack)
111
- throw new Error(`Track ${trackId} not found`);
112
- this.updateTrackMetadata(remoteTrack.trackContext, data.metadata);
113
- this.emit('trackUpdated', remoteTrack.trackContext);
114
- };
115
- updateTrackMetadata = (trackContext, trackMetadata) => {
116
- try {
117
- trackContext.metadata = this.trackMetadataParser(trackMetadata);
118
- trackContext.metadataParsingError = undefined;
119
- }
120
- catch (error) {
121
- trackContext.metadataParsingError = error;
122
- trackContext.metadata = undefined;
123
- }
124
- trackContext.rawMetadata = trackMetadata;
125
- };
126
- disableRemoteTrackEncoding = (trackId, encoding) => {
127
- const remoteTrack = this.remoteTracks[trackId];
128
- if (!remoteTrack)
129
- throw new Error(`Track ${trackId} not found`);
130
- remoteTrack.disableTrackEncoding(encoding);
131
- this.emit('trackEncodingDisabled', remoteTrack.trackContext, encoding);
132
- };
133
- enableRemoteTrackEncoding = (trackId, encoding) => {
134
- const remoteTrack = this.remoteTracks[trackId];
135
- if (!remoteTrack)
136
- throw new Error(`Track ${trackId} not found`);
137
- remoteTrack.enableTrackEncoding(encoding);
138
- this.emit('trackEncodingEnabled', remoteTrack.trackContext, encoding);
139
- };
140
- setRemoteTrackEncoding = (trackId, encoding, reason) => {
141
- const remoteTrack = this.remoteTracks[trackId];
142
- if (!remoteTrack)
143
- throw new Error(`Track ${trackId} not found`);
144
- remoteTrack.trackContext.encoding = encoding;
145
- remoteTrack.trackContext.encodingReason = reason;
146
- remoteTrack.trackContext.emit('encodingChanged', remoteTrack.trackContext);
147
- };
148
- setRemoteTrackVadStatus = (trackId, vadStatus) => {
149
- const remoteTrack = this.remoteTracks[trackId];
150
- if (!remoteTrack)
151
- throw new Error(`Track ${trackId} not found`);
152
- if (isVadStatus(vadStatus)) {
153
- remoteTrack.trackContext.vadStatus = vadStatus;
154
- remoteTrack.trackContext.emit('voiceActivityChanged', remoteTrack.trackContext);
155
- }
156
- else {
157
- console.warn('Received unknown vad status: ', vadStatus);
158
- }
159
- };
160
- getRemoteTrackContexts = () => {
161
- return Object.values(this.remoteTracks).reduce((acc, current) => ({
162
- ...acc,
163
- [current.trackContext.trackId]: current.trackContext,
164
- }), {});
165
- };
166
- getRemoteEndpoints = () => {
167
- return Object.values(this.remoteEndpoints).reduce((acc, current) => ({ ...acc, [current.id]: current }), {});
168
- };
169
- setTargetRemoteTrackEncoding = (trackId, variant) => {
170
- const remoteTrack = this.remoteTracks[trackId];
171
- if (!remoteTrack)
172
- throw new Error(`Track ${trackId} not found`);
173
- try {
174
- remoteTrack.setTargetTrackEncoding(variant);
175
- const mediaEvent = generateCustomEvent({
176
- type: 'setTargetTrackVariant',
177
- data: {
178
- trackId: trackId,
179
- variant,
180
- },
181
- });
182
- this.sendMediaEvent(mediaEvent);
183
- this.emit('targetTrackEncodingRequested', {
184
- trackId,
185
- variant,
186
- });
187
- }
188
- catch (e) {
189
- console.warn(e);
190
- }
191
- };
192
- updateMLineIds = (midToTrackId) => {
193
- Object.entries(midToTrackId).forEach(([mLineId, trackId]) => {
194
- const remoteTrack = this.remoteTracks[trackId];
195
- if (remoteTrack) {
196
- remoteTrack.setMLineId(mLineId);
197
- }
198
- });
199
- };
200
- }
@@ -1,39 +0,0 @@
1
- import type { TrackCommon, TrackEncodings, TrackId } from './TrackCommon';
2
- import type { LocalTrackId, MLineId, Encoding } from '../types';
3
- import type { TrackContextImpl } from '../internal';
4
- /**
5
- * This is a wrapper over `TrackContext` that adds additional properties such as:
6
- * - `MLineId`: required to generate sdpOffer
7
- *
8
- * # Lifecycle, state transitions
9
- *
10
- * I identified the following states
11
- * - on `trackAdded`
12
- * - trackContext.stream === null
13
- * - trackContext.track === null
14
- * - trackContext.trackKind === null
15
- * - mLineId === null
16
- * - on `onSdpAnswer`
17
- * - trackContext.stream === null
18
- * - trackContext.track === null
19
- * - trackContext.trackKind === null
20
- * - mLineId !== null
21
- * - on `trackReady`
22
- * - trackContext.stream !== null
23
- * - trackContext.track !== null
24
- * - trackContext.trackKind !== null
25
- * - mLineId !== null
26
- */
27
- export declare class RemoteTrack<EndpointMetadata, TrackMetadata> implements TrackCommon {
28
- id: TrackId;
29
- mLineId: MLineId | null;
30
- readonly trackContext: TrackContextImpl<EndpointMetadata, TrackMetadata>;
31
- readonly encodings: TrackEncodings;
32
- private targetEncoding;
33
- constructor(id: LocalTrackId, trackContext: TrackContextImpl<EndpointMetadata, TrackMetadata>);
34
- setMLineId: (mLineId: MLineId) => void;
35
- setReady: (stream: MediaStream, track: MediaStreamTrack) => void;
36
- disableTrackEncoding: (encoding: Encoding) => void;
37
- enableTrackEncoding: (encoding: Encoding) => void;
38
- setTargetTrackEncoding: (variant: Encoding) => void;
39
- }
@@ -1,64 +0,0 @@
1
- import { isTrackKind } from '../internal';
2
- /**
3
- * This is a wrapper over `TrackContext` that adds additional properties such as:
4
- * - `MLineId`: required to generate sdpOffer
5
- *
6
- * # Lifecycle, state transitions
7
- *
8
- * I identified the following states
9
- * - on `trackAdded`
10
- * - trackContext.stream === null
11
- * - trackContext.track === null
12
- * - trackContext.trackKind === null
13
- * - mLineId === null
14
- * - on `onSdpAnswer`
15
- * - trackContext.stream === null
16
- * - trackContext.track === null
17
- * - trackContext.trackKind === null
18
- * - mLineId !== null
19
- * - on `trackReady`
20
- * - trackContext.stream !== null
21
- * - trackContext.track !== null
22
- * - trackContext.trackKind !== null
23
- * - mLineId !== null
24
- */
25
- export class RemoteTrack {
26
- id;
27
- mLineId = null;
28
- trackContext;
29
- encodings = { h: false, m: false, l: false };
30
- // todo this field is not exposed
31
- targetEncoding = null;
32
- constructor(id, trackContext) {
33
- this.id = id;
34
- this.trackContext = trackContext;
35
- }
36
- setMLineId = (mLineId) => {
37
- this.mLineId = mLineId;
38
- };
39
- setReady = (stream, track) => {
40
- if (!isTrackKind(track.kind))
41
- throw new Error('Track has no kind');
42
- this.trackContext.stream = stream;
43
- this.trackContext.track = track;
44
- this.trackContext.trackKind = track.kind;
45
- };
46
- disableTrackEncoding = (encoding) => {
47
- this.encodings[encoding] = false;
48
- };
49
- enableTrackEncoding = (encoding) => {
50
- this.encodings[encoding] = true;
51
- };
52
- setTargetTrackEncoding = (variant) => {
53
- // todo implement validation
54
- this.targetEncoding = variant;
55
- const trackContext = this.trackContext;
56
- if (!trackContext.simulcastConfig?.enabled) {
57
- throw new Error('The track does not support changing its target variant');
58
- }
59
- const isValidTargetEncoding = !trackContext.simulcastConfig.activeEncodings.includes(variant);
60
- if (isValidTargetEncoding) {
61
- throw new Error(`The track does not support variant ${variant}`);
62
- }
63
- };
64
- }