@livekit/rtc-node 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/room.ts DELETED
@@ -1,370 +0,0 @@
1
- import { FfiClient, FfiClientEvent, FfiHandle } from './ffi_client';
2
- import EventEmitter from 'events';
3
- import TypedEmitter from 'typed-emitter';
4
- import { FfiEvent } from './proto/ffi_pb';
5
- import { LocalParticipant, Participant, RemoteParticipant } from './participant';
6
- import {
7
- ConnectCallback,
8
- ConnectRequest,
9
- ConnectResponse,
10
- ConnectionQuality,
11
- ConnectionState,
12
- ContinualGatheringPolicy,
13
- DataPacketKind,
14
- DisconnectResponse,
15
- IceServer,
16
- IceTransportType,
17
- RoomInfo,
18
- } from './proto/room_pb';
19
- import { E2EEManager, E2EEOptions, defaultE2EEOptions } from './e2ee';
20
- import { OwnedParticipant } from './proto/participant_pb';
21
- import {
22
- LocalTrackPublication,
23
- RemoteTrackPublication,
24
- TrackPublication,
25
- } from './track_publication';
26
- import { LocalTrack, RemoteAudioTrack, RemoteTrack, RemoteVideoTrack } from './track';
27
- import { TrackKind } from './proto/track_pb';
28
- import { EncryptionState } from './proto/e2ee_pb';
29
-
30
- export interface RtcConfiguration {
31
- iceTransportType: IceTransportType;
32
- continualGatheringPolicy: ContinualGatheringPolicy;
33
- iceServers: IceServer[];
34
- }
35
-
36
- export const defaultRtcConfiguration: RtcConfiguration = {
37
- iceTransportType: IceTransportType.TRANSPORT_ALL,
38
- continualGatheringPolicy: ContinualGatheringPolicy.GATHER_CONTINUALLY,
39
- iceServers: [],
40
- };
41
-
42
- export interface RoomOptions {
43
- autoSubscribe: boolean;
44
- dynacast: boolean;
45
- e2ee?: E2EEOptions;
46
- rtcConfig?: RtcConfiguration;
47
- }
48
-
49
- export const defaultRoomOptions: RoomOptions = {
50
- autoSubscribe: true,
51
- dynacast: false,
52
- e2ee: undefined,
53
- rtcConfig: undefined,
54
- };
55
-
56
- export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>) {
57
- private info: RoomInfo;
58
- private ffiHandle?: FfiHandle;
59
-
60
- e2eeManager: E2EEManager;
61
- connection_state: ConnectionState = ConnectionState.CONN_DISCONNECTED;
62
-
63
- participants: Map<string, RemoteParticipant> = new Map();
64
- localParticipant?: LocalParticipant;
65
-
66
- constructor() {
67
- super();
68
- FfiClient.instance.addListener(FfiClientEvent.FfiEvent, this.onFfiEvent);
69
- }
70
-
71
- get sid(): string {
72
- return this.info.sid;
73
- }
74
-
75
- get name(): string {
76
- return this.info.name;
77
- }
78
-
79
- get metadata(): string {
80
- return this.info.metadata;
81
- }
82
-
83
- get isConnected(): boolean {
84
- return (
85
- this.ffiHandle != undefined && this.connection_state != ConnectionState.CONN_DISCONNECTED
86
- );
87
- }
88
-
89
- async connect(url: string, token: string, opts: RoomOptions) {
90
- const options = { ...defaultRoomOptions, ...opts };
91
-
92
- let req = new ConnectRequest({
93
- url: url,
94
- token: token,
95
- options: {
96
- autoSubscribe: options.autoSubscribe,
97
- dynacast: options.dynacast,
98
- e2ee: {
99
- encryptionType: options.e2ee?.encryptionType,
100
- keyProviderOptions: {
101
- failureTolerance: options.e2ee?.keyProviderOptions?.failureTolerance,
102
- ratchetSalt: options.e2ee?.keyProviderOptions?.ratchetSalt,
103
- ratchetWindowSize: options.e2ee?.keyProviderOptions?.ratchetWindowSize,
104
- sharedKey: options.e2ee?.keyProviderOptions?.sharedKey,
105
- },
106
- },
107
- },
108
- });
109
-
110
- let res = FfiClient.instance.request<ConnectResponse>({
111
- message: {
112
- case: 'connect',
113
- value: req,
114
- },
115
- });
116
-
117
- let cb = await FfiClient.instance.waitFor<ConnectCallback>((ev: FfiEvent) => {
118
- return ev.message.case == 'connect' && ev.message.value.asyncId == res.asyncId;
119
- });
120
-
121
- if (cb.error) {
122
- throw new ConnectError(cb.error);
123
- }
124
-
125
- this.ffiHandle = new FfiHandle(cb.room.handle.id);
126
- this.e2eeManager = new E2EEManager(this.ffiHandle.handle, options.e2ee);
127
-
128
- this.info = cb.room.info;
129
- this.connection_state = ConnectionState.CONN_CONNECTED;
130
- this.localParticipant = new LocalParticipant(cb.localParticipant);
131
-
132
- for (let pt of cb.participants) {
133
- let rp = this.createRemoteParticipant(pt.participant);
134
-
135
- for (let pub of pt.publications) {
136
- let publication = new RemoteTrackPublication(pub);
137
- rp.tracks.set(publication.sid, publication);
138
- }
139
- }
140
-
141
- FfiClient.instance.on(FfiClientEvent.FfiEvent, this.onFfiEvent);
142
- }
143
-
144
- async disconnect() {
145
- if (!this.isConnected) {
146
- return;
147
- }
148
-
149
- FfiClient.instance.request<DisconnectResponse>({
150
- message: {
151
- case: 'disconnect',
152
- value: {
153
- roomHandle: this.ffiHandle.handle,
154
- },
155
- },
156
- });
157
- }
158
-
159
- onFfiEvent(ffiEvent: FfiEvent) {
160
- if (
161
- ffiEvent.message.case != 'roomEvent' ||
162
- ffiEvent.message.value.roomHandle != this.ffiHandle.handle
163
- ) {
164
- return;
165
- }
166
-
167
- let ev = ffiEvent.message.value.message;
168
- if (ev.case == 'participantConnected') {
169
- let participant = this.createRemoteParticipant(ev.value.info);
170
- this.participants.set(participant.sid, participant);
171
- this.emit(RoomEvent.ParticipantConnected, participant);
172
- } else if (ev.case == 'participantDisconnected') {
173
- let participant = this.participants.get(ev.value.participantSid);
174
- this.participants.delete(ev.value.participantSid);
175
- this.emit(RoomEvent.ParticipantDisconnected, participant);
176
- } else if (ev.case == 'localTrackPublished') {
177
- let publication = this.localParticipant.tracks.get(ev.value.trackSid);
178
- this.emit(RoomEvent.LocalTrackPublished, publication, publication.track);
179
- } else if (ev.case == 'localTrackUnpublished') {
180
- let publication = this.localParticipant.tracks.get(ev.value.publicationSid);
181
- this.localParticipant.tracks.delete(ev.value.publicationSid);
182
- this.emit(RoomEvent.LocalTrackUnpublished, publication);
183
- } else if (ev.case == 'trackPublished') {
184
- let participant = this.participants.get(ev.value.participantSid);
185
- let publication = new RemoteTrackPublication(ev.value.publication);
186
- participant.tracks.set(publication.sid, publication);
187
- this.emit(RoomEvent.TrackPublished, publication, participant);
188
- } else if (ev.case == 'trackUnpublished') {
189
- let participant = this.participants.get(ev.value.participantSid);
190
- let publication = participant.tracks.get(ev.value.publicationSid);
191
- participant.tracks.delete(ev.value.publicationSid);
192
- this.emit(RoomEvent.TrackUnpublished, publication, participant);
193
- } else if (ev.case == 'trackSubscribed') {
194
- let ownedTrack = ev.value.track;
195
- let participant = this.participants.get(ev.value.participantSid);
196
- let publication = participant.tracks.get(ownedTrack.info.sid);
197
- publication.subscribed = true;
198
- if (ownedTrack.info.kind == TrackKind.KIND_VIDEO) {
199
- publication.track = new RemoteVideoTrack(ownedTrack);
200
- } else if (ownedTrack.info.kind == TrackKind.KIND_AUDIO) {
201
- publication.track = new RemoteAudioTrack(ownedTrack);
202
- }
203
-
204
- this.emit(RoomEvent.TrackSubscribed, publication.track, publication, participant);
205
- } else if (ev.case == 'trackUnsubscribed') {
206
- let participant = this.participants.get(ev.value.participantSid);
207
- let publication = participant.tracks.get(ev.value.trackSid);
208
- publication.track = undefined;
209
- publication.subscribed = false;
210
- this.emit(RoomEvent.TrackUnsubscribed, publication.track, publication, participant);
211
- } else if (ev.case == 'trackSubscriptionFailed') {
212
- let participant = this.participants.get(ev.value.participantSid);
213
- this.emit(RoomEvent.TrackSubscriptionFailed, participant, ev.value.trackSid, ev.value.error);
214
- } else if (ev.case == 'trackMuted') {
215
- let participant = this.retrieveParticipant(ev.value.participantSid);
216
- let publication = participant.tracks.get(ev.value.trackSid);
217
- publication.info.muted = true;
218
- if (publication.track) {
219
- publication.track.info.muted = true;
220
- }
221
- this.emit(RoomEvent.TrackMuted, participant, publication);
222
- } else if (ev.case == 'trackUnmuted') {
223
- let participant = this.retrieveParticipant(ev.value.participantSid);
224
- let publication = participant.tracks.get(ev.value.trackSid);
225
- publication.info.muted = false;
226
- if (publication.track) {
227
- publication.track.info.muted = false;
228
- }
229
- this.emit(RoomEvent.TrackUnmuted, participant, publication);
230
- } else if (ev.case == 'activeSpeakersChanged') {
231
- let activeSpeakers = ev.value.participantSids.map((sid) => this.participants.get(sid));
232
- this.emit(RoomEvent.ActiveSpeakersChanged, activeSpeakers);
233
- } else if (ev.case == 'roomMetadataChanged') {
234
- let oldMetadata = this.info.metadata;
235
- this.info.metadata = ev.value.metadata;
236
- this.emit(RoomEvent.RoomMetadataChanged, oldMetadata, this.info.metadata);
237
- } else if (ev.case == 'participantMetadataChanged') {
238
- let participant = this.retrieveParticipant(ev.value.participantSid);
239
- let oldMetadata = participant.metadata;
240
- participant.info.metadata = ev.value.metadata;
241
- this.emit(
242
- RoomEvent.ParticipantMetadataChanged,
243
- participant,
244
- oldMetadata,
245
- participant.metadata,
246
- );
247
- } else if (ev.case == 'participantNameChanged') {
248
- let participant = this.retrieveParticipant(ev.value.participantSid);
249
- let oldName = participant.name;
250
- participant.info.name = ev.value.name;
251
- this.emit(RoomEvent.ParticipantNameChanged, participant, oldName, participant.name);
252
- } else if (ev.case == 'connectionQualityChanged') {
253
- let participant = this.retrieveParticipant(ev.value.participantSid);
254
- this.emit(RoomEvent.ConnectionQualityChanged, participant, ev.value.quality);
255
- } else if (ev.case == 'dataReceived') {
256
- // Can be undefined if the data is sent from a Server SDK
257
- let participant = this.participants.get(ev.value.participantSid);
258
- let info = ev.value.data;
259
- let buffer = FfiClient.instance.copyBuffer(info.data.dataPtr, Number(info.data.dataLen));
260
- new FfiHandle(info.handle.id).dispose();
261
- this.emit(RoomEvent.DataReceived, buffer, ev.value.kind, participant);
262
- } else if (ev.case == 'e2eeStateChanged') {
263
- let participant = this.retrieveParticipant(ev.value.participantSid);
264
- this.emit(RoomEvent.E2EEStateChanged, participant, ev.value.state);
265
- } else if (ev.case == 'connectionStateChanged') {
266
- this.connection_state = ev.value.state;
267
- this.emit(RoomEvent.ConenctionStateChanged, this.connection_state);
268
- /*} else if (ev.case == 'connected') {
269
- this.emit(RoomEvent.Connected);*/
270
- } else if (ev.case == 'disconnected') {
271
- this.emit(RoomEvent.Disconnected);
272
- } else if (ev.case == 'reconnecting') {
273
- this.emit(RoomEvent.Reconnecting);
274
- } else if (ev.case == 'reconnected') {
275
- this.emit(RoomEvent.Reconnected);
276
- }
277
- }
278
-
279
- private retrieveParticipant(sid: string): Participant {
280
- if (this.localParticipant.sid == sid) {
281
- return this.localParticipant;
282
- } else {
283
- return this.participants.get(sid);
284
- }
285
- }
286
-
287
- private createRemoteParticipant(ownedInfo: OwnedParticipant) {
288
- if (this.participants.has(ownedInfo.info.sid)) {
289
- throw new Error('Participant already exists');
290
- }
291
-
292
- let participant = new RemoteParticipant(ownedInfo);
293
- this.participants.set(ownedInfo.info.sid, participant);
294
- return participant;
295
- }
296
- }
297
-
298
- export class ConnectError extends Error {
299
- constructor(message: string) {
300
- super(message);
301
- }
302
- }
303
-
304
- export type RoomCallbacks = {
305
- participantConnected: (participant: RemoteParticipant) => void;
306
- participantDisconnected: (participant: RemoteParticipant) => void;
307
- localTrackPublished: (publication: LocalTrackPublication, track: LocalTrack) => void;
308
- localTrackUnpublished: (publication: LocalTrackPublication) => void;
309
- trackPublished: (publication: RemoteTrackPublication, participant: RemoteParticipant) => void;
310
- trackUnpublished: (publication: RemoteTrackPublication, participant: RemoteParticipant) => void;
311
- trackSubscribed: (
312
- track: RemoteTrack,
313
- publication: RemoteTrackPublication,
314
- participant: RemoteParticipant,
315
- ) => void;
316
- trackUnsubscribed: (
317
- track: RemoteTrack,
318
- publication: RemoteTrackPublication,
319
- participant: RemoteParticipant,
320
- ) => void;
321
- trackSubscriptionFailed: (
322
- participant: RemoteParticipant,
323
- publicationSid: string,
324
- error: string,
325
- ) => void;
326
- trackMuted: (participant: Participant, publication: TrackPublication) => void;
327
- trackUnmuted: (participant: Participant, publication: TrackPublication) => void;
328
- activeSpeakersChanged: (speakers: RemoteParticipant[]) => void;
329
- roomMetadataChanged: (oldMetadata: string, metadata: string) => void;
330
- participantMetadataChanged: (
331
- participant: Participant,
332
- oldMetadata: string,
333
- metadata: string,
334
- ) => void;
335
- participantNameChanged: (participant: Participant, oldName: string, name: string) => void;
336
- connectionQualityChanged: (participant: Participant, quality: ConnectionQuality) => void;
337
- dataReceived: (data: Uint8Array, kind: DataPacketKind, participant?: RemoteParticipant) => void;
338
- e2eeStateChanged: (participant: Participant, state: EncryptionState) => void;
339
- connectionStateChanged: (state: ConnectionState) => void;
340
- connected: () => void;
341
- disconnected: () => void;
342
- reconnecting: () => void;
343
- reconnected: () => void;
344
- };
345
-
346
- export enum RoomEvent {
347
- ParticipantConnected = 'participantConnected',
348
- ParticipantDisconnected = 'participantDisconnected',
349
- LocalTrackPublished = 'localTrackPublished',
350
- LocalTrackUnpublished = 'localTrackUnpublished',
351
- TrackPublished = 'trackPublished',
352
- TrackUnpublished = 'trackUnpublished',
353
- TrackSubscribed = 'trackSubscribed',
354
- TrackUnsubscribed = 'trackUnsubscribed',
355
- TrackSubscriptionFailed = 'trackSubscriptionFailed',
356
- TrackMuted = 'trackMuted',
357
- TrackUnmuted = 'trackUnmuted',
358
- ActiveSpeakersChanged = 'activeSpeakersChanged',
359
- RoomMetadataChanged = 'roomMetadataChanged',
360
- ParticipantMetadataChanged = 'participantMetadataChanged',
361
- ParticipantNameChanged = 'participantNameChanged',
362
- ConnectionQualityChanged = 'connectionQualityChanged',
363
- DataReceived = 'dataReceived',
364
- E2EEStateChanged = 'e2eeStateChanged',
365
- ConenctionStateChanged = 'connectionStateChanged',
366
- Connected = 'connected',
367
- Disconnected = 'disconnected',
368
- Reconnecting = 'reconnecting',
369
- Reconnected = 'reconnected',
370
- }
package/src/track.ts DELETED
@@ -1,101 +0,0 @@
1
- import { AudioSource } from './audio_source';
2
- import { FfiClient, FfiHandle, FfiRequest } from './ffi_client';
3
- import {
4
- CreateAudioTrackRequest,
5
- CreateAudioTrackResponse,
6
- CreateVideoTrackRequest,
7
- CreateVideoTrackResponse,
8
- OwnedTrack,
9
- StreamState,
10
- TrackInfo,
11
- TrackKind,
12
- } from './proto/track_pb';
13
- import { VideoSource } from './video_source';
14
-
15
- export abstract class Track {
16
- /** @internal */
17
- info: TrackInfo;
18
-
19
- /** @internal */
20
- ffi_handle: FfiHandle;
21
-
22
- constructor(owned: OwnedTrack) {
23
- this.info = owned.info;
24
- this.ffi_handle = new FfiHandle(owned.handle.id);
25
- }
26
-
27
- get sid(): string {
28
- return this.info.sid;
29
- }
30
-
31
- get name(): string {
32
- return this.info.name;
33
- }
34
-
35
- get kind(): TrackKind {
36
- return this.info.kind;
37
- }
38
-
39
- get stream_state(): StreamState {
40
- return this.info.streamState;
41
- }
42
-
43
- get muted(): boolean {
44
- return this.info.muted;
45
- }
46
- }
47
-
48
- export class LocalAudioTrack extends Track {
49
- constructor(owned: OwnedTrack) {
50
- super(owned);
51
- }
52
-
53
- static createAudioTrack(name: string, source: AudioSource): LocalAudioTrack {
54
- let req = new CreateAudioTrackRequest({
55
- name: name,
56
- sourceHandle: source.ffiHandle.handle,
57
- });
58
-
59
- let res = FfiClient.instance.request<CreateAudioTrackResponse>({
60
- message: { case: 'createAudioTrack', value: req },
61
- });
62
-
63
- return new LocalAudioTrack(res.track);
64
- }
65
- }
66
-
67
- export class LocalVideoTrack extends Track {
68
- constructor(owned: OwnedTrack) {
69
- super(owned);
70
- }
71
-
72
- static createVideoTrack(name: string, source: VideoSource): LocalVideoTrack {
73
- let req = new CreateVideoTrackRequest({
74
- name: name,
75
- sourceHandle: source.ffiHandle.handle,
76
- });
77
-
78
- let res = FfiClient.instance.request<CreateVideoTrackResponse>({
79
- message: { case: 'createVideoTrack', value: req },
80
- });
81
-
82
- return new LocalVideoTrack(res.track);
83
- }
84
- }
85
-
86
- export class RemoteVideoTrack extends Track {
87
- constructor(owned: OwnedTrack) {
88
- super(owned);
89
- }
90
- }
91
-
92
- export class RemoteAudioTrack extends Track {
93
- constructor(owned: OwnedTrack) {
94
- super(owned);
95
- }
96
- }
97
-
98
- export type LocalTrack = LocalVideoTrack | LocalAudioTrack;
99
- export type RemoteTrack = RemoteVideoTrack | RemoteAudioTrack;
100
- export type AudioTrack = LocalAudioTrack | RemoteAudioTrack;
101
- export type VideoTrack = LocalVideoTrack | RemoteVideoTrack;
@@ -1,90 +0,0 @@
1
- import { FfiClient, FfiRequest } from './ffi_client';
2
- import { FfiHandle } from './native';
3
- import { EncryptionType } from './proto/e2ee_pb';
4
- import { SetSubscribedRequest, SetSubscribedResponse } from './proto/room_pb';
5
- import {
6
- OwnedTrackPublication,
7
- TrackKind,
8
- TrackPublicationInfo,
9
- TrackSource,
10
- } from './proto/track_pb';
11
- import { Track } from './track';
12
-
13
- export abstract class TrackPublication {
14
- /** @internal */
15
- ffiHandle: FfiHandle;
16
-
17
- /** @internal */
18
- info: TrackPublicationInfo;
19
- track?: Track;
20
-
21
- constructor(ownedInfo: OwnedTrackPublication) {
22
- this.info = ownedInfo.info;
23
- this.ffiHandle = new FfiHandle(ownedInfo.handle.id);
24
- }
25
-
26
- get sid(): string {
27
- return this.info.sid;
28
- }
29
-
30
- get name(): string {
31
- return this.info.name;
32
- }
33
-
34
- get kind(): TrackKind {
35
- return this.info.kind;
36
- }
37
-
38
- get source(): TrackSource {
39
- return this.info.source;
40
- }
41
-
42
- get simulcasted(): boolean {
43
- return this.info.simulcasted;
44
- }
45
-
46
- get width(): number {
47
- return this.info.width;
48
- }
49
-
50
- get height(): number {
51
- return this.info.height;
52
- }
53
-
54
- get mimeType(): string {
55
- return this.info.mimeType;
56
- }
57
-
58
- get muted(): boolean {
59
- return this.info.muted;
60
- }
61
-
62
- get encryptionType(): EncryptionType {
63
- return this.info.encryptionType;
64
- }
65
- }
66
-
67
- export class LocalTrackPublication extends TrackPublication {
68
- constructor(ownedInfo: OwnedTrackPublication) {
69
- super(ownedInfo);
70
- }
71
- }
72
-
73
- export class RemoteTrackPublication extends TrackPublication {
74
- subscribed: boolean = false;
75
-
76
- constructor(ownedInfo: OwnedTrackPublication) {
77
- super(ownedInfo);
78
- }
79
-
80
- setSubscribed(subscribed: boolean) {
81
- let req = new SetSubscribedRequest({
82
- subscribe: subscribed,
83
- publicationHandle: this.ffiHandle.handle,
84
- });
85
-
86
- FfiClient.instance.request<SetSubscribedResponse>({
87
- message: { case: 'setSubscribed', value: req },
88
- });
89
- }
90
- }