@fishjam-cloud/webrtc-client 0.25.0 → 0.25.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.
Files changed (85) hide show
  1. package/dist/protobufs/fishjam/media_events/peer/peer.d.ts +130 -0
  2. package/dist/protobufs/fishjam/media_events/peer/peer.js +1283 -0
  3. package/dist/protobufs/fishjam/media_events/server/server.d.ts +197 -0
  4. package/dist/protobufs/fishjam/media_events/server/server.js +2121 -0
  5. package/dist/protobufs/fishjam/media_events/shared.d.ts +48 -0
  6. package/dist/protobufs/fishjam/media_events/shared.js +315 -0
  7. package/dist/webrtc-client/src/CommandsQueue.d.ts +23 -0
  8. package/dist/webrtc-client/src/CommandsQueue.js +87 -0
  9. package/dist/webrtc-client/src/ConnectionManager.d.ts +17 -0
  10. package/dist/webrtc-client/src/ConnectionManager.js +49 -0
  11. package/dist/webrtc-client/src/bitrate.d.ts +12 -0
  12. package/dist/webrtc-client/src/bitrate.js +15 -0
  13. package/dist/webrtc-client/src/dataChannels/DataChannel.d.ts +56 -0
  14. package/dist/webrtc-client/src/dataChannels/DataChannel.js +144 -0
  15. package/dist/webrtc-client/src/dataChannels/DataChannelManager.d.ts +83 -0
  16. package/dist/webrtc-client/src/dataChannels/DataChannelManager.js +184 -0
  17. package/dist/webrtc-client/src/deferred.d.ts +8 -0
  18. package/dist/webrtc-client/src/deferred.js +17 -0
  19. package/dist/webrtc-client/src/index.d.ts +6 -0
  20. package/dist/webrtc-client/src/index.js +4 -0
  21. package/dist/webrtc-client/src/internal.d.ts +27 -0
  22. package/dist/webrtc-client/src/internal.js +18 -0
  23. package/dist/webrtc-client/src/logger.d.ts +5 -0
  24. package/dist/webrtc-client/src/logger.js +15 -0
  25. package/dist/webrtc-client/src/mediaEvent.d.ts +13 -0
  26. package/dist/webrtc-client/src/mediaEvent.js +20 -0
  27. package/dist/webrtc-client/src/tracks/Local.d.ts +49 -0
  28. package/dist/webrtc-client/src/tracks/Local.js +243 -0
  29. package/dist/webrtc-client/src/tracks/LocalTrack.d.ts +61 -0
  30. package/dist/webrtc-client/src/tracks/LocalTrack.js +212 -0
  31. package/dist/webrtc-client/src/tracks/LocalTrackManager.d.ts +39 -0
  32. package/dist/webrtc-client/src/tracks/LocalTrackManager.js +76 -0
  33. package/dist/webrtc-client/src/tracks/Remote.d.ts +32 -0
  34. package/dist/webrtc-client/src/tracks/Remote.js +165 -0
  35. package/dist/webrtc-client/src/tracks/RemoteTrack.d.ts +40 -0
  36. package/dist/webrtc-client/src/tracks/RemoteTrack.js +71 -0
  37. package/dist/webrtc-client/src/tracks/TrackCommon.d.ts +9 -0
  38. package/dist/webrtc-client/src/tracks/TrackCommon.js +1 -0
  39. package/dist/webrtc-client/src/tracks/bandwidth.d.ts +1 -0
  40. package/dist/webrtc-client/src/tracks/bandwidth.js +27 -0
  41. package/dist/webrtc-client/src/tracks/encodings.d.ts +3 -0
  42. package/dist/webrtc-client/src/tracks/encodings.js +11 -0
  43. package/dist/webrtc-client/src/tracks/muteTrackUtils.d.ts +3 -0
  44. package/dist/webrtc-client/src/tracks/muteTrackUtils.js +23 -0
  45. package/dist/webrtc-client/src/tracks/transceivers.d.ts +2 -0
  46. package/dist/webrtc-client/src/tracks/transceivers.js +93 -0
  47. package/dist/webrtc-client/src/types.d.ts +340 -0
  48. package/dist/webrtc-client/src/types.js +1 -0
  49. package/dist/webrtc-client/src/webRTCEndpoint.d.ts +350 -0
  50. package/dist/webrtc-client/src/webRTCEndpoint.js +747 -0
  51. package/dist/webrtc-client/tests/events/bandwidthEstimationEvent.test.d.ts +1 -0
  52. package/dist/webrtc-client/tests/events/bandwidthEstimationEvent.test.js +21 -0
  53. package/dist/webrtc-client/tests/events/connectedEvent.test.d.ts +1 -0
  54. package/dist/webrtc-client/tests/events/connectedEvent.test.js +70 -0
  55. package/dist/webrtc-client/tests/events/encodingSwitchedEvent.test.d.ts +1 -0
  56. package/dist/webrtc-client/tests/events/encodingSwitchedEvent.test.js +60 -0
  57. package/dist/webrtc-client/tests/events/endpointAddedEvent.test.d.ts +1 -0
  58. package/dist/webrtc-client/tests/events/endpointAddedEvent.test.js +57 -0
  59. package/dist/webrtc-client/tests/events/endpointRemovedEvent.test.d.ts +1 -0
  60. package/dist/webrtc-client/tests/events/endpointRemovedEvent.test.js +64 -0
  61. package/dist/webrtc-client/tests/events/endpointUpdatedEvent.test.d.ts +1 -0
  62. package/dist/webrtc-client/tests/events/endpointUpdatedEvent.test.js +78 -0
  63. package/dist/webrtc-client/tests/events/trackAddedEvent.test.d.ts +1 -0
  64. package/dist/webrtc-client/tests/events/trackAddedEvent.test.js +84 -0
  65. package/dist/webrtc-client/tests/events/trackRemovedEvent.test.d.ts +1 -0
  66. package/dist/webrtc-client/tests/events/trackRemovedEvent.test.js +26 -0
  67. package/dist/webrtc-client/tests/events/trackUpdatedEvent.test.d.ts +1 -0
  68. package/dist/webrtc-client/tests/events/trackUpdatedEvent.test.js +77 -0
  69. package/dist/webrtc-client/tests/events/vadNotificationEvent.test.d.ts +1 -0
  70. package/dist/webrtc-client/tests/events/vadNotificationEvent.test.js +42 -0
  71. package/dist/webrtc-client/tests/fixtures.d.ts +27 -0
  72. package/dist/webrtc-client/tests/fixtures.js +172 -0
  73. package/dist/webrtc-client/tests/methods/addTrackMethod.test.d.ts +1 -0
  74. package/dist/webrtc-client/tests/methods/addTrackMethod.test.js +46 -0
  75. package/dist/webrtc-client/tests/methods/cleanUpMethod.test.d.ts +1 -0
  76. package/dist/webrtc-client/tests/methods/cleanUpMethod.test.js +14 -0
  77. package/dist/webrtc-client/tests/methods/connectMethod.test.d.ts +1 -0
  78. package/dist/webrtc-client/tests/methods/connectMethod.test.js +40 -0
  79. package/dist/webrtc-client/tests/methods/disconnectMethod.test.d.ts +1 -0
  80. package/dist/webrtc-client/tests/methods/disconnectMethod.test.js +29 -0
  81. package/dist/webrtc-client/tests/mocks.d.ts +5 -0
  82. package/dist/webrtc-client/tests/mocks.js +80 -0
  83. package/dist/webrtc-client/tests/utils.d.ts +3 -0
  84. package/dist/webrtc-client/tests/utils.js +56 -0
  85. package/package.json +3 -3
@@ -0,0 +1,48 @@
1
+ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
2
+ export declare const protobufPackage = "fishjam.media_events";
3
+ export declare enum Variant {
4
+ VARIANT_UNSPECIFIED = 0,
5
+ VARIANT_LOW = 1,
6
+ VARIANT_MEDIUM = 2,
7
+ VARIANT_HIGH = 3,
8
+ UNRECOGNIZED = -1
9
+ }
10
+ export declare function variantFromJSON(object: any): Variant;
11
+ export declare function variantToJSON(object: Variant): string;
12
+ /** Contains information about an ICE candidate which will be sent to the peer/server */
13
+ export interface Candidate {
14
+ candidate: string;
15
+ sdpMLineIndex: number;
16
+ sdpMid: string;
17
+ usernameFragment: string;
18
+ }
19
+ export interface ChannelMessageBinaryPayload {
20
+ data: Uint8Array;
21
+ }
22
+ export interface ChannelMessage {
23
+ source: string;
24
+ destinations: string[];
25
+ binary?: ChannelMessageBinaryPayload | undefined;
26
+ }
27
+ export declare const Candidate: MessageFns<Candidate>;
28
+ export declare const ChannelMessageBinaryPayload: MessageFns<ChannelMessageBinaryPayload>;
29
+ export declare const ChannelMessage: MessageFns<ChannelMessage>;
30
+ type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
31
+ export type DeepPartial<T> = T extends Builtin ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : T extends {} ? {
32
+ [K in keyof T]?: DeepPartial<T[K]>;
33
+ } : Partial<T>;
34
+ type KeysOfUnion<T> = T extends T ? keyof T : never;
35
+ export type Exact<P, I extends P> = P extends Builtin ? P : P & {
36
+ [K in keyof P]: Exact<P[K], I[K]>;
37
+ } & {
38
+ [K in Exclude<keyof I, KeysOfUnion<P>>]: never;
39
+ };
40
+ export interface MessageFns<T> {
41
+ encode(message: T, writer?: BinaryWriter): BinaryWriter;
42
+ decode(input: BinaryReader | Uint8Array, length?: number): T;
43
+ fromJSON(object: any): T;
44
+ toJSON(message: T): unknown;
45
+ create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
46
+ fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
47
+ }
48
+ export {};
@@ -0,0 +1,315 @@
1
+ // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
+ // versions:
3
+ // protoc-gen-ts_proto v2.7.0
4
+ // protoc v6.33.0
5
+ // source: fishjam/media_events/shared.proto
6
+ /* eslint-disable */
7
+ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
8
+ export const protobufPackage = "fishjam.media_events";
9
+ export var Variant;
10
+ (function (Variant) {
11
+ Variant[Variant["VARIANT_UNSPECIFIED"] = 0] = "VARIANT_UNSPECIFIED";
12
+ Variant[Variant["VARIANT_LOW"] = 1] = "VARIANT_LOW";
13
+ Variant[Variant["VARIANT_MEDIUM"] = 2] = "VARIANT_MEDIUM";
14
+ Variant[Variant["VARIANT_HIGH"] = 3] = "VARIANT_HIGH";
15
+ Variant[Variant["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
16
+ })(Variant || (Variant = {}));
17
+ export function variantFromJSON(object) {
18
+ switch (object) {
19
+ case 0:
20
+ case "VARIANT_UNSPECIFIED":
21
+ return Variant.VARIANT_UNSPECIFIED;
22
+ case 1:
23
+ case "VARIANT_LOW":
24
+ return Variant.VARIANT_LOW;
25
+ case 2:
26
+ case "VARIANT_MEDIUM":
27
+ return Variant.VARIANT_MEDIUM;
28
+ case 3:
29
+ case "VARIANT_HIGH":
30
+ return Variant.VARIANT_HIGH;
31
+ case -1:
32
+ case "UNRECOGNIZED":
33
+ default:
34
+ return Variant.UNRECOGNIZED;
35
+ }
36
+ }
37
+ export function variantToJSON(object) {
38
+ switch (object) {
39
+ case Variant.VARIANT_UNSPECIFIED:
40
+ return "VARIANT_UNSPECIFIED";
41
+ case Variant.VARIANT_LOW:
42
+ return "VARIANT_LOW";
43
+ case Variant.VARIANT_MEDIUM:
44
+ return "VARIANT_MEDIUM";
45
+ case Variant.VARIANT_HIGH:
46
+ return "VARIANT_HIGH";
47
+ case Variant.UNRECOGNIZED:
48
+ default:
49
+ return "UNRECOGNIZED";
50
+ }
51
+ }
52
+ function createBaseCandidate() {
53
+ return { candidate: "", sdpMLineIndex: 0, sdpMid: "", usernameFragment: "" };
54
+ }
55
+ export const Candidate = {
56
+ encode(message, writer = new BinaryWriter()) {
57
+ if (message.candidate !== "") {
58
+ writer.uint32(10).string(message.candidate);
59
+ }
60
+ if (message.sdpMLineIndex !== 0) {
61
+ writer.uint32(16).int32(message.sdpMLineIndex);
62
+ }
63
+ if (message.sdpMid !== "") {
64
+ writer.uint32(26).string(message.sdpMid);
65
+ }
66
+ if (message.usernameFragment !== "") {
67
+ writer.uint32(34).string(message.usernameFragment);
68
+ }
69
+ return writer;
70
+ },
71
+ decode(input, length) {
72
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
73
+ let end = length === undefined ? reader.len : reader.pos + length;
74
+ const message = createBaseCandidate();
75
+ while (reader.pos < end) {
76
+ const tag = reader.uint32();
77
+ switch (tag >>> 3) {
78
+ case 1: {
79
+ if (tag !== 10) {
80
+ break;
81
+ }
82
+ message.candidate = reader.string();
83
+ continue;
84
+ }
85
+ case 2: {
86
+ if (tag !== 16) {
87
+ break;
88
+ }
89
+ message.sdpMLineIndex = reader.int32();
90
+ continue;
91
+ }
92
+ case 3: {
93
+ if (tag !== 26) {
94
+ break;
95
+ }
96
+ message.sdpMid = reader.string();
97
+ continue;
98
+ }
99
+ case 4: {
100
+ if (tag !== 34) {
101
+ break;
102
+ }
103
+ message.usernameFragment = reader.string();
104
+ continue;
105
+ }
106
+ }
107
+ if ((tag & 7) === 4 || tag === 0) {
108
+ break;
109
+ }
110
+ reader.skip(tag & 7);
111
+ }
112
+ return message;
113
+ },
114
+ fromJSON(object) {
115
+ return {
116
+ candidate: isSet(object.candidate) ? globalThis.String(object.candidate) : "",
117
+ sdpMLineIndex: isSet(object.sdpMLineIndex) ? globalThis.Number(object.sdpMLineIndex) : 0,
118
+ sdpMid: isSet(object.sdpMid) ? globalThis.String(object.sdpMid) : "",
119
+ usernameFragment: isSet(object.usernameFragment) ? globalThis.String(object.usernameFragment) : "",
120
+ };
121
+ },
122
+ toJSON(message) {
123
+ const obj = {};
124
+ if (message.candidate !== "") {
125
+ obj.candidate = message.candidate;
126
+ }
127
+ if (message.sdpMLineIndex !== 0) {
128
+ obj.sdpMLineIndex = Math.round(message.sdpMLineIndex);
129
+ }
130
+ if (message.sdpMid !== "") {
131
+ obj.sdpMid = message.sdpMid;
132
+ }
133
+ if (message.usernameFragment !== "") {
134
+ obj.usernameFragment = message.usernameFragment;
135
+ }
136
+ return obj;
137
+ },
138
+ create(base) {
139
+ return Candidate.fromPartial(base ?? {});
140
+ },
141
+ fromPartial(object) {
142
+ const message = createBaseCandidate();
143
+ message.candidate = object.candidate ?? "";
144
+ message.sdpMLineIndex = object.sdpMLineIndex ?? 0;
145
+ message.sdpMid = object.sdpMid ?? "";
146
+ message.usernameFragment = object.usernameFragment ?? "";
147
+ return message;
148
+ },
149
+ };
150
+ function createBaseChannelMessageBinaryPayload() {
151
+ return { data: new Uint8Array(0) };
152
+ }
153
+ export const ChannelMessageBinaryPayload = {
154
+ encode(message, writer = new BinaryWriter()) {
155
+ if (message.data.length !== 0) {
156
+ writer.uint32(10).bytes(message.data);
157
+ }
158
+ return writer;
159
+ },
160
+ decode(input, length) {
161
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
162
+ let end = length === undefined ? reader.len : reader.pos + length;
163
+ const message = createBaseChannelMessageBinaryPayload();
164
+ while (reader.pos < end) {
165
+ const tag = reader.uint32();
166
+ switch (tag >>> 3) {
167
+ case 1: {
168
+ if (tag !== 10) {
169
+ break;
170
+ }
171
+ message.data = reader.bytes();
172
+ continue;
173
+ }
174
+ }
175
+ if ((tag & 7) === 4 || tag === 0) {
176
+ break;
177
+ }
178
+ reader.skip(tag & 7);
179
+ }
180
+ return message;
181
+ },
182
+ fromJSON(object) {
183
+ return { data: isSet(object.data) ? bytesFromBase64(object.data) : new Uint8Array(0) };
184
+ },
185
+ toJSON(message) {
186
+ const obj = {};
187
+ if (message.data.length !== 0) {
188
+ obj.data = base64FromBytes(message.data);
189
+ }
190
+ return obj;
191
+ },
192
+ create(base) {
193
+ return ChannelMessageBinaryPayload.fromPartial(base ?? {});
194
+ },
195
+ fromPartial(object) {
196
+ const message = createBaseChannelMessageBinaryPayload();
197
+ message.data = object.data ?? new Uint8Array(0);
198
+ return message;
199
+ },
200
+ };
201
+ function createBaseChannelMessage() {
202
+ return { source: "", destinations: [], binary: undefined };
203
+ }
204
+ export const ChannelMessage = {
205
+ encode(message, writer = new BinaryWriter()) {
206
+ if (message.source !== "") {
207
+ writer.uint32(10).string(message.source);
208
+ }
209
+ for (const v of message.destinations) {
210
+ writer.uint32(18).string(v);
211
+ }
212
+ if (message.binary !== undefined) {
213
+ ChannelMessageBinaryPayload.encode(message.binary, writer.uint32(26).fork()).join();
214
+ }
215
+ return writer;
216
+ },
217
+ decode(input, length) {
218
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
219
+ let end = length === undefined ? reader.len : reader.pos + length;
220
+ const message = createBaseChannelMessage();
221
+ while (reader.pos < end) {
222
+ const tag = reader.uint32();
223
+ switch (tag >>> 3) {
224
+ case 1: {
225
+ if (tag !== 10) {
226
+ break;
227
+ }
228
+ message.source = reader.string();
229
+ continue;
230
+ }
231
+ case 2: {
232
+ if (tag !== 18) {
233
+ break;
234
+ }
235
+ message.destinations.push(reader.string());
236
+ continue;
237
+ }
238
+ case 3: {
239
+ if (tag !== 26) {
240
+ break;
241
+ }
242
+ message.binary = ChannelMessageBinaryPayload.decode(reader, reader.uint32());
243
+ continue;
244
+ }
245
+ }
246
+ if ((tag & 7) === 4 || tag === 0) {
247
+ break;
248
+ }
249
+ reader.skip(tag & 7);
250
+ }
251
+ return message;
252
+ },
253
+ fromJSON(object) {
254
+ return {
255
+ source: isSet(object.source) ? globalThis.String(object.source) : "",
256
+ destinations: globalThis.Array.isArray(object?.destinations)
257
+ ? object.destinations.map((e) => globalThis.String(e))
258
+ : [],
259
+ binary: isSet(object.binary) ? ChannelMessageBinaryPayload.fromJSON(object.binary) : undefined,
260
+ };
261
+ },
262
+ toJSON(message) {
263
+ const obj = {};
264
+ if (message.source !== "") {
265
+ obj.source = message.source;
266
+ }
267
+ if (message.destinations?.length) {
268
+ obj.destinations = message.destinations;
269
+ }
270
+ if (message.binary !== undefined) {
271
+ obj.binary = ChannelMessageBinaryPayload.toJSON(message.binary);
272
+ }
273
+ return obj;
274
+ },
275
+ create(base) {
276
+ return ChannelMessage.fromPartial(base ?? {});
277
+ },
278
+ fromPartial(object) {
279
+ const message = createBaseChannelMessage();
280
+ message.source = object.source ?? "";
281
+ message.destinations = object.destinations?.map((e) => e) || [];
282
+ message.binary = (object.binary !== undefined && object.binary !== null)
283
+ ? ChannelMessageBinaryPayload.fromPartial(object.binary)
284
+ : undefined;
285
+ return message;
286
+ },
287
+ };
288
+ function bytesFromBase64(b64) {
289
+ if (globalThis.Buffer) {
290
+ return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
291
+ }
292
+ else {
293
+ const bin = globalThis.atob(b64);
294
+ const arr = new Uint8Array(bin.length);
295
+ for (let i = 0; i < bin.length; ++i) {
296
+ arr[i] = bin.charCodeAt(i);
297
+ }
298
+ return arr;
299
+ }
300
+ }
301
+ function base64FromBytes(arr) {
302
+ if (globalThis.Buffer) {
303
+ return globalThis.Buffer.from(arr).toString("base64");
304
+ }
305
+ else {
306
+ const bin = [];
307
+ arr.forEach((byte) => {
308
+ bin.push(globalThis.String.fromCharCode(byte));
309
+ });
310
+ return globalThis.btoa(bin.join(""));
311
+ }
312
+ }
313
+ function isSet(value) {
314
+ return value !== null && value !== undefined;
315
+ }
@@ -0,0 +1,23 @@
1
+ import type { ConnectionManager } from './ConnectionManager';
2
+ import type { Deferred } from './deferred';
3
+ import type { LocalTrackManager } from './tracks/LocalTrackManager';
4
+ export type Command = {
5
+ handler: () => Promise<void>;
6
+ parse?: () => void;
7
+ resolutionNotifier: Deferred<void>;
8
+ resolve: 'after-renegotiation' | 'on-handler-resolve';
9
+ };
10
+ export declare class CommandsQueue {
11
+ private readonly localTrackManager;
12
+ private connection;
13
+ private clearConnectionCallbacks;
14
+ constructor(localTrackManager: LocalTrackManager);
15
+ initConnection: (connection: ConnectionManager) => void;
16
+ private commandsQueue;
17
+ private commandResolutionNotifier;
18
+ pushCommand: (command: Command) => void;
19
+ processNextCommand: () => void;
20
+ private handleCommand;
21
+ private resolvePreviousCommand;
22
+ cleanUp: () => void;
23
+ }
@@ -0,0 +1,87 @@
1
+ export class CommandsQueue {
2
+ localTrackManager;
3
+ connection = null;
4
+ clearConnectionCallbacks = null;
5
+ constructor(localTrackManager) {
6
+ this.localTrackManager = localTrackManager;
7
+ }
8
+ initConnection = (connection) => {
9
+ this.connection = connection;
10
+ const onSignalingStateChange = () => {
11
+ if (connection.getConnection().signalingState === 'stable') {
12
+ this.processNextCommand();
13
+ }
14
+ };
15
+ const onIceGatheringStateChange = () => {
16
+ if (connection.getConnection().iceGatheringState === 'complete') {
17
+ this.processNextCommand();
18
+ }
19
+ };
20
+ const onConnectionStateChange = () => {
21
+ if (connection.getConnection().connectionState === 'connected') {
22
+ this.processNextCommand();
23
+ }
24
+ };
25
+ const onIceConnectionStateChange = () => {
26
+ if (connection.getConnection().iceConnectionState === 'connected') {
27
+ this.processNextCommand();
28
+ }
29
+ };
30
+ this.clearConnectionCallbacks = () => {
31
+ connection.getConnection().removeEventListener('signalingstatechange', onSignalingStateChange);
32
+ connection.getConnection().removeEventListener('icegatheringstatechange', onIceGatheringStateChange);
33
+ connection.getConnection().removeEventListener('connectionstatechange', onConnectionStateChange);
34
+ connection.getConnection().removeEventListener('iceconnectionstatechange', onIceConnectionStateChange);
35
+ };
36
+ connection.getConnection().addEventListener('icegatheringstatechange', onIceConnectionStateChange);
37
+ connection.getConnection().addEventListener('connectionstatechange', onConnectionStateChange);
38
+ connection.getConnection().addEventListener('iceconnectionstatechange', onIceConnectionStateChange);
39
+ connection.getConnection().addEventListener('signalingstatechange', onSignalingStateChange);
40
+ };
41
+ commandsQueue = [];
42
+ commandResolutionNotifier = null;
43
+ pushCommand = (command) => {
44
+ this.commandsQueue.push(command);
45
+ this.processNextCommand();
46
+ };
47
+ processNextCommand = () => {
48
+ if (this.localTrackManager.isNegotiationInProgress())
49
+ return;
50
+ if (this.connection?.isConnectionUnstable())
51
+ return;
52
+ this.resolvePreviousCommand();
53
+ const command = this.commandsQueue.shift();
54
+ if (!command)
55
+ return;
56
+ this.commandResolutionNotifier = command.resolutionNotifier;
57
+ this.handleCommand(command);
58
+ };
59
+ handleCommand = async (command) => {
60
+ try {
61
+ command.parse?.();
62
+ const promise = command.handler();
63
+ if (command.resolve === 'on-handler-resolve') {
64
+ await promise;
65
+ this.resolvePreviousCommand();
66
+ this.processNextCommand();
67
+ }
68
+ }
69
+ catch (error) {
70
+ this.commandResolutionNotifier?.reject(error);
71
+ this.commandResolutionNotifier = null;
72
+ this.processNextCommand();
73
+ }
74
+ };
75
+ resolvePreviousCommand = () => {
76
+ if (!this.commandResolutionNotifier)
77
+ return;
78
+ this.commandResolutionNotifier.resolve();
79
+ this.commandResolutionNotifier = null;
80
+ };
81
+ cleanUp = () => {
82
+ this.commandResolutionNotifier?.reject('Disconnected');
83
+ this.commandResolutionNotifier = null;
84
+ this.commandsQueue = [];
85
+ this.clearConnectionCallbacks?.();
86
+ };
87
+ }
@@ -0,0 +1,17 @@
1
+ import type { MediaEvent_OfferData_TrackTypes } from '@fishjam-cloud/protobufs/server';
2
+ import type { MediaStreamTrackId } from './types';
3
+ export declare class ConnectionManager {
4
+ private readonly connection;
5
+ constructor(iceServers: RTCIceServer[]);
6
+ isConnectionUnstable: () => boolean;
7
+ getConnection: () => RTCPeerConnection;
8
+ addTransceiversIfNeeded: (serverTracks: MediaEvent_OfferData_TrackTypes) => void;
9
+ addTransceiver: (track: MediaStreamTrack, transceiverConfig: RTCRtpTransceiverInit) => void;
10
+ setOnTrackReady: (onTrackReady: (event: RTCTrackEvent) => void) => void;
11
+ setRemoteDescription: (data: RTCSessionDescriptionInit) => Promise<void>;
12
+ isTrackInUse: (track: MediaStreamTrack) => boolean;
13
+ removeTrack: (sender: RTCRtpSender) => void;
14
+ findSender: (mediaStreamTrackId: MediaStreamTrackId) => RTCRtpSender;
15
+ addIceCandidate: (iceCandidate: RTCIceCandidate) => Promise<void>;
16
+ createDataChannel: (label: string, config: RTCDataChannelInit) => RTCDataChannel;
17
+ }
@@ -0,0 +1,49 @@
1
+ export class ConnectionManager {
2
+ connection;
3
+ constructor(iceServers) {
4
+ this.connection = new RTCPeerConnection({
5
+ bundlePolicy: 'max-bundle',
6
+ iceServers: iceServers,
7
+ iceTransportPolicy: 'all',
8
+ });
9
+ }
10
+ isConnectionUnstable = () => {
11
+ if (!this.connection)
12
+ return false;
13
+ const isSignalingUnstable = this.connection.signalingState !== 'stable';
14
+ const isConnectionNotConnected = this.connection.connectionState !== 'connected';
15
+ const isIceNotConnected = this.connection.iceConnectionState !== 'connected';
16
+ return isSignalingUnstable && isConnectionNotConnected && isIceNotConnected;
17
+ };
18
+ getConnection = () => {
19
+ return this.connection;
20
+ };
21
+ addTransceiversIfNeeded = (serverTracks) => {
22
+ const recvTransceivers = this.connection.getTransceivers().filter((elem) => elem.direction === 'recvonly');
23
+ const videoTransceiversAmount = recvTransceivers.filter((elem) => elem.receiver.track.kind === 'video').length;
24
+ const audioTransceiversAmount = recvTransceivers.filter((elem) => elem.receiver.track.kind === 'audio').length;
25
+ const videoNeededTypes = Array(serverTracks.video - videoTransceiversAmount).fill('video');
26
+ const audioNeededTypes = Array(serverTracks.audio - audioTransceiversAmount).fill('audio');
27
+ [...videoNeededTypes, ...audioNeededTypes].forEach((kind) => this.connection.addTransceiver(kind, { direction: 'recvonly' }));
28
+ };
29
+ addTransceiver = (track, transceiverConfig) => {
30
+ this.connection.addTransceiver(track, transceiverConfig);
31
+ };
32
+ setOnTrackReady = (onTrackReady) => {
33
+ this.connection.ontrack = onTrackReady;
34
+ };
35
+ setRemoteDescription = async (data) => {
36
+ await this.connection.setRemoteDescription(data);
37
+ };
38
+ isTrackInUse = (track) => this.connection.getSenders().some((val) => val.track === track);
39
+ removeTrack = (sender) => {
40
+ this.connection.removeTrack(sender);
41
+ };
42
+ findSender = (mediaStreamTrackId) => this.connection.getSenders().find((sender) => sender.track && sender.track.id === mediaStreamTrackId);
43
+ addIceCandidate = async (iceCandidate) => {
44
+ await this.connection.addIceCandidate(iceCandidate);
45
+ };
46
+ createDataChannel = (label, config) => {
47
+ return this.connection.createDataChannel(label, config);
48
+ };
49
+ }
@@ -0,0 +1,12 @@
1
+ import { Variant } from '@fishjam-cloud/protobufs/shared';
2
+ import { type BandwidthLimit } from './types';
3
+ export type Bitrate = number;
4
+ export type Bitrates = Record<Variant, Bitrate> | Bitrate;
5
+ export declare const defaultBitrates: {
6
+ readonly audio: Bitrate;
7
+ readonly video: Bitrate;
8
+ };
9
+ export declare const UNLIMITED_BANDWIDTH: Bitrate;
10
+ export declare const defaultSimulcastBitrates: {
11
+ [key in Variant]: BandwidthLimit;
12
+ };
@@ -0,0 +1,15 @@
1
+ import { Variant } from '@fishjam-cloud/protobufs/shared';
2
+ // The suggested bitrate values are based on our internal tests.
3
+ export const defaultBitrates = {
4
+ audio: 50_000,
5
+ video: 2_500_000,
6
+ };
7
+ export const UNLIMITED_BANDWIDTH = 0;
8
+ // The suggested bitrate values are based on our internal tests.
9
+ export const defaultSimulcastBitrates = {
10
+ [Variant.VARIANT_HIGH]: 2_500_000,
11
+ [Variant.VARIANT_MEDIUM]: 500_000,
12
+ [Variant.VARIANT_LOW]: 150_000,
13
+ [Variant.VARIANT_UNSPECIFIED]: 0,
14
+ [Variant.UNRECOGNIZED]: 0,
15
+ };
@@ -0,0 +1,56 @@
1
+ import type { DataCallback, DataChannelStatus, DataChannelType, Logger } from '../types';
2
+ /**
3
+ * Wrapper class for RTCDataChannel.
4
+ * Handles bidirectional data transmission.
5
+ * @internal
6
+ */
7
+ export declare class DataChannel {
8
+ private readonly type;
9
+ private readonly logger;
10
+ private channel;
11
+ private dataCallback;
12
+ private openCallback;
13
+ private errorCallback;
14
+ private _status;
15
+ constructor(type: DataChannelType, logger: Logger);
16
+ /**
17
+ * Get the current status of the data channel
18
+ */
19
+ get status(): DataChannelStatus;
20
+ /**
21
+ * Set the underlying RTCDataChannel and set up event listeners
22
+ */
23
+ setChannel(channel: RTCDataChannel): void;
24
+ /**
25
+ * Set callback to be called when the channel is opened
26
+ */
27
+ setOnOpen(callback: () => void): void;
28
+ /**
29
+ * Set callback to be called when the channel errors
30
+ */
31
+ setOnError(callback: (error: Event) => void): void;
32
+ /**
33
+ * Send data through the channel
34
+ * @param data - The data to send as Uint8Array
35
+ */
36
+ send(data: Uint8Array): void;
37
+ /**
38
+ * Set the callback for receiving data
39
+ * @param callback - Function to call when data is received
40
+ */
41
+ setCallback(callback: DataCallback): void;
42
+ /**
43
+ * Close the data channel
44
+ */
45
+ close(): void;
46
+ /**
47
+ * Set up event listeners for the RTCDataChannel
48
+ * @private
49
+ */
50
+ private setupListeners;
51
+ /**
52
+ * Handle incoming message data
53
+ * @private
54
+ */
55
+ private handleMessage;
56
+ }