@stream-io/video-client 0.0.1-alpha.7

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 (157) hide show
  1. package/LICENSE +219 -0
  2. package/README.md +14 -0
  3. package/dist/index.d.ts +23 -0
  4. package/dist/index.js +14663 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/src/Batcher.d.ts +12 -0
  7. package/dist/src/CallDropScheduler.d.ts +44 -0
  8. package/dist/src/StreamSfuClient.d.ts +25 -0
  9. package/dist/src/StreamVideoClient.d.ts +145 -0
  10. package/dist/src/__tests__/StreamVideoClient.test.d.ts +1 -0
  11. package/dist/src/config/defaultConfigs.d.ts +2 -0
  12. package/dist/src/config/types.d.ts +29 -0
  13. package/dist/src/coordinator/StreamCoordinatorClient.d.ts +19 -0
  14. package/dist/src/coordinator/connection/base64.d.ts +2 -0
  15. package/dist/src/coordinator/connection/client.d.ts +174 -0
  16. package/dist/src/coordinator/connection/connection.d.ts +139 -0
  17. package/dist/src/coordinator/connection/connection_fallback.d.ts +38 -0
  18. package/dist/src/coordinator/connection/errors.d.ts +16 -0
  19. package/dist/src/coordinator/connection/events.d.ts +7 -0
  20. package/dist/src/coordinator/connection/insights.d.ts +58 -0
  21. package/dist/src/coordinator/connection/signing.d.ts +30 -0
  22. package/dist/src/coordinator/connection/token_manager.d.ts +39 -0
  23. package/dist/src/coordinator/connection/types.d.ts +96 -0
  24. package/dist/src/coordinator/connection/utils.d.ts +25 -0
  25. package/dist/src/devices.d.ts +79 -0
  26. package/dist/src/events/call.d.ts +26 -0
  27. package/dist/src/events/internal.d.ts +8 -0
  28. package/dist/src/events/participant.d.ts +21 -0
  29. package/dist/src/events/speaker.d.ts +10 -0
  30. package/dist/src/gen/coordinator/index.d.ts +1664 -0
  31. package/dist/src/gen/google/protobuf/descriptor.d.ts +1650 -0
  32. package/dist/src/gen/google/protobuf/duration.d.ts +113 -0
  33. package/dist/src/gen/google/protobuf/struct.d.ts +184 -0
  34. package/dist/src/gen/google/protobuf/timestamp.d.ts +158 -0
  35. package/dist/src/gen/video/coordinator/broadcast_v1/broadcast.d.ts +66 -0
  36. package/dist/src/gen/video/coordinator/call_v1/call.d.ts +254 -0
  37. package/dist/src/gen/video/coordinator/client_v1_rpc/client_rpc.client.d.ts +351 -0
  38. package/dist/src/gen/video/coordinator/client_v1_rpc/client_rpc.d.ts +1488 -0
  39. package/dist/src/gen/video/coordinator/client_v1_rpc/envelopes.d.ts +143 -0
  40. package/dist/src/gen/video/coordinator/client_v1_rpc/websocket.d.ts +292 -0
  41. package/dist/src/gen/video/coordinator/edge_v1/edge.d.ts +183 -0
  42. package/dist/src/gen/video/coordinator/event_v1/event.d.ts +411 -0
  43. package/dist/src/gen/video/coordinator/geofence_v1/geofence.d.ts +63 -0
  44. package/dist/src/gen/video/coordinator/member_v1/member.d.ts +59 -0
  45. package/dist/src/gen/video/coordinator/participant_v1/participant.d.ts +103 -0
  46. package/dist/src/gen/video/coordinator/push_v1/push.d.ts +240 -0
  47. package/dist/src/gen/video/coordinator/stat_v1/stat.d.ts +308 -0
  48. package/dist/src/gen/video/coordinator/user_v1/user.d.ts +112 -0
  49. package/dist/src/gen/video/coordinator/utils_v1/utils.d.ts +47 -0
  50. package/dist/src/gen/video/sfu/event/events.d.ts +736 -0
  51. package/dist/src/gen/video/sfu/models/models.d.ts +460 -0
  52. package/dist/src/gen/video/sfu/signal_rpc/signal.client.d.ts +89 -0
  53. package/dist/src/gen/video/sfu/signal_rpc/signal.d.ts +320 -0
  54. package/dist/src/helpers/browsers.d.ts +8 -0
  55. package/dist/src/helpers/sound-detector.d.ts +34 -0
  56. package/dist/src/rpc/createClient.d.ts +10 -0
  57. package/dist/src/rpc/index.d.ts +2 -0
  58. package/dist/src/rpc/latency.d.ts +9 -0
  59. package/dist/src/rtc/Call.d.ts +180 -0
  60. package/dist/src/rtc/CallMetadata.d.ts +9 -0
  61. package/dist/src/rtc/Dispatcher.d.ts +9 -0
  62. package/dist/src/rtc/IceTrickleBuffer.d.ts +11 -0
  63. package/dist/src/rtc/callEventHandlers.d.ts +5 -0
  64. package/dist/src/rtc/codecs.d.ts +2 -0
  65. package/dist/src/rtc/helpers/iceCandidate.d.ts +2 -0
  66. package/dist/src/rtc/helpers/tracks.d.ts +3 -0
  67. package/dist/src/rtc/publisher.d.ts +53 -0
  68. package/dist/src/rtc/signal.d.ts +5 -0
  69. package/dist/src/rtc/subscriber.d.ts +7 -0
  70. package/dist/src/rtc/types.d.ts +84 -0
  71. package/dist/src/rtc/videoLayers.d.ts +17 -0
  72. package/dist/src/stats/coordinator-stats-reporter.d.ts +10 -0
  73. package/dist/src/stats/state-store-stats-reporter.d.ts +57 -0
  74. package/dist/src/stats/types.d.ts +42 -0
  75. package/dist/src/store/index.d.ts +2 -0
  76. package/dist/src/store/rxUtils.d.ts +18 -0
  77. package/dist/src/store/stateStore.d.ts +182 -0
  78. package/generate-openapi.sh +32 -0
  79. package/index.ts +30 -0
  80. package/openapitools.json +7 -0
  81. package/package.json +54 -0
  82. package/rollup.config.mjs +48 -0
  83. package/src/Batcher.ts +43 -0
  84. package/src/CallDropScheduler.ts +192 -0
  85. package/src/StreamSfuClient.ts +185 -0
  86. package/src/StreamVideoClient.ts +487 -0
  87. package/src/__tests__/StreamVideoClient.test.ts +83 -0
  88. package/src/config/defaultConfigs.ts +15 -0
  89. package/src/config/types.ts +30 -0
  90. package/src/coordinator/StreamCoordinatorClient.ts +111 -0
  91. package/src/coordinator/connection/base64.ts +80 -0
  92. package/src/coordinator/connection/client.ts +815 -0
  93. package/src/coordinator/connection/connection.ts +750 -0
  94. package/src/coordinator/connection/connection_fallback.ts +239 -0
  95. package/src/coordinator/connection/errors.ts +70 -0
  96. package/src/coordinator/connection/events.ts +10 -0
  97. package/src/coordinator/connection/insights.ts +88 -0
  98. package/src/coordinator/connection/signing.ts +104 -0
  99. package/src/coordinator/connection/token_manager.ts +160 -0
  100. package/src/coordinator/connection/types.ts +120 -0
  101. package/src/coordinator/connection/utils.ts +148 -0
  102. package/src/devices.ts +266 -0
  103. package/src/events/call.ts +166 -0
  104. package/src/events/internal.ts +47 -0
  105. package/src/events/participant.ts +97 -0
  106. package/src/events/speaker.ts +62 -0
  107. package/src/gen/coordinator/index.ts +1653 -0
  108. package/src/gen/google/protobuf/descriptor.ts +3466 -0
  109. package/src/gen/google/protobuf/duration.ts +232 -0
  110. package/src/gen/google/protobuf/struct.ts +481 -0
  111. package/src/gen/google/protobuf/timestamp.ts +291 -0
  112. package/src/gen/video/coordinator/broadcast_v1/broadcast.ts +154 -0
  113. package/src/gen/video/coordinator/call_v1/call.ts +651 -0
  114. package/src/gen/video/coordinator/client_v1_rpc/client_rpc.client.ts +463 -0
  115. package/src/gen/video/coordinator/client_v1_rpc/client_rpc.ts +3819 -0
  116. package/src/gen/video/coordinator/client_v1_rpc/envelopes.ts +424 -0
  117. package/src/gen/video/coordinator/client_v1_rpc/websocket.ts +719 -0
  118. package/src/gen/video/coordinator/edge_v1/edge.ts +532 -0
  119. package/src/gen/video/coordinator/event_v1/event.ts +1171 -0
  120. package/src/gen/video/coordinator/geofence_v1/geofence.ts +128 -0
  121. package/src/gen/video/coordinator/member_v1/member.ts +138 -0
  122. package/src/gen/video/coordinator/participant_v1/participant.ts +261 -0
  123. package/src/gen/video/coordinator/push_v1/push.ts +651 -0
  124. package/src/gen/video/coordinator/stat_v1/stat.ts +656 -0
  125. package/src/gen/video/coordinator/user_v1/user.ts +277 -0
  126. package/src/gen/video/coordinator/utils_v1/utils.ts +98 -0
  127. package/src/gen/video/sfu/event/events.ts +1962 -0
  128. package/src/gen/video/sfu/models/models.ts +1062 -0
  129. package/src/gen/video/sfu/signal_rpc/signal.client.ts +108 -0
  130. package/src/gen/video/sfu/signal_rpc/signal.ts +906 -0
  131. package/src/helpers/browsers.ts +13 -0
  132. package/src/helpers/sound-detector.ts +85 -0
  133. package/src/rpc/createClient.ts +50 -0
  134. package/src/rpc/index.ts +2 -0
  135. package/src/rpc/latency.ts +43 -0
  136. package/src/rtc/Call.ts +585 -0
  137. package/src/rtc/CallMetadata.ts +24 -0
  138. package/src/rtc/Dispatcher.ts +46 -0
  139. package/src/rtc/IceTrickleBuffer.ts +21 -0
  140. package/src/rtc/callEventHandlers.ts +37 -0
  141. package/src/rtc/codecs.ts +61 -0
  142. package/src/rtc/helpers/iceCandidate.ts +16 -0
  143. package/src/rtc/helpers/tracks.ts +18 -0
  144. package/src/rtc/publisher.ts +305 -0
  145. package/src/rtc/signal.ts +34 -0
  146. package/src/rtc/subscriber.ts +85 -0
  147. package/src/rtc/types.ts +105 -0
  148. package/src/rtc/videoLayers.ts +103 -0
  149. package/src/stats/coordinator-stats-reporter.ts +167 -0
  150. package/src/stats/state-store-stats-reporter.ts +364 -0
  151. package/src/stats/types.ts +46 -0
  152. package/src/store/index.ts +2 -0
  153. package/src/store/rxUtils.ts +42 -0
  154. package/src/store/stateStore.ts +341 -0
  155. package/tsconfig.json +25 -0
  156. package/typedoc.json +11 -0
  157. package/vite.config.ts +11 -0
package/src/Batcher.ts ADDED
@@ -0,0 +1,43 @@
1
+ export class Batcher<BatchItemType> {
2
+ private batch: Array<BatchItemType>;
3
+ private timeoutId: NodeJS.Timeout | undefined;
4
+
5
+ constructor(
6
+ private readonly timeoutInterval: number,
7
+ private readonly requestFunction: (data: Array<BatchItemType>) => void,
8
+ ) {
9
+ this.batch = [];
10
+ }
11
+
12
+ private scheduleTimeout = () => {
13
+ this.timeoutId = setTimeout(() => {
14
+ try {
15
+ if (!this.batch.length) return;
16
+ this.requestFunction(this.batch);
17
+ this.clearBatch();
18
+ } catch (error) {
19
+ console.error(error);
20
+ }
21
+ }, this.timeoutInterval);
22
+ };
23
+
24
+ private clearTimeout = () => {
25
+ clearTimeout(this.timeoutId);
26
+ this.timeoutId = undefined;
27
+ };
28
+
29
+ public clearBatch = () => {
30
+ this.batch = [];
31
+ this.clearTimeout();
32
+ };
33
+
34
+ public addToBatch = (item: BatchItemType) => {
35
+ this.batch.push(item);
36
+ if (!this.timeoutId) this.scheduleTimeout();
37
+ };
38
+
39
+ public removeFromBatch = (item: BatchItemType) => {
40
+ const itemIndex = this.batch.indexOf(item);
41
+ if (itemIndex > -1) this.batch.splice(itemIndex, 1);
42
+ };
43
+ }
@@ -0,0 +1,192 @@
1
+ import { StreamVideoWriteableStateStore } from './store';
2
+ import { CallConfig } from './config/types';
3
+ import { Observable, pairwise, startWith, Subscription } from 'rxjs';
4
+ import { CallMetadata } from './rtc/CallMetadata';
5
+
6
+ type CallCID = string;
7
+ type DropFunction = (callCid: CallCID) => Promise<void>;
8
+
9
+ export class CallDropScheduler {
10
+ private autoCallDropSchedule: Record<CallCID, ReturnType<typeof setTimeout>>;
11
+ private storeSubscriptions: { [key in keyof CallConfig]?: Subscription } & {
12
+ cancelDropOnPendingCallRemoval?: Subscription;
13
+ cancelDropOnCallAccepted?: Subscription;
14
+ };
15
+ private pairwisePendingCalls$: Observable<CallMetadata[][]>;
16
+ private pairwiseIncomingCalls$: Observable<CallMetadata[][]>;
17
+ private pairwiseOutgoingCalls$: Observable<CallMetadata[][]>;
18
+ constructor(
19
+ private store: StreamVideoWriteableStateStore,
20
+ private callConfig: CallConfig,
21
+ private reject: DropFunction,
22
+ private cancel: DropFunction,
23
+ ) {
24
+ this.pairwisePendingCalls$ = store.pendingCallsSubject.pipe(
25
+ startWith([]),
26
+ pairwise(),
27
+ );
28
+ this.pairwiseIncomingCalls$ = store.incomingCalls$.pipe(
29
+ startWith([]),
30
+ pairwise(),
31
+ );
32
+ this.pairwiseOutgoingCalls$ = store.outgoingCalls$.pipe(
33
+ startWith([]),
34
+ pairwise(),
35
+ );
36
+
37
+ this.autoCallDropSchedule = {};
38
+ this.storeSubscriptions = {};
39
+
40
+ this.startAutoRejectWhenInCall();
41
+ this.scheduleRejectAfterTimeout();
42
+ this.scheduleCancelAfterTimeout();
43
+ this.startCancellingDrops();
44
+ }
45
+
46
+ private static getLatestCall = (
47
+ from: CallMetadata[],
48
+ compareTo: CallMetadata[],
49
+ ) => {
50
+ return from > compareTo ? from.slice(-1)[0] : undefined;
51
+ };
52
+ private startAutoRejectWhenInCall = () => {
53
+ if (!this.callConfig.autoRejectWhenInCall) return;
54
+
55
+ this.storeSubscriptions.autoRejectWhenInCall =
56
+ this.pairwiseIncomingCalls$.subscribe(
57
+ async ([prevCalls, currentCalls]) => {
58
+ const newIncomingCall = CallDropScheduler.getLatestCall(
59
+ currentCalls,
60
+ prevCalls,
61
+ );
62
+
63
+ if (!newIncomingCall) return;
64
+
65
+ const activeCall = this.store.getCurrentValue(
66
+ this.store.activeCallSubject,
67
+ );
68
+
69
+ if (activeCall && newIncomingCall?.call.cid) {
70
+ await this.reject(newIncomingCall.call.cid);
71
+ }
72
+ },
73
+ );
74
+ };
75
+
76
+ private scheduleRejectAfterTimeout = () => {
77
+ const { autoRejectTimeoutInMs } = this.callConfig;
78
+ if (typeof autoRejectTimeoutInMs !== 'number' || autoRejectTimeoutInMs < 0)
79
+ return;
80
+
81
+ this.storeSubscriptions.autoRejectTimeoutInMs =
82
+ this.pairwiseIncomingCalls$.subscribe(([prevCalls, currentCalls]) => {
83
+ const newIncomingCall = CallDropScheduler.getLatestCall(
84
+ currentCalls,
85
+ prevCalls,
86
+ );
87
+ if (!newIncomingCall?.call.cid) return;
88
+
89
+ const activeCall = this.store.getCurrentValue(
90
+ this.store.activeCallSubject,
91
+ );
92
+ const incomingCallRejectedImmediately =
93
+ activeCall && this.callConfig.autoRejectWhenInCall;
94
+ if (incomingCallRejectedImmediately) return;
95
+
96
+ this.scheduleReject(newIncomingCall.call.cid);
97
+ });
98
+ };
99
+
100
+ private scheduleCancelAfterTimeout = () => {
101
+ const { autoCancelTimeoutInMs } = this.callConfig;
102
+ if (typeof autoCancelTimeoutInMs !== 'number' || autoCancelTimeoutInMs < 0)
103
+ return;
104
+
105
+ this.storeSubscriptions.autoCancelTimeoutInMs =
106
+ this.pairwiseOutgoingCalls$.subscribe(([prevCalls, currentCalls]) => {
107
+ const newOutgoingCall = CallDropScheduler.getLatestCall(
108
+ currentCalls,
109
+ prevCalls,
110
+ );
111
+
112
+ if (!newOutgoingCall?.call.cid) return;
113
+ this.scheduleCancel(newOutgoingCall.call.cid);
114
+ });
115
+ };
116
+
117
+ private startCancellingDrops = () => {
118
+ this.storeSubscriptions.cancelDropOnPendingCallRemoval =
119
+ this.pairwisePendingCalls$.subscribe(([prevCalls, currentCalls]) => {
120
+ const removedCall = CallDropScheduler.getLatestCall(
121
+ prevCalls,
122
+ currentCalls,
123
+ );
124
+
125
+ if (removedCall?.call.cid) {
126
+ this.cancelDrop(removedCall?.call.cid);
127
+ }
128
+ });
129
+
130
+ this.storeSubscriptions.cancelDropOnCallAccepted =
131
+ this.store.acceptedCallSubject.subscribe((acceptedCall) => {
132
+ if (acceptedCall?.call_cid) {
133
+ this.cancelDrop(acceptedCall.call_cid);
134
+ }
135
+ });
136
+ };
137
+
138
+ /**
139
+ * Schedules automatic call cancellation.
140
+ * The cancellation is intended for the scenarios, when the call has been rejected
141
+ * or not accepted by all the call members.
142
+ * @param {string} callCid
143
+ */
144
+ private scheduleCancel = (callCid: string) => {
145
+ const timeout = this.callConfig.autoCancelTimeoutInMs;
146
+ if (!timeout) return;
147
+ this.autoCallDropSchedule[callCid] = setTimeout(() => {
148
+ console.log('Automatic call cancellation after timeout', timeout);
149
+ this.cancel(callCid);
150
+ }, timeout);
151
+ };
152
+
153
+ /**
154
+ * Schedules automatic call rejection.
155
+ * @param {string} callCid
156
+ */
157
+ private scheduleReject = (callCid: string) => {
158
+ const timeout = this.callConfig.autoRejectTimeoutInMs;
159
+ if (!timeout) return;
160
+ this.autoCallDropSchedule[callCid] = setTimeout(() => {
161
+ console.log('Automatic call rejection after timeout', timeout);
162
+ this.reject(callCid);
163
+ }, timeout);
164
+ };
165
+
166
+ /**
167
+ * Cancels the automatic call drop (rejection of an incoming call / cancellation of an outgoing call).
168
+ * Indented for the scenario, when:
169
+ * - an incoming call has been cancelled
170
+ * - an outgoing call has been accepted by at least one member
171
+ * - an outgoing call has been rejected / left by all the members resp. participants
172
+ * - a call has been cancelled / rejected / accepted manually before the cancellation timeout expires.
173
+ */
174
+ private cancelDrop = (callCid: string) => {
175
+ const { [callCid]: timeoutRef, ...rest } = this.autoCallDropSchedule;
176
+ if (timeoutRef !== undefined) {
177
+ console.log(`Cancelling automatic call drop, [callCID: ${callCid}]`);
178
+ clearTimeout(timeoutRef);
179
+ this.autoCallDropSchedule = rest;
180
+ }
181
+ };
182
+
183
+ cleanUp = () => {
184
+ Object.values(this.autoCallDropSchedule).forEach((timeoutRef) =>
185
+ clearTimeout(timeoutRef),
186
+ );
187
+ this.autoCallDropSchedule = {};
188
+ Object.values(this.storeSubscriptions).forEach((subscription) =>
189
+ subscription.unsubscribe(),
190
+ );
191
+ };
192
+ }
@@ -0,0 +1,185 @@
1
+ import { SignalServerClient } from './gen/video/sfu/signal_rpc/signal.client';
2
+ import { createSignalClient, withHeaders } from './rpc';
3
+ import { createWebSocketSignalChannel } from './rtc/signal';
4
+ import { JoinRequest, SfuRequest } from './gen/video/sfu/event/events';
5
+ import { Dispatcher } from './rtc/Dispatcher';
6
+ import { v4 as uuidv4 } from 'uuid';
7
+ import { IceTrickleBuffer } from './rtc/IceTrickleBuffer';
8
+ import {
9
+ SendAnswerRequest,
10
+ SetPublisherRequest,
11
+ TrackSubscriptionDetails,
12
+ UpdateMuteStatesRequest,
13
+ } from './gen/video/sfu/signal_rpc/signal';
14
+ import { ICETrickle, TrackType } from './gen/video/sfu/models/models';
15
+
16
+ const hostnameFromUrl = (url: string) => {
17
+ try {
18
+ return new URL(url).hostname;
19
+ } catch (e) {
20
+ console.warn(`Invalid URL. Can't extract hostname from it.`, e);
21
+ return url;
22
+ }
23
+ };
24
+
25
+ const toURL = (url: string) => {
26
+ try {
27
+ return new URL(url);
28
+ } catch (e) {
29
+ return null;
30
+ }
31
+ };
32
+
33
+ export class StreamSfuClient {
34
+ readonly dispatcher = new Dispatcher();
35
+ readonly iceTrickleBuffer = new IceTrickleBuffer();
36
+ // we generate uuid session id client side
37
+ readonly sessionId: string;
38
+ private readonly rpc: SignalServerClient;
39
+ // Current JWT token
40
+ private readonly token: string;
41
+ signalReady: Promise<WebSocket>;
42
+ private keepAliveInterval?: NodeJS.Timeout;
43
+
44
+ constructor(url: string, token: string) {
45
+ this.sessionId = uuidv4();
46
+ this.token = token;
47
+ this.rpc = createSignalClient({
48
+ baseUrl: url,
49
+ interceptors: [
50
+ withHeaders({
51
+ Authorization: `Bearer ${token}`,
52
+ }),
53
+ ],
54
+ });
55
+
56
+ // FIXME: OL: this should come from the coordinator API
57
+ const sfuHost = hostnameFromUrl(url);
58
+ let wsEndpoint = `ws://${sfuHost}:3031/ws`;
59
+ if (!['localhost', '127.0.0.1'].includes(sfuHost)) {
60
+ const sfuUrl = toURL(url);
61
+ if (sfuUrl) {
62
+ sfuUrl.protocol = 'wss:';
63
+ sfuUrl.pathname = '/ws';
64
+ wsEndpoint = sfuUrl.toString();
65
+ }
66
+ }
67
+
68
+ // Special handling for the ICETrickle kind of events.
69
+ // These events might be triggered by the SFU before the initial RTC
70
+ // connection is established. In that case, those events (ICE candidates)
71
+ // need to be buffered and later added to the appropriate PeerConnection
72
+ // once the remoteDescription is known and set.
73
+ this.dispatcher.on('iceTrickle', (e) => {
74
+ if (e.eventPayload.oneofKind !== 'iceTrickle') return;
75
+ const { iceTrickle } = e.eventPayload;
76
+ this.iceTrickleBuffer.push(iceTrickle);
77
+ });
78
+
79
+ this.signalReady = createWebSocketSignalChannel({
80
+ endpoint: wsEndpoint,
81
+ onMessage: (message) => {
82
+ this.dispatcher.dispatch(message);
83
+ },
84
+ });
85
+ }
86
+
87
+ close = () => {
88
+ this.signalReady.then((ws) => {
89
+ this.signalReady = Promise.reject('Connection closed');
90
+ // TODO OL: re-connect flow
91
+ ws.close(1000, 'Requested signal connection close');
92
+
93
+ this.dispatcher.offAll();
94
+ clearInterval(this.keepAliveInterval);
95
+ });
96
+ };
97
+
98
+ updateSubscriptions = async (subscriptions: TrackSubscriptionDetails[]) => {
99
+ return this.rpc.updateSubscriptions({
100
+ sessionId: this.sessionId,
101
+ tracks: subscriptions,
102
+ });
103
+ };
104
+
105
+ setPublisher = async (data: Omit<SetPublisherRequest, 'sessionId'>) => {
106
+ return this.rpc.setPublisher({
107
+ ...data,
108
+ sessionId: this.sessionId,
109
+ });
110
+ };
111
+
112
+ sendAnswer = async (data: Omit<SendAnswerRequest, 'sessionId'>) => {
113
+ return this.rpc.sendAnswer({
114
+ ...data,
115
+ sessionId: this.sessionId,
116
+ });
117
+ };
118
+
119
+ iceTrickle = async (data: Omit<ICETrickle, 'sessionId'>) => {
120
+ return this.rpc.iceTrickle({
121
+ ...data,
122
+ sessionId: this.sessionId,
123
+ });
124
+ };
125
+
126
+ updateMuteState = async (trackType: TrackType, muted: boolean) => {
127
+ return this.updateMuteStates({
128
+ muteStates: [
129
+ {
130
+ trackType,
131
+ muted,
132
+ },
133
+ ],
134
+ });
135
+ };
136
+
137
+ updateMuteStates = async (
138
+ data: Omit<UpdateMuteStatesRequest, 'sessionId'>,
139
+ ) => {
140
+ return this.rpc.updateMuteStates({
141
+ ...data,
142
+ sessionId: this.sessionId,
143
+ });
144
+ };
145
+
146
+ join = async (data: Omit<JoinRequest, 'sessionId' | 'token'>) => {
147
+ const joinRequest = JoinRequest.create({
148
+ ...data,
149
+ sessionId: this.sessionId,
150
+ token: this.token,
151
+ });
152
+ return this.send(
153
+ SfuRequest.create({
154
+ requestPayload: {
155
+ oneofKind: 'joinRequest',
156
+ joinRequest,
157
+ },
158
+ }),
159
+ );
160
+ };
161
+
162
+ send = (message: SfuRequest) => {
163
+ return this.signalReady.then((signal) => {
164
+ signal.send(SfuRequest.toBinary(message));
165
+ });
166
+ };
167
+
168
+ // FIXME: make this private
169
+ async keepAlive() {
170
+ await this.signalReady;
171
+ console.log('Registering healthcheck for SFU');
172
+ this.keepAliveInterval = setInterval(() => {
173
+ const message = SfuRequest.create({
174
+ requestPayload: {
175
+ oneofKind: 'healthCheckRequest',
176
+ healthCheckRequest: {
177
+ sessionId: this.sessionId,
178
+ },
179
+ },
180
+ });
181
+ console.log('Sending healthCheckRequest to SFU', message);
182
+ this.send(message);
183
+ }, 27000);
184
+ }
185
+ }