livekit-client 1.4.4 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. package/dist/livekit-client.esm.mjs +2478 -5368
  2. package/dist/livekit-client.esm.mjs.map +1 -1
  3. package/dist/livekit-client.umd.js +1 -1
  4. package/dist/livekit-client.umd.js.map +1 -1
  5. package/dist/src/api/SignalClient.d.ts +3 -2
  6. package/dist/src/api/SignalClient.d.ts.map +1 -1
  7. package/dist/src/connectionHelper/ConnectionCheck.d.ts +25 -0
  8. package/dist/src/connectionHelper/ConnectionCheck.d.ts.map +1 -0
  9. package/dist/src/connectionHelper/checks/Checker.d.ts +59 -0
  10. package/dist/src/connectionHelper/checks/Checker.d.ts.map +1 -0
  11. package/dist/src/connectionHelper/checks/publishAudio.d.ts +6 -0
  12. package/dist/src/connectionHelper/checks/publishAudio.d.ts.map +1 -0
  13. package/dist/src/connectionHelper/checks/publishVideo.d.ts +6 -0
  14. package/dist/src/connectionHelper/checks/publishVideo.d.ts.map +1 -0
  15. package/dist/src/connectionHelper/checks/reconnect.d.ts +6 -0
  16. package/dist/src/connectionHelper/checks/reconnect.d.ts.map +1 -0
  17. package/dist/src/connectionHelper/checks/turn.d.ts +6 -0
  18. package/dist/src/connectionHelper/checks/turn.d.ts.map +1 -0
  19. package/dist/src/connectionHelper/checks/webrtc.d.ts +6 -0
  20. package/dist/src/connectionHelper/checks/webrtc.d.ts.map +1 -0
  21. package/dist/src/connectionHelper/checks/websocket.d.ts +6 -0
  22. package/dist/src/connectionHelper/checks/websocket.d.ts.map +1 -0
  23. package/dist/src/index.d.ts +6 -3
  24. package/dist/src/index.d.ts.map +1 -1
  25. package/dist/src/logger.d.ts +3 -3
  26. package/dist/src/logger.d.ts.map +1 -1
  27. package/dist/src/options.d.ts +4 -1
  28. package/dist/src/options.d.ts.map +1 -1
  29. package/dist/src/proto/google/protobuf/timestamp.d.ts +4 -4
  30. package/dist/src/proto/google/protobuf/timestamp.d.ts.map +1 -1
  31. package/dist/src/proto/livekit_models.d.ts +4 -4
  32. package/dist/src/proto/livekit_models.d.ts.map +1 -1
  33. package/dist/src/proto/livekit_rtc.d.ts +12 -4
  34. package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
  35. package/dist/src/room/DeviceManager.d.ts.map +1 -1
  36. package/dist/src/room/RTCEngine.d.ts +4 -3
  37. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  38. package/dist/src/room/Room.d.ts +27 -4
  39. package/dist/src/room/Room.d.ts.map +1 -1
  40. package/dist/src/room/events.d.ts +9 -1
  41. package/dist/src/room/events.d.ts.map +1 -1
  42. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  43. package/dist/src/room/participant/Participant.d.ts +1 -1
  44. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  45. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  46. package/dist/src/room/track/RemoteTrackPublication.d.ts +2 -0
  47. package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -1
  48. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  49. package/dist/src/room/track/Track.d.ts +2 -1
  50. package/dist/src/room/track/Track.d.ts.map +1 -1
  51. package/dist/src/room/track/TrackPublication.d.ts +1 -1
  52. package/dist/src/room/track/TrackPublication.d.ts.map +1 -1
  53. package/dist/src/room/track/options.d.ts +3 -3
  54. package/dist/src/room/track/options.d.ts.map +1 -1
  55. package/dist/src/room/track/types.d.ts +3 -3
  56. package/dist/src/room/track/types.d.ts.map +1 -1
  57. package/dist/src/room/types.d.ts +13 -0
  58. package/dist/src/room/types.d.ts.map +1 -0
  59. package/dist/src/room/utils.d.ts +44 -0
  60. package/dist/src/room/utils.d.ts.map +1 -1
  61. package/dist/ts4.2/src/api/SignalClient.d.ts +86 -0
  62. package/dist/ts4.2/src/connectionHelper/ConnectionCheck.d.ts +25 -0
  63. package/dist/ts4.2/src/connectionHelper/checks/Checker.d.ts +59 -0
  64. package/dist/ts4.2/src/connectionHelper/checks/publishAudio.d.ts +6 -0
  65. package/dist/ts4.2/src/connectionHelper/checks/publishVideo.d.ts +6 -0
  66. package/dist/ts4.2/src/connectionHelper/checks/reconnect.d.ts +6 -0
  67. package/dist/ts4.2/src/connectionHelper/checks/turn.d.ts +6 -0
  68. package/dist/ts4.2/src/connectionHelper/checks/webrtc.d.ts +6 -0
  69. package/dist/ts4.2/src/connectionHelper/checks/websocket.d.ts +6 -0
  70. package/dist/ts4.2/src/index.d.ts +31 -0
  71. package/dist/ts4.2/src/logger.d.ts +26 -0
  72. package/dist/ts4.2/src/options.d.ts +94 -0
  73. package/dist/ts4.2/src/proto/google/protobuf/timestamp.d.ts +141 -0
  74. package/dist/ts4.2/src/proto/livekit_models.d.ts +1421 -0
  75. package/dist/ts4.2/src/proto/livekit_rtc.d.ts +7122 -0
  76. package/dist/ts4.2/src/room/DefaultReconnectPolicy.d.ts +8 -0
  77. package/dist/ts4.2/src/room/DeviceManager.d.ts +9 -0
  78. package/dist/ts4.2/src/room/PCTransport.d.ts +33 -0
  79. package/dist/ts4.2/src/room/RTCEngine.d.ts +97 -0
  80. package/dist/ts4.2/src/room/ReconnectPolicy.d.ts +23 -0
  81. package/dist/ts4.2/src/room/Room.d.ts +220 -0
  82. package/dist/ts4.2/src/room/defaults.d.ts +8 -0
  83. package/dist/ts4.2/src/room/errors.d.ts +39 -0
  84. package/dist/ts4.2/src/room/events.d.ts +426 -0
  85. package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +141 -0
  86. package/dist/ts4.2/src/room/participant/Participant.d.ts +92 -0
  87. package/dist/ts4.2/src/room/participant/ParticipantTrackPermission.d.ts +26 -0
  88. package/dist/ts4.2/src/room/participant/RemoteParticipant.d.ts +52 -0
  89. package/dist/ts4.2/src/room/participant/publishUtils.d.ts +19 -0
  90. package/dist/ts4.2/src/room/stats.d.ts +67 -0
  91. package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +25 -0
  92. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +42 -0
  93. package/dist/ts4.2/src/room/track/LocalTrackPublication.d.ts +38 -0
  94. package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +53 -0
  95. package/dist/ts4.2/src/room/track/RemoteAudioTrack.d.ts +53 -0
  96. package/dist/ts4.2/src/room/track/RemoteTrack.d.ts +15 -0
  97. package/dist/ts4.2/src/room/track/RemoteTrackPublication.d.ts +61 -0
  98. package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +52 -0
  99. package/dist/ts4.2/src/room/track/Track.d.ts +122 -0
  100. package/dist/ts4.2/src/room/track/TrackPublication.d.ts +68 -0
  101. package/dist/ts4.2/src/room/track/create.d.ts +24 -0
  102. package/dist/ts4.2/src/room/track/options.d.ts +241 -0
  103. package/dist/ts4.2/src/room/track/types.d.ts +23 -0
  104. package/dist/ts4.2/src/room/track/utils.d.ts +14 -0
  105. package/dist/ts4.2/src/room/types.d.ts +13 -0
  106. package/dist/ts4.2/src/room/utils.d.ts +79 -0
  107. package/dist/ts4.2/src/test/MockMediaStreamTrack.d.ts +26 -0
  108. package/dist/ts4.2/src/test/mocks.d.ts +11 -0
  109. package/dist/ts4.2/src/version.d.ts +3 -0
  110. package/package.json +32 -22
  111. package/src/api/SignalClient.ts +41 -17
  112. package/src/connectionHelper/ConnectionCheck.ts +90 -0
  113. package/src/connectionHelper/checks/Checker.ts +164 -0
  114. package/src/connectionHelper/checks/publishAudio.ts +33 -0
  115. package/src/connectionHelper/checks/publishVideo.ts +33 -0
  116. package/src/connectionHelper/checks/reconnect.ts +45 -0
  117. package/src/connectionHelper/checks/turn.ts +53 -0
  118. package/src/connectionHelper/checks/webrtc.ts +18 -0
  119. package/src/connectionHelper/checks/websocket.ts +22 -0
  120. package/src/index.ts +8 -1
  121. package/src/options.ts +5 -1
  122. package/src/proto/livekit_rtc.ts +12 -1
  123. package/src/room/DeviceManager.ts +0 -17
  124. package/src/room/RTCEngine.ts +35 -26
  125. package/src/room/Room.ts +231 -63
  126. package/src/room/events.ts +9 -0
  127. package/src/room/participant/LocalParticipant.ts +18 -11
  128. package/src/room/participant/publishUtils.ts +1 -1
  129. package/src/room/track/LocalAudioTrack.ts +1 -1
  130. package/src/room/track/LocalTrack.ts +4 -0
  131. package/src/room/track/LocalVideoTrack.ts +1 -1
  132. package/src/room/track/RemoteTrackPublication.ts +20 -0
  133. package/src/room/track/RemoteVideoTrack.ts +4 -0
  134. package/src/room/track/Track.ts +1 -0
  135. package/src/room/types.ts +12 -0
  136. package/src/room/utils.ts +150 -12
@@ -0,0 +1,90 @@
1
+ import EventEmitter from 'events';
2
+ import type TypedEmitter from 'typed-emitter';
3
+
4
+ import { Checker, CheckInfo, CheckStatus, InstantiableCheck } from './checks/Checker';
5
+ import { PublishAudioCheck } from './checks/publishAudio';
6
+ import { PublishVideoCheck } from './checks/publishVideo';
7
+ import { ReconnectCheck } from './checks/reconnect';
8
+ import { TURNCheck } from './checks/turn';
9
+ import { WebRTCCheck } from './checks/webrtc';
10
+ import { WebSocketCheck } from './checks/websocket';
11
+
12
+ export type { CheckInfo };
13
+
14
+ export class ConnectionCheck extends (EventEmitter as new () => TypedEmitter<ConnectionCheckCallbacks>) {
15
+ token: string;
16
+
17
+ url: string;
18
+
19
+ private checkResults: Map<number, CheckInfo> = new Map();
20
+
21
+ constructor(url: string, token: string) {
22
+ super();
23
+ this.url = url;
24
+ this.token = token;
25
+ }
26
+
27
+ private getNextCheckId() {
28
+ const nextId = this.checkResults.size;
29
+ this.checkResults.set(nextId, {
30
+ logs: [],
31
+ status: CheckStatus.IDLE,
32
+ name: '',
33
+ description: '',
34
+ });
35
+ return nextId;
36
+ }
37
+
38
+ private updateCheck(checkId: number, info: CheckInfo) {
39
+ this.checkResults.set(checkId, info);
40
+ this.emit('checkUpdate', checkId, info);
41
+ }
42
+
43
+ isSuccess() {
44
+ return Array.from(this.checkResults.values()).every((r) => r.status !== CheckStatus.FAILED);
45
+ }
46
+
47
+ getResults() {
48
+ return Array.from(this.checkResults.values());
49
+ }
50
+
51
+ async createAndRunCheck<T extends Checker>(check: InstantiableCheck<T>) {
52
+ const checkId = this.getNextCheckId();
53
+ const test = new check(this.url, this.token);
54
+ const handleUpdate = (info: CheckInfo) => {
55
+ this.updateCheck(checkId, info);
56
+ };
57
+ test.on('update', handleUpdate);
58
+ const result = await test.run();
59
+ test.off('update', handleUpdate);
60
+ return result;
61
+ }
62
+
63
+ async checkWebsocket() {
64
+ return this.createAndRunCheck(WebSocketCheck);
65
+ }
66
+
67
+ async checkWebRTC() {
68
+ return this.createAndRunCheck(WebRTCCheck);
69
+ }
70
+
71
+ async checkTURN() {
72
+ return this.createAndRunCheck(TURNCheck);
73
+ }
74
+
75
+ async checkReconnect() {
76
+ return this.createAndRunCheck(ReconnectCheck);
77
+ }
78
+
79
+ async checkPublishAudio() {
80
+ return this.createAndRunCheck(PublishAudioCheck);
81
+ }
82
+
83
+ async checkPublishVideo() {
84
+ return this.createAndRunCheck(PublishVideoCheck);
85
+ }
86
+ }
87
+
88
+ type ConnectionCheckCallbacks = {
89
+ checkUpdate: (id: number, info: CheckInfo) => void;
90
+ };
@@ -0,0 +1,164 @@
1
+ import { EventEmitter } from 'events';
2
+ import type TypedEmitter from 'typed-emitter';
3
+ import type { RoomConnectOptions, RoomOptions } from '../../options';
4
+ import Room, { ConnectionState } from '../../room/Room';
5
+ import type RTCEngine from '../../room/RTCEngine';
6
+
7
+ type LogMessage = {
8
+ level: 'info' | 'warning' | 'error';
9
+ message: string;
10
+ };
11
+
12
+ export enum CheckStatus {
13
+ IDLE,
14
+ RUNNING,
15
+ SKIPPED,
16
+ SUCCESS,
17
+ FAILED,
18
+ }
19
+
20
+ export type CheckInfo = {
21
+ name: string;
22
+ logs: Array<LogMessage>;
23
+ status: CheckStatus;
24
+ description: string;
25
+ };
26
+
27
+ export interface CheckerOptions {
28
+ errorsAsWarnings?: boolean;
29
+ roomOptions?: RoomOptions;
30
+ connectOptions?: RoomConnectOptions;
31
+ }
32
+
33
+ export abstract class Checker extends (EventEmitter as new () => TypedEmitter<CheckerCallbacks>) {
34
+ protected url: string;
35
+
36
+ protected token: string;
37
+
38
+ room: Room;
39
+
40
+ connectOptions?: RoomConnectOptions;
41
+
42
+ status: CheckStatus = CheckStatus.IDLE;
43
+
44
+ logs: Array<LogMessage> = [];
45
+
46
+ errorsAsWarnings: boolean = false;
47
+
48
+ name: string;
49
+
50
+ constructor(url: string, token: string, options: CheckerOptions = {}) {
51
+ super();
52
+ this.url = url;
53
+ this.token = token;
54
+ this.name = this.constructor.name;
55
+ this.room = new Room(options.roomOptions);
56
+ this.connectOptions = options.connectOptions;
57
+ if (options.errorsAsWarnings) {
58
+ this.errorsAsWarnings = options.errorsAsWarnings;
59
+ }
60
+ }
61
+
62
+ abstract get description(): string;
63
+
64
+ protected abstract perform(): Promise<void>;
65
+
66
+ async run(onComplete?: () => void) {
67
+ if (this.status !== CheckStatus.IDLE) {
68
+ throw Error('check is running already');
69
+ }
70
+ this.setStatus(CheckStatus.RUNNING);
71
+ this.appendMessage(`${this.name} started.`);
72
+
73
+ try {
74
+ await this.perform();
75
+ } catch (err) {
76
+ if (err instanceof Error) {
77
+ if (this.errorsAsWarnings) {
78
+ this.appendWarning(err.message);
79
+ } else {
80
+ this.appendError(err.message);
81
+ }
82
+ }
83
+ }
84
+
85
+ await this.disconnect();
86
+
87
+ // sleep for a bit to ensure disconnect
88
+ await new Promise((resolve) => setTimeout(resolve, 500));
89
+
90
+ // @ts-ignore
91
+ if (this.status !== CheckStatus.SKIPPED) {
92
+ this.setStatus(this.isSuccess() ? CheckStatus.SUCCESS : CheckStatus.FAILED);
93
+ }
94
+
95
+ if (onComplete) {
96
+ onComplete();
97
+ }
98
+ return this.getInfo();
99
+ }
100
+
101
+ protected isSuccess(): boolean {
102
+ return !this.logs.some((l) => l.level === 'error');
103
+ }
104
+
105
+ protected async connect(): Promise<Room> {
106
+ if (this.room.state === ConnectionState.Connected) {
107
+ return this.room;
108
+ }
109
+ await this.room.connect(this.url, this.token);
110
+ return this.room;
111
+ }
112
+
113
+ protected async disconnect() {
114
+ if (this.room && this.room.state !== ConnectionState.Disconnected) {
115
+ await this.room.disconnect();
116
+ // wait for it to go through
117
+ await new Promise((resolve) => setTimeout(resolve, 500));
118
+ }
119
+ }
120
+
121
+ protected skip() {
122
+ this.setStatus(CheckStatus.SKIPPED);
123
+ }
124
+
125
+ protected appendMessage(message: string) {
126
+ this.logs.push({ level: 'info', message });
127
+ this.emit('update', this.getInfo());
128
+ }
129
+
130
+ protected appendWarning(message: string) {
131
+ this.logs.push({ level: 'warning', message });
132
+ this.emit('update', this.getInfo());
133
+ }
134
+
135
+ protected appendError(message: string) {
136
+ this.logs.push({ level: 'error', message });
137
+ this.emit('update', this.getInfo());
138
+ }
139
+
140
+ protected setStatus(status: CheckStatus) {
141
+ this.status = status;
142
+ this.emit('update', this.getInfo());
143
+ }
144
+
145
+ protected get engine(): RTCEngine | undefined {
146
+ return this.room?.engine;
147
+ }
148
+
149
+ getInfo(): CheckInfo {
150
+ return {
151
+ logs: this.logs,
152
+ name: this.name,
153
+ status: this.status,
154
+ description: this.description,
155
+ };
156
+ }
157
+ }
158
+ export type InstantiableCheck<T extends Checker> = {
159
+ new (url: string, token: string, options?: CheckerOptions): T;
160
+ };
161
+
162
+ type CheckerCallbacks = {
163
+ update: (info: CheckInfo) => void;
164
+ };
@@ -0,0 +1,33 @@
1
+ import { createLocalAudioTrack } from '../../room/track/create';
2
+ import { Checker } from './Checker';
3
+
4
+ export class PublishAudioCheck extends Checker {
5
+ get description(): string {
6
+ return 'Can publish audio';
7
+ }
8
+
9
+ async perform(): Promise<void> {
10
+ const room = await this.connect();
11
+
12
+ const track = await createLocalAudioTrack();
13
+ room.localParticipant.publishTrack(track);
14
+ // wait for a few seconds to publish
15
+ await new Promise((resolve) => setTimeout(resolve, 3000));
16
+
17
+ // verify RTC stats that it's publishing
18
+ const stats = await track.sender?.getStats();
19
+ if (!stats) {
20
+ throw new Error('Could not get RTCStats');
21
+ }
22
+ let numPackets = 0;
23
+ stats.forEach((stat) => {
24
+ if (stat.type === 'outbound-rtp' && stat.mediaType === 'audio') {
25
+ numPackets = stat.packetsSent;
26
+ }
27
+ });
28
+ if (numPackets === 0) {
29
+ throw new Error('Could not determine packets are sent');
30
+ }
31
+ this.appendMessage(`published ${numPackets} audio packets`);
32
+ }
33
+ }
@@ -0,0 +1,33 @@
1
+ import { createLocalVideoTrack } from '../../room/track/create';
2
+ import { Checker } from './Checker';
3
+
4
+ export class PublishVideoCheck extends Checker {
5
+ get description(): string {
6
+ return 'Can publish video';
7
+ }
8
+
9
+ async perform(): Promise<void> {
10
+ const room = await this.connect();
11
+
12
+ const track = await createLocalVideoTrack();
13
+ room.localParticipant.publishTrack(track);
14
+ // wait for a few seconds to publish
15
+ await new Promise((resolve) => setTimeout(resolve, 3000));
16
+
17
+ // verify RTC stats that it's publishing
18
+ const stats = await track.sender?.getStats();
19
+ if (!stats) {
20
+ throw new Error('Could not get RTCStats');
21
+ }
22
+ let numPackets = 0;
23
+ stats.forEach((stat) => {
24
+ if (stat.type === 'outbound-rtp' && stat.mediaType === 'video') {
25
+ numPackets = stat.packetsSent;
26
+ }
27
+ });
28
+ if (numPackets === 0) {
29
+ throw new Error('Could not determine packets are sent');
30
+ }
31
+ this.appendMessage(`published ${numPackets} video packets`);
32
+ }
33
+ }
@@ -0,0 +1,45 @@
1
+ import { RoomEvent } from '../../room/events';
2
+ import { ConnectionState } from '../../room/Room';
3
+ import { Checker } from './Checker';
4
+
5
+ export class ReconnectCheck extends Checker {
6
+ get description(): string {
7
+ return 'Resuming connection after interruption';
8
+ }
9
+
10
+ async perform(): Promise<void> {
11
+ const room = await this.connect();
12
+ let reconnectingTriggered = false;
13
+ let reconnected = false;
14
+
15
+ let reconnectResolver: (value: unknown) => void;
16
+ const reconnectTimeout = new Promise((resolve) => {
17
+ setTimeout(resolve, 5000);
18
+ reconnectResolver = resolve;
19
+ });
20
+
21
+ room
22
+ .on(RoomEvent.Reconnecting, () => {
23
+ reconnectingTriggered = true;
24
+ })
25
+ .on(RoomEvent.Reconnected, () => {
26
+ reconnected = true;
27
+ reconnectResolver(true);
28
+ });
29
+
30
+ room.engine.client.ws?.close();
31
+ const onClose = room.engine.client.onClose;
32
+ if (onClose) {
33
+ onClose('');
34
+ }
35
+
36
+ await reconnectTimeout;
37
+
38
+ if (!reconnectingTriggered) {
39
+ throw new Error('Did not attempt to reconnect');
40
+ } else if (!reconnected || room.state !== ConnectionState.Connected) {
41
+ this.appendWarning('reconnection is only possible in Redis-based configurations');
42
+ throw new Error('Not able to reconnect');
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,53 @@
1
+ import { SignalClient } from '../../api/SignalClient';
2
+ import { Checker } from './Checker';
3
+
4
+ export class TURNCheck extends Checker {
5
+ get description(): string {
6
+ return 'Can connect via TURN';
7
+ }
8
+
9
+ async perform(): Promise<void> {
10
+ const signalClient = new SignalClient();
11
+ const joinRes = await signalClient.join(this.url, this.token, {
12
+ autoSubscribe: true,
13
+ maxRetries: 0,
14
+ });
15
+
16
+ let hasTLS = false;
17
+ let hasTURN = false;
18
+ let hasSTUN = false;
19
+
20
+ for (let iceServer of joinRes.iceServers) {
21
+ for (let url of iceServer.urls) {
22
+ if (url.startsWith('turn:')) {
23
+ hasTURN = true;
24
+ hasSTUN = true;
25
+ } else if (url.startsWith('turns:')) {
26
+ hasTURN = true;
27
+ hasSTUN = true;
28
+ hasTLS = true;
29
+ }
30
+ if (url.startsWith('stun:')) {
31
+ hasSTUN = true;
32
+ }
33
+ }
34
+ }
35
+ if (!hasSTUN) {
36
+ this.appendWarning('No STUN servers configured on server side.');
37
+ } else if (hasTURN && !hasTLS) {
38
+ this.appendWarning('TURN is configured server side, but TURN/TLS is unavailable.');
39
+ }
40
+ await signalClient.close();
41
+ if (this.connectOptions?.rtcConfig?.iceServers || hasTURN) {
42
+ await this.room!.connect(this.url, this.token, {
43
+ rtcConfig: {
44
+ iceTransportPolicy: 'relay',
45
+ },
46
+ });
47
+ } else {
48
+ this.appendWarning('No TURN servers configured.');
49
+ this.skip();
50
+ await new Promise((resolve) => setTimeout(resolve, 0));
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,18 @@
1
+ import { Checker } from './Checker';
2
+
3
+ export class WebRTCCheck extends Checker {
4
+ get description(): string {
5
+ return 'Establishing WebRTC connection';
6
+ }
7
+
8
+ protected async perform(): Promise<void> {
9
+ try {
10
+ console.log('initiating room connection');
11
+ this.room = await this.connect();
12
+ console.log('now the room is connected');
13
+ } catch (err) {
14
+ this.appendWarning('ports need to be open on firewall in order to connect.');
15
+ throw err;
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,22 @@
1
+ import { SignalClient } from '../../api/SignalClient';
2
+ import { Checker } from './Checker';
3
+
4
+ export class WebSocketCheck extends Checker {
5
+ get description(): string {
6
+ return 'Connecting to signal connection via WebSocket';
7
+ }
8
+
9
+ protected async perform(): Promise<void> {
10
+ if (this.url.startsWith('ws:') || this.url.startsWith('http:')) {
11
+ this.appendWarning('Server is insecure, clients may block connections to it');
12
+ }
13
+
14
+ let signalClient = new SignalClient();
15
+ const joinRes = await signalClient.join(this.url, this.token, {
16
+ autoSubscribe: true,
17
+ maxRetries: 0,
18
+ });
19
+ this.appendMessage(`Connected to server, version ${joinRes.serverVersion}.`);
20
+ await signalClient.close();
21
+ }
22
+ }
package/src/index.ts CHANGED
@@ -13,7 +13,8 @@ import LocalVideoTrack from './room/track/LocalVideoTrack';
13
13
  import RemoteAudioTrack from './room/track/RemoteAudioTrack';
14
14
  import RemoteTrack from './room/track/RemoteTrack';
15
15
  import RemoteTrackPublication from './room/track/RemoteTrackPublication';
16
- import RemoteVideoTrack, { type ElementInfo } from './room/track/RemoteVideoTrack';
16
+ import RemoteVideoTrack from './room/track/RemoteVideoTrack';
17
+ import type { ElementInfo } from './room/track/RemoteVideoTrack';
17
18
  import { TrackPublication } from './room/track/TrackPublication';
18
19
  import {
19
20
  getEmptyAudioStreamTrack,
@@ -22,8 +23,11 @@ import {
22
23
  supportsAdaptiveStream,
23
24
  supportsAV1,
24
25
  supportsDynacast,
26
+ createAudioAnalyser,
25
27
  } from './room/utils';
26
28
 
29
+ import type { AudioAnalyserOptions } from './room/utils';
30
+
27
31
  export * from './options';
28
32
  export * from './room/errors';
29
33
  export * from './room/events';
@@ -32,6 +36,7 @@ export * from './room/track/options';
32
36
  export * from './room/track/Track';
33
37
  export * from './room/track/types';
34
38
  export * from './version';
39
+ export * from './connectionHelper/ConnectionCheck';
35
40
  export {
36
41
  setLogLevel,
37
42
  setLogExtension,
@@ -41,6 +46,8 @@ export {
41
46
  supportsAdaptiveStream,
42
47
  supportsDynacast,
43
48
  supportsAV1,
49
+ createAudioAnalyser,
50
+ AudioAnalyserOptions,
44
51
  LogLevel,
45
52
  Room,
46
53
  ConnectionState,
package/src/options.ts CHANGED
@@ -7,6 +7,10 @@ import type {
7
7
  } from './room/track/options';
8
8
  import type { AdaptiveStreamSettings } from './room/track/types';
9
9
 
10
+ export interface WebAudioSettings {
11
+ audioContext: AudioContext;
12
+ }
13
+
10
14
  /**
11
15
  * @internal
12
16
  */
@@ -72,7 +76,7 @@ export interface InternalRoomOptions {
72
76
  * experimental flag, mix all audio tracks in web audio
73
77
  */
74
78
 
75
- expWebAudioMix: boolean;
79
+ expWebAudioMix: boolean | WebAudioSettings;
76
80
  }
77
81
 
78
82
  /**
@@ -267,6 +267,8 @@ export interface UpdateTrackSettings {
267
267
  width: number;
268
268
  /** for video, height to receive */
269
269
  height: number;
270
+ /** for video, frame rate to receive */
271
+ fps: number;
270
272
  }
271
273
 
272
274
  export interface LeaveRequest {
@@ -1843,7 +1845,7 @@ export const UpdateSubscription = {
1843
1845
  };
1844
1846
 
1845
1847
  function createBaseUpdateTrackSettings(): UpdateTrackSettings {
1846
- return { trackSids: [], disabled: false, quality: 0, width: 0, height: 0 };
1848
+ return { trackSids: [], disabled: false, quality: 0, width: 0, height: 0, fps: 0 };
1847
1849
  }
1848
1850
 
1849
1851
  export const UpdateTrackSettings = {
@@ -1863,6 +1865,9 @@ export const UpdateTrackSettings = {
1863
1865
  if (message.height !== 0) {
1864
1866
  writer.uint32(48).uint32(message.height);
1865
1867
  }
1868
+ if (message.fps !== 0) {
1869
+ writer.uint32(56).uint32(message.fps);
1870
+ }
1866
1871
  return writer;
1867
1872
  },
1868
1873
 
@@ -1888,6 +1893,9 @@ export const UpdateTrackSettings = {
1888
1893
  case 6:
1889
1894
  message.height = reader.uint32();
1890
1895
  break;
1896
+ case 7:
1897
+ message.fps = reader.uint32();
1898
+ break;
1891
1899
  default:
1892
1900
  reader.skipType(tag & 7);
1893
1901
  break;
@@ -1903,6 +1911,7 @@ export const UpdateTrackSettings = {
1903
1911
  quality: isSet(object.quality) ? videoQualityFromJSON(object.quality) : 0,
1904
1912
  width: isSet(object.width) ? Number(object.width) : 0,
1905
1913
  height: isSet(object.height) ? Number(object.height) : 0,
1914
+ fps: isSet(object.fps) ? Number(object.fps) : 0,
1906
1915
  };
1907
1916
  },
1908
1917
 
@@ -1917,6 +1926,7 @@ export const UpdateTrackSettings = {
1917
1926
  message.quality !== undefined && (obj.quality = videoQualityToJSON(message.quality));
1918
1927
  message.width !== undefined && (obj.width = Math.round(message.width));
1919
1928
  message.height !== undefined && (obj.height = Math.round(message.height));
1929
+ message.fps !== undefined && (obj.fps = Math.round(message.fps));
1920
1930
  return obj;
1921
1931
  },
1922
1932
 
@@ -1927,6 +1937,7 @@ export const UpdateTrackSettings = {
1927
1937
  message.quality = object.quality ?? 0;
1928
1938
  message.width = object.width ?? 0;
1929
1939
  message.height = object.height ?? 0;
1940
+ message.fps = object.fps ?? 0;
1930
1941
  return message;
1931
1942
  },
1932
1943
  };
@@ -65,23 +65,6 @@ export default class DeviceManager {
65
65
  devices = devices.filter((device) => device.kind === kind);
66
66
  }
67
67
 
68
- // Chrome returns 'default' devices, we would filter them out, but put the default
69
- // device at first
70
- // we would only do this if there are more than 1 device though
71
- if (devices.length > 1 && devices[0].deviceId === defaultId) {
72
- // find another device with matching group id, and move that to 0
73
- const defaultDevice = devices[0];
74
- for (let i = 1; i < devices.length; i += 1) {
75
- if (devices[i].groupId === defaultDevice.groupId) {
76
- const temp = devices[0];
77
- devices[0] = devices[i];
78
- devices[i] = temp;
79
- break;
80
- }
81
- }
82
- return devices.filter((device) => device !== defaultDevice);
83
- }
84
-
85
68
  return devices;
86
69
  }
87
70