@fishjam-cloud/webrtc-client 0.25.2 → 0.25.3

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 (85) hide show
  1. package/package.json +3 -3
  2. package/dist/protobufs/fishjam/media_events/peer/peer.d.ts +0 -130
  3. package/dist/protobufs/fishjam/media_events/peer/peer.js +0 -1283
  4. package/dist/protobufs/fishjam/media_events/server/server.d.ts +0 -197
  5. package/dist/protobufs/fishjam/media_events/server/server.js +0 -2121
  6. package/dist/protobufs/fishjam/media_events/shared.d.ts +0 -48
  7. package/dist/protobufs/fishjam/media_events/shared.js +0 -315
  8. package/dist/webrtc-client/src/CommandsQueue.d.ts +0 -23
  9. package/dist/webrtc-client/src/CommandsQueue.js +0 -87
  10. package/dist/webrtc-client/src/ConnectionManager.d.ts +0 -17
  11. package/dist/webrtc-client/src/ConnectionManager.js +0 -49
  12. package/dist/webrtc-client/src/bitrate.d.ts +0 -12
  13. package/dist/webrtc-client/src/bitrate.js +0 -15
  14. package/dist/webrtc-client/src/dataChannels/DataChannel.d.ts +0 -56
  15. package/dist/webrtc-client/src/dataChannels/DataChannel.js +0 -144
  16. package/dist/webrtc-client/src/dataChannels/DataChannelManager.d.ts +0 -83
  17. package/dist/webrtc-client/src/dataChannels/DataChannelManager.js +0 -184
  18. package/dist/webrtc-client/src/deferred.d.ts +0 -8
  19. package/dist/webrtc-client/src/deferred.js +0 -17
  20. package/dist/webrtc-client/src/index.d.ts +0 -6
  21. package/dist/webrtc-client/src/index.js +0 -4
  22. package/dist/webrtc-client/src/internal.d.ts +0 -27
  23. package/dist/webrtc-client/src/internal.js +0 -18
  24. package/dist/webrtc-client/src/logger.d.ts +0 -5
  25. package/dist/webrtc-client/src/logger.js +0 -15
  26. package/dist/webrtc-client/src/mediaEvent.d.ts +0 -13
  27. package/dist/webrtc-client/src/mediaEvent.js +0 -20
  28. package/dist/webrtc-client/src/tracks/Local.d.ts +0 -49
  29. package/dist/webrtc-client/src/tracks/Local.js +0 -243
  30. package/dist/webrtc-client/src/tracks/LocalTrack.d.ts +0 -61
  31. package/dist/webrtc-client/src/tracks/LocalTrack.js +0 -212
  32. package/dist/webrtc-client/src/tracks/LocalTrackManager.d.ts +0 -39
  33. package/dist/webrtc-client/src/tracks/LocalTrackManager.js +0 -76
  34. package/dist/webrtc-client/src/tracks/Remote.d.ts +0 -32
  35. package/dist/webrtc-client/src/tracks/Remote.js +0 -165
  36. package/dist/webrtc-client/src/tracks/RemoteTrack.d.ts +0 -40
  37. package/dist/webrtc-client/src/tracks/RemoteTrack.js +0 -71
  38. package/dist/webrtc-client/src/tracks/TrackCommon.d.ts +0 -9
  39. package/dist/webrtc-client/src/tracks/TrackCommon.js +0 -1
  40. package/dist/webrtc-client/src/tracks/bandwidth.d.ts +0 -1
  41. package/dist/webrtc-client/src/tracks/bandwidth.js +0 -27
  42. package/dist/webrtc-client/src/tracks/encodings.d.ts +0 -3
  43. package/dist/webrtc-client/src/tracks/encodings.js +0 -11
  44. package/dist/webrtc-client/src/tracks/muteTrackUtils.d.ts +0 -3
  45. package/dist/webrtc-client/src/tracks/muteTrackUtils.js +0 -23
  46. package/dist/webrtc-client/src/tracks/transceivers.d.ts +0 -2
  47. package/dist/webrtc-client/src/tracks/transceivers.js +0 -93
  48. package/dist/webrtc-client/src/types.d.ts +0 -340
  49. package/dist/webrtc-client/src/types.js +0 -1
  50. package/dist/webrtc-client/src/webRTCEndpoint.d.ts +0 -350
  51. package/dist/webrtc-client/src/webRTCEndpoint.js +0 -747
  52. package/dist/webrtc-client/tests/events/bandwidthEstimationEvent.test.d.ts +0 -1
  53. package/dist/webrtc-client/tests/events/bandwidthEstimationEvent.test.js +0 -21
  54. package/dist/webrtc-client/tests/events/connectedEvent.test.d.ts +0 -1
  55. package/dist/webrtc-client/tests/events/connectedEvent.test.js +0 -70
  56. package/dist/webrtc-client/tests/events/encodingSwitchedEvent.test.d.ts +0 -1
  57. package/dist/webrtc-client/tests/events/encodingSwitchedEvent.test.js +0 -60
  58. package/dist/webrtc-client/tests/events/endpointAddedEvent.test.d.ts +0 -1
  59. package/dist/webrtc-client/tests/events/endpointAddedEvent.test.js +0 -57
  60. package/dist/webrtc-client/tests/events/endpointRemovedEvent.test.d.ts +0 -1
  61. package/dist/webrtc-client/tests/events/endpointRemovedEvent.test.js +0 -64
  62. package/dist/webrtc-client/tests/events/endpointUpdatedEvent.test.d.ts +0 -1
  63. package/dist/webrtc-client/tests/events/endpointUpdatedEvent.test.js +0 -78
  64. package/dist/webrtc-client/tests/events/trackAddedEvent.test.d.ts +0 -1
  65. package/dist/webrtc-client/tests/events/trackAddedEvent.test.js +0 -84
  66. package/dist/webrtc-client/tests/events/trackRemovedEvent.test.d.ts +0 -1
  67. package/dist/webrtc-client/tests/events/trackRemovedEvent.test.js +0 -26
  68. package/dist/webrtc-client/tests/events/trackUpdatedEvent.test.d.ts +0 -1
  69. package/dist/webrtc-client/tests/events/trackUpdatedEvent.test.js +0 -77
  70. package/dist/webrtc-client/tests/events/vadNotificationEvent.test.d.ts +0 -1
  71. package/dist/webrtc-client/tests/events/vadNotificationEvent.test.js +0 -42
  72. package/dist/webrtc-client/tests/fixtures.d.ts +0 -27
  73. package/dist/webrtc-client/tests/fixtures.js +0 -172
  74. package/dist/webrtc-client/tests/methods/addTrackMethod.test.d.ts +0 -1
  75. package/dist/webrtc-client/tests/methods/addTrackMethod.test.js +0 -46
  76. package/dist/webrtc-client/tests/methods/cleanUpMethod.test.d.ts +0 -1
  77. package/dist/webrtc-client/tests/methods/cleanUpMethod.test.js +0 -14
  78. package/dist/webrtc-client/tests/methods/connectMethod.test.d.ts +0 -1
  79. package/dist/webrtc-client/tests/methods/connectMethod.test.js +0 -40
  80. package/dist/webrtc-client/tests/methods/disconnectMethod.test.d.ts +0 -1
  81. package/dist/webrtc-client/tests/methods/disconnectMethod.test.js +0 -29
  82. package/dist/webrtc-client/tests/mocks.d.ts +0 -5
  83. package/dist/webrtc-client/tests/mocks.js +0 -80
  84. package/dist/webrtc-client/tests/utils.d.ts +0 -3
  85. package/dist/webrtc-client/tests/utils.js +0 -56
@@ -1,243 +0,0 @@
1
- import { MediaEvent as PeerMediaEvent, MediaEvent_DisableTrackVariant, MediaEvent_EnableTrackVariant, MediaEvent_RenegotiateTracks, MediaEvent_SdpOffer, MediaEvent_TrackBitrates, MediaEvent_UpdateEndpointMetadata, MediaEvent_UpdateTrackMetadata, } from '@fishjam-cloud/protobufs/peer';
2
- import { Variant } from '@fishjam-cloud/protobufs/shared';
3
- import { isTrackKind, TrackContextImpl } from '../internal';
4
- import { LocalTrack } from './LocalTrack';
5
- /**
6
- * This class encapsulates methods related to handling the list of local tracks and local endpoint.
7
- * It stores and mutates part of the client state for this local peer.
8
- * It emits local events for local tracks and endpoints,
9
- * and delegates mutation logic to the appropriate `LocalTrack` objects.
10
- * It's responsible for creating `MidToTrackId` record which is required in `sdpOffer`
11
- */
12
- export class Local {
13
- localTracks = {};
14
- localEndpoint = {
15
- id: '',
16
- type: 'webrtc',
17
- metadata: undefined,
18
- tracks: new Map(),
19
- };
20
- emit;
21
- sendMediaEvent;
22
- connection = null;
23
- constructor(emit, sendMediaEvent) {
24
- this.emit = emit;
25
- this.sendMediaEvent = sendMediaEvent;
26
- }
27
- updateSenders = () => {
28
- Object.values(this.localTracks).forEach((localTrack) => {
29
- localTrack.updateSender();
30
- });
31
- };
32
- updateMLineIds = (midToTrackIds) => {
33
- Object.entries(midToTrackIds).forEach(([mid, trackId]) => {
34
- this.localTracks[trackId]?.setMLineId(mid);
35
- });
36
- };
37
- updateConnection = (connection) => {
38
- this.connection = connection;
39
- Object.values(this.localTracks).forEach((track) => {
40
- track.updateConnection(connection);
41
- });
42
- };
43
- createSdpOfferEvent = (sdpOffer) => {
44
- const trackIdToMetadataJson = this.getTrackIdToMetadataJson();
45
- const trackIdToBitrates = this.getTrackIdToTrackBitrates();
46
- const midToTrackId = this.getMidToTrackId();
47
- return MediaEvent_SdpOffer.create({
48
- sdp: sdpOffer.sdp,
49
- midToTrackId,
50
- trackIdToBitrates,
51
- trackIdToMetadataJson,
52
- });
53
- };
54
- addTrack = (connection, trackId, track, stream, trackMetadata, simulcastConfig, maxBandwidth) => {
55
- const trackContext = new TrackContextImpl(this.localEndpoint, trackId, trackMetadata, simulcastConfig);
56
- trackContext.track = track;
57
- trackContext.stream = stream;
58
- trackContext.maxBandwidth = maxBandwidth;
59
- if (!isTrackKind(track.kind))
60
- throw new Error('Track has no kind');
61
- trackContext.trackKind = track.kind;
62
- this.localEndpoint.tracks.set(trackId, trackContext);
63
- const trackManager = new LocalTrack(connection, trackId, trackContext);
64
- this.localTracks[trackId] = trackManager;
65
- return trackManager;
66
- };
67
- getTrackByMidOrNull = (mid) => {
68
- return Object.values(this.localTracks).find((track) => track.mLineId === mid) ?? null;
69
- };
70
- removeTrack = (trackId) => {
71
- const trackManager = this.localTracks[trackId];
72
- if (!trackManager)
73
- throw new Error(`Cannot find ${trackId}`);
74
- trackManager.removeFromConnection();
75
- const renegotiateTracks = MediaEvent_RenegotiateTracks.create({});
76
- this.sendMediaEvent({ renegotiateTracks });
77
- this.localEndpoint.tracks.delete(trackId);
78
- delete this.localTracks[trackId];
79
- };
80
- replaceTrack = async (webrtc, trackId, newTrack) => {
81
- // TODO add validation to track.kind, you cannot replace video with audio
82
- const trackManager = this.localTracks[trackId];
83
- if (!trackManager)
84
- throw new Error(`Cannot find ${trackId}`);
85
- await trackManager.replaceTrack(newTrack, webrtc);
86
- };
87
- setEndpointMetadata = (metadata) => {
88
- this.localEndpoint.metadata = metadata;
89
- };
90
- getEndpoint = () => {
91
- return this.localEndpoint;
92
- };
93
- setTrackBandwidth = async (trackId, bandwidth) => {
94
- // FIXME: maxBandwidth in TrackContext is not updated
95
- const trackManager = this.localTracks[trackId];
96
- if (!trackManager)
97
- throw new Error(`Cannot find ${trackId}`);
98
- await trackManager.setTrackBandwidth(bandwidth);
99
- const trackBitrates = MediaEvent_TrackBitrates.create({
100
- trackId,
101
- variantBitrates: [{ variant: Variant.VARIANT_UNSPECIFIED, bitrate: bandwidth }],
102
- });
103
- this.sendMediaEvent(PeerMediaEvent.create({ trackBitrates }));
104
- this.emit('localTrackBandwidthSet', {
105
- trackId,
106
- bandwidth,
107
- });
108
- };
109
- getTrackIdToTrack = () => {
110
- const entries = Object.values(this.localTracks).map((track) => [track.id, track.trackContext]);
111
- return new Map(entries);
112
- };
113
- setLocalEndpointId = (endpointId) => {
114
- this.localEndpoint.id = endpointId;
115
- };
116
- setEncodingBandwidth = async (trackId, rid, bandwidth) => {
117
- const trackManager = this.localTracks[trackId];
118
- if (!trackManager)
119
- throw new Error(`Cannot find ${trackId}`);
120
- await trackManager.setEncodingBandwidth(rid, bandwidth);
121
- const bitrates = trackManager.getTrackBitrates();
122
- let variantBitrates = [];
123
- if (typeof bitrates === 'number') {
124
- variantBitrates = [{ variant: Variant.VARIANT_UNSPECIFIED, bitrate: bitrates }];
125
- }
126
- else if (bitrates) {
127
- variantBitrates = Object.entries(bitrates).map(([variant, bitrate]) => ({
128
- variant: Number(variant),
129
- bitrate,
130
- }));
131
- }
132
- const trackBitrates = MediaEvent_TrackBitrates.create({
133
- trackId,
134
- variantBitrates,
135
- });
136
- this.sendMediaEvent(PeerMediaEvent.create({ trackBitrates }));
137
- this.emit('localTrackEncodingBandwidthSet', {
138
- trackId,
139
- rid,
140
- bandwidth,
141
- });
142
- };
143
- updateEndpointMetadata = (metadata) => {
144
- this.localEndpoint.metadata = metadata;
145
- const updateEndpointMetadata = MediaEvent_UpdateEndpointMetadata.create({
146
- metadataJson: JSON.stringify(this.localEndpoint.metadata),
147
- });
148
- this.sendMediaEvent({ updateEndpointMetadata });
149
- this.emit('localEndpointMetadataChanged', {
150
- metadata: this.localEndpoint.metadata,
151
- });
152
- };
153
- updateLocalTrackMetadata = (trackId, metadata) => {
154
- const trackManager = this.localTracks[trackId];
155
- if (!trackManager)
156
- throw new Error(`Cannot find ${trackId}`);
157
- trackManager.updateTrackMetadata(metadata);
158
- const trackContext = trackManager.trackContext;
159
- const updateTrackMetadata = MediaEvent_UpdateTrackMetadata.create({
160
- trackId,
161
- metadataJson: metadata ? JSON.stringify(metadata) : undefined,
162
- });
163
- switch (trackContext.negotiationStatus) {
164
- case 'done':
165
- this.sendMediaEvent({ updateTrackMetadata });
166
- this.emit('localTrackMetadataChanged', {
167
- trackId,
168
- metadata: trackContext.metadata,
169
- });
170
- break;
171
- case 'offered':
172
- trackContext.pendingMetadataUpdate = true;
173
- break;
174
- case 'awaiting':
175
- // We don't need to do anything
176
- break;
177
- }
178
- };
179
- disableLocalTrackEncoding = async (trackId, encoding) => {
180
- const localTrack = this.localTracks[trackId];
181
- if (!localTrack)
182
- throw new Error(`Track ${trackId} not found`);
183
- await localTrack.disableTrackEncoding(encoding);
184
- const disableTrackVariant = MediaEvent_DisableTrackVariant.create({ trackId, variant: encoding });
185
- this.sendMediaEvent(PeerMediaEvent.create({ disableTrackVariant }));
186
- this.emit('localTrackEncodingEnabled', {
187
- trackId,
188
- encoding,
189
- });
190
- };
191
- enableLocalTrackEncoding = async (trackId, variant) => {
192
- const trackManager = this.localTracks[trackId];
193
- if (!trackManager)
194
- throw new Error(`Cannot find ${trackId}`);
195
- await trackManager.enableTrackEncoding(variant);
196
- const enableTrackVariant = MediaEvent_EnableTrackVariant.create({ trackId, variant });
197
- this.sendMediaEvent(PeerMediaEvent.create({ enableTrackVariant }));
198
- this.emit('localTrackEncodingEnabled', {
199
- trackId,
200
- encoding: variant,
201
- });
202
- };
203
- getTrackIdToMetadataJson = () => Object.values(this.localTracks).reduce((acc, { id, trackContext }) => ({ ...acc, [id]: JSON.stringify(trackContext.metadata) }), {});
204
- // TODO add bitrates
205
- getTrackIdToTrackBitrates = () => Object.values(this.localTracks).reduce((acc, { id }) => ({ ...acc, [id]: { bitrate: 1_500_000 } }), {});
206
- getMidToTrackId = () => {
207
- if (!this.connection)
208
- return {};
209
- // - negotiated unmuted tracks: tracks added in previous negotiation, data is being transmitted
210
- // - not yet negotiated tracks: tracks added in this negotiation, data will be transmitted after successful negotiation
211
- const mappingFromTransceivers = this.getTransceiverMapping();
212
- // - negotiated unmuted tracks: tracks added in previous negotiation, data is being transmitted
213
- // - negotiated muted tracks: tracks added in previous negotiation, data is not being transmitted but can be transmitted in the future
214
- const mappingFromLocalNegotiatedTracks = Object.values(this.localTracks)
215
- .filter((track) => !!track.mLineId)
216
- .reduce((acc, { id, mLineId }) => ({ ...acc, [mLineId]: id }), {});
217
- return { ...mappingFromTransceivers, ...mappingFromLocalNegotiatedTracks };
218
- };
219
- getTransceiverMapping = () => {
220
- if (!this.connection)
221
- return {};
222
- return this.connection
223
- .getConnection()
224
- .getTransceivers()
225
- .filter((transceiver) => Boolean(transceiver.sender.track?.id && transceiver.mid))
226
- .reduce((acc, { sender, mid }) => {
227
- const localTrack = Object.values(this.localTracks).find((track) => track.mediaStreamTrackId === sender.track.id);
228
- if (!localTrack)
229
- throw new Error('Local track not found');
230
- return { ...acc, [mid]: localTrack.id };
231
- }, {});
232
- };
233
- setLocalTrackStatusToOffered = () => {
234
- Object.values(this.localTracks).forEach((localTrack) => {
235
- localTrack.trackContext.negotiationStatus = 'offered';
236
- });
237
- };
238
- addAllTracksToConnection = () => {
239
- Object.values(this.localTracks).forEach((localTrack) => {
240
- localTrack.addTrackToConnection();
241
- });
242
- };
243
- }
@@ -1,61 +0,0 @@
1
- import { Variant } from '@fishjam-cloud/protobufs/shared';
2
- import type { Bitrates } from '../bitrate';
3
- import type { ConnectionManager } from '../ConnectionManager';
4
- import type { TrackContextImpl } from '../internal';
5
- import type { BandwidthLimit, LocalTrackId, MediaStreamTrackId, MLineId } from '../types';
6
- import type { WebRTCEndpoint } from '../webRTCEndpoint';
7
- import type { TrackCommon, TrackEncodings, TrackId } from './TrackCommon';
8
- /**
9
- * This is a wrapper over `TrackContext` that adds additional properties such as:
10
- * - `MLineId`: required to generate sdpOffer
11
- * - `MediaStreamTrackId`: required to generate sdpOffer and match RTCRtpSender
12
- * - `RTCRtpSender`: required to manage RTCPeerConnection track, e.g.:
13
- * - enable/disable encoding
14
- * - remove from connection
15
- * - replace track
16
- * - set track bandwidth
17
- *
18
- * In the future, this object could potentially be merged with `TrackContextImpl`.
19
- *
20
- * # Lifecycle, state transitions
21
- *
22
- * I identified the following states
23
- * - Before creating `Connection` object
24
- * - connection === null
25
- * - sender === null
26
- * - mLineId === null
27
- * - After creating `Connection` object, during `onOfferData` handler
28
- * // TODO: Verify if the track acquires a sender at this point or if it's only for past tracks
29
- * - connection !== null
30
- * - sender !== null
31
- * - mLineId === null
32
- * - After establishing connection, during `onSdpAnswer`, track is being sent
33
- * - connection !== null
34
- * - sender !== null
35
- * - mLineId !== null
36
- */
37
- export declare class LocalTrack implements TrackCommon {
38
- readonly id: TrackId;
39
- mediaStreamTrackId: MediaStreamTrackId | null;
40
- mLineId: MLineId | null;
41
- readonly trackContext: TrackContextImpl;
42
- private sender;
43
- readonly encodings: TrackEncodings;
44
- connection: ConnectionManager | undefined;
45
- constructor(connection: ConnectionManager | undefined, id: LocalTrackId, trackContext: TrackContextImpl);
46
- updateSender: () => void;
47
- updateConnection: (connection: ConnectionManager) => void;
48
- disableTrackEncoding: (encoding: Variant) => Promise<void>;
49
- addTrackToConnection: () => void;
50
- private updateEncodings;
51
- removeFromConnection: () => void;
52
- replaceTrack: (newTrack: MediaStreamTrack | null, webrtc: WebRTCEndpoint) => Promise<void>;
53
- setTrackBandwidth: (bandwidth: BandwidthLimit) => Promise<void>;
54
- setEncodingBandwidth(variant: Variant, bandwidth: BandwidthLimit): Promise<void>;
55
- updateTrackMetadata: (metadata: unknown) => void;
56
- enableTrackEncoding: (encoding: Variant) => Promise<void>;
57
- setMLineId: (mLineId: MLineId) => void;
58
- private isNotSimulcastTrack;
59
- getTrackBitrates: () => Bitrates | undefined;
60
- createTrackVariantBitratesEvent: () => void;
61
- }
@@ -1,212 +0,0 @@
1
- import { Variant } from '@fishjam-cloud/protobufs/shared';
2
- import { defaultBitrates, defaultSimulcastBitrates, UNLIMITED_BANDWIDTH } from '../bitrate';
3
- import { encodingToVariantMap, getEncodingParameters } from './encodings';
4
- import { emitMutableEvents, getActionType } from './muteTrackUtils';
5
- import { createTransceiverConfig } from './transceivers';
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
- [Variant.UNRECOGNIZED]: false,
43
- [Variant.VARIANT_UNSPECIFIED]: false,
44
- [Variant.VARIANT_LOW]: false,
45
- [Variant.VARIANT_MEDIUM]: false,
46
- [Variant.VARIANT_HIGH]: false,
47
- };
48
- connection;
49
- constructor(connection, id, trackContext) {
50
- this.connection = connection;
51
- this.id = id;
52
- this.trackContext = trackContext;
53
- // todo maybe we could remove this object and use sender.getParameters().encodings.encodingParameter.active instead
54
- if (trackContext.track?.id) {
55
- this.mediaStreamTrackId = trackContext.track?.id;
56
- }
57
- }
58
- updateSender = () => {
59
- if (this.mediaStreamTrackId && this.connection) {
60
- this.sender = this.connection.findSender(this.mediaStreamTrackId);
61
- }
62
- };
63
- updateConnection = (connection) => {
64
- this.connection = connection;
65
- };
66
- disableTrackEncoding = async (encoding) => {
67
- if (!this.sender)
68
- throw new Error(`RTCRtpSender for track ${this.id} not found`);
69
- const params = this.sender.getParameters();
70
- const encodings = params.encodings;
71
- const encodingParameter = encodings.find((en) => en.rid && encodingToVariantMap[en.rid] === encoding);
72
- if (!encodingParameter)
73
- throw new Error(`RTCRtpEncodingParameters for track ${this.id} not found`);
74
- encodingParameter.active = false;
75
- this.encodings[encoding] = false;
76
- await this.sender.setParameters(params);
77
- };
78
- addTrackToConnection = () => {
79
- if (!this.trackContext.track)
80
- throw Error(`MediaStreamTrack for track ${this.id} does not exist`);
81
- if (!this.connection)
82
- throw new Error(`There is no active RTCPeerConnection`);
83
- const transceiverConfig = createTransceiverConfig(this.trackContext);
84
- this.updateEncodings();
85
- this.connection.addTransceiver(this.trackContext.track, transceiverConfig);
86
- };
87
- updateEncodings = () => {
88
- const enabledVariants = this.trackContext.simulcastConfig?.enabledVariants;
89
- if (this.trackContext?.track?.kind === 'video' && enabledVariants) {
90
- this.encodings[Variant.VARIANT_LOW] = enabledVariants.some((e) => e === Variant.VARIANT_LOW);
91
- this.encodings[Variant.VARIANT_MEDIUM] = enabledVariants.some((e) => e === Variant.VARIANT_MEDIUM);
92
- this.encodings[Variant.VARIANT_HIGH] = enabledVariants.some((e) => e === Variant.VARIANT_HIGH);
93
- }
94
- };
95
- removeFromConnection = () => {
96
- if (!this.sender)
97
- throw new Error(`RTCRtpSender for track ${this.id} not found`);
98
- if (!this.connection)
99
- throw new Error(`There is no active RTCPeerConnection`);
100
- this.connection.removeTrack(this.sender);
101
- };
102
- replaceTrack = async (newTrack, webrtc) => {
103
- const trackId = this.id;
104
- const stream = this.trackContext.stream;
105
- const oldTrack = this.trackContext.track;
106
- if (!this.sender)
107
- throw Error('There is no RTCRtpSender for this track id!');
108
- stream?.getTracks().forEach((track) => {
109
- stream?.removeTrack(track);
110
- });
111
- if (newTrack) {
112
- stream?.addTrack(newTrack);
113
- }
114
- const action = getActionType(this.trackContext.track, newTrack);
115
- this.trackContext.track = newTrack;
116
- this.mediaStreamTrackId = newTrack?.id ?? null;
117
- if (action === 'mute' || action === 'unmute') {
118
- emitMutableEvents(action, webrtc, trackId);
119
- }
120
- try {
121
- await this.sender.replaceTrack(newTrack);
122
- }
123
- catch (_error) {
124
- // rollback: emit opposite events and revert internal state
125
- if (action === 'mute') {
126
- emitMutableEvents('unmute', webrtc, trackId);
127
- }
128
- else if (action === 'unmute') {
129
- emitMutableEvents('mute', webrtc, trackId);
130
- }
131
- this.trackContext.track = oldTrack;
132
- this.mediaStreamTrackId = oldTrack?.id ?? null;
133
- }
134
- };
135
- setTrackBandwidth = (bandwidth) => {
136
- if (!this.sender)
137
- throw new Error(`RTCRtpSender for track ${this.id} not found`);
138
- const parameters = this.sender.getParameters();
139
- parameters.encodings = getEncodingParameters(parameters, bandwidth);
140
- return this.sender.setParameters(parameters);
141
- };
142
- setEncodingBandwidth(variant, bandwidth) {
143
- if (!this.sender)
144
- throw new Error(`RTCRtpSender for track ${this.id} not found`);
145
- const parameters = this.sender.getParameters();
146
- const encoding = parameters.encodings.find((enc) => enc.rid && encodingToVariantMap[enc.rid] === variant);
147
- if (!encoding) {
148
- return Promise.reject(`Encoding with Variant '${variant}' doesn't exist`);
149
- }
150
- else if (bandwidth === 0) {
151
- delete encoding.maxBitrate;
152
- }
153
- else {
154
- encoding.maxBitrate = bandwidth * 1024;
155
- }
156
- return this.sender.setParameters(parameters);
157
- }
158
- updateTrackMetadata = (metadata) => {
159
- this.trackContext.metadata = metadata;
160
- };
161
- enableTrackEncoding = (encoding) => {
162
- if (!this.sender)
163
- throw new Error(`RTCRtpSender for track ${this.id} not found`);
164
- const params = this.sender.getParameters();
165
- const encodingParameters = params.encodings.find((en) => en.rid && encodingToVariantMap[en.rid] === encoding);
166
- if (!encodingParameters)
167
- throw new Error(`RTCRtEncodingParameters ${encoding} for track ${this.id} not found`);
168
- encodingParameters.active = true;
169
- this.encodings[encoding] = true;
170
- return this.sender.setParameters(params);
171
- };
172
- setMLineId = (mLineId) => {
173
- this.mLineId = mLineId;
174
- };
175
- isNotSimulcastTrack = (encodings) => encodings.length === 1 && !encodings[0].rid;
176
- getTrackBitrates = () => {
177
- const trackContext = this.trackContext;
178
- const kind = this.trackContext.track?.kind;
179
- if (!trackContext.track) {
180
- if (!trackContext.trackKind) {
181
- throw new Error('trackContext.trackKind is empty');
182
- }
183
- return defaultBitrates[trackContext.trackKind];
184
- }
185
- if (!this.sender)
186
- return undefined;
187
- const encodings = this.sender.getParameters().encodings;
188
- if (this.isNotSimulcastTrack(encodings)) {
189
- return encodings[0].maxBitrate || (kind ? defaultBitrates[kind] : UNLIMITED_BANDWIDTH);
190
- }
191
- else if (kind === 'audio') {
192
- throw 'Audio track cannot have multiple encodings';
193
- }
194
- return encodings
195
- .filter((encoding) => encoding.rid)
196
- .reduce((acc, encoding) => {
197
- const variant = encodingToVariantMap[encoding.rid] ?? Variant.VARIANT_UNSPECIFIED;
198
- acc[variant] = encoding.maxBitrate || defaultSimulcastBitrates[variant];
199
- return acc;
200
- }, {});
201
- };
202
- createTrackVariantBitratesEvent = () => {
203
- // TODO implement this when simulcast is supported
204
- // return generateCustomEvent({
205
- // type: 'trackVariantBitrates',
206
- // data: {
207
- // trackId: this.id,
208
- // variantBitrates: this.getTrackBitrates(),
209
- // },
210
- // });
211
- };
212
- }
@@ -1,39 +0,0 @@
1
- import { type MediaEvent as PeerMediaEvent } from '@fishjam-cloud/protobufs/peer';
2
- import type { SimulcastConfig } from '..';
3
- import type { ConnectionManager } from '../ConnectionManager';
4
- import type { TrackBandwidthLimit } from '../types';
5
- import type { WebRTCEndpoint } from '../webRTCEndpoint';
6
- import type { Local } from './Local';
7
- /**
8
- * This class is responsible for handling asynchronous operations related to track management.
9
- * It contains methods and state associated with handling a single operation
10
- * (adding, removing, and replacing a track).
11
- * It facilitates the preparation of events that will later be handled by the `CommandsQueue`.
12
- * It informs the `CommandsQueue` whether the previous task has been completed
13
- *
14
- * Adding and removing tracks requires renegotiation.
15
- *
16
- * Replacing a track relies on `ongoingTrackReplacement`, which probably could be removed
17
- * and replaced with a Promise, because it does not require renegotiation.
18
- */
19
- export declare class LocalTrackManager {
20
- connection?: ConnectionManager;
21
- private readonly local;
22
- ongoingTrackReplacement: boolean;
23
- /**
24
- * Indicates if an ongoing renegotiation is active.
25
- * During renegotiation, both parties are expected to actively exchange events: renegotiateTracks, offerData, sdpOffer, sdpAnswer.
26
- */
27
- ongoingRenegotiation: boolean;
28
- private readonly sendMediaEvent;
29
- constructor(local: Local, sendMediaEvent: (mediaEvent: PeerMediaEvent) => void);
30
- isNegotiationInProgress: () => boolean;
31
- cleanUp: () => void;
32
- parseAddTrack: (track: MediaStreamTrack, simulcastConfig: SimulcastConfig, maxBandwidth: TrackBandwidthLimit) => void;
33
- addTrackHandler: (trackId: string, track: MediaStreamTrack, stream: MediaStream, trackMetadata: unknown | undefined, simulcastConfig: SimulcastConfig, maxBandwidth: TrackBandwidthLimit) => void;
34
- removeTrackHandler: (trackId: string) => void;
35
- replaceTrackHandler: (webrtc: WebRTCEndpoint, trackId: string, newTrack: MediaStreamTrack | null) => Promise<void>;
36
- getEndpointId: () => string;
37
- updateConnection: (connection: ConnectionManager) => void;
38
- updateSenders: () => void;
39
- }
@@ -1,76 +0,0 @@
1
- import { MediaEvent_RenegotiateTracks } from '@fishjam-cloud/protobufs/peer';
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
- this.sendMediaEvent({ renegotiateTracks: MediaEvent_RenegotiateTracks.create() });
53
- };
54
- removeTrackHandler = (trackId) => {
55
- if (!this.connection)
56
- throw new Error(`There is no active RTCPeerConnection`);
57
- this.ongoingRenegotiation = true;
58
- this.local.removeTrack(trackId);
59
- };
60
- replaceTrackHandler = async (webrtc, trackId, newTrack) => {
61
- this.ongoingTrackReplacement = true;
62
- try {
63
- await this.local.replaceTrack(webrtc, trackId, newTrack);
64
- }
65
- finally {
66
- this.ongoingTrackReplacement = false;
67
- }
68
- };
69
- getEndpointId = () => this.local.getEndpoint().id;
70
- updateConnection = (connection) => {
71
- this.connection = connection;
72
- };
73
- updateSenders = () => {
74
- this.local.updateSenders();
75
- };
76
- }
@@ -1,32 +0,0 @@
1
- import type { MediaEvent as PeerMediaEvent } from '@fishjam-cloud/protobufs/peer';
2
- import type { MediaEvent_Track } from '@fishjam-cloud/protobufs/server';
3
- import { MediaEvent_VadNotification_Status } from '@fishjam-cloud/protobufs/server';
4
- import type { Variant } from '@fishjam-cloud/protobufs/shared';
5
- import type { EndpointWithTrackContext } from '../internal';
6
- import type { EncodingReason, MetadataJson, RemoteTrackId, TrackContext, WebRTCEndpointEvents } from '../types';
7
- import { RemoteTrack } from './RemoteTrack';
8
- import type { EndpointId, TrackId } from './TrackCommon';
9
- export declare class Remote {
10
- private readonly remoteTracks;
11
- private readonly remoteEndpoints;
12
- private readonly emit;
13
- private readonly sendMediaEvent;
14
- constructor(emit: <E extends keyof Required<WebRTCEndpointEvents>>(event: E, ...args: Parameters<Required<WebRTCEndpointEvents>[E]>) => void, sendMediaEvent: (mediaEvent: PeerMediaEvent) => void);
15
- getTrackByMid: (mid: string) => RemoteTrack;
16
- addTracks: (endpointId: EndpointId, tracks: Record<TrackId, MediaEvent_Track>) => void;
17
- removeTracks: (trackIds: TrackId[]) => void;
18
- private removeRemoteTrack;
19
- addRemoteEndpoint: (endpointId: string, metadataJson?: MetadataJson, tracks?: Record<RemoteTrackId, MediaEvent_Track>, sendNotification?: boolean) => void;
20
- private addEndpoint;
21
- updateRemoteEndpoint: (endpointId: string, metadataJson?: MetadataJson) => void;
22
- removeRemoteEndpoint: (endpointId: EndpointId) => void;
23
- updateRemoteTrack: (endpointId: string, trackId: string, metadataJson?: MetadataJson) => void;
24
- disableRemoteTrackEncoding: (trackId: TrackId, encoding: Variant) => void;
25
- enableRemoteTrackEncoding: (trackId: TrackId, encoding: Variant) => void;
26
- setRemoteTrackEncoding: (trackId: TrackId, encoding: Variant, reason?: EncodingReason) => void;
27
- setRemoteTrackVadStatus: (trackId: TrackId, vadStatus: MediaEvent_VadNotification_Status) => void;
28
- getRemoteTrackContexts: () => Record<string, TrackContext>;
29
- getRemoteEndpoints: () => Record<string, EndpointWithTrackContext>;
30
- setTargetRemoteTrackEncoding: (trackId: TrackId, variant: Variant) => void;
31
- updateMLineIds: (midToTrackIds: Record<string, string>) => void;
32
- }