livekit-client 1.12.0 → 1.12.2
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +19 -1
- package/dist/livekit-client.e2ee.worker.js +1 -1
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs +442 -334
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +12303 -14499
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/api/SignalClient.d.ts +2 -2
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/connectionHelper/ConnectionCheck.d.ts +3 -2
- package/dist/src/connectionHelper/ConnectionCheck.d.ts.map +1 -1
- package/dist/src/connectionHelper/checks/Checker.d.ts +3 -2
- package/dist/src/connectionHelper/checks/Checker.d.ts.map +1 -1
- package/dist/src/connectionHelper/checks/webrtc.d.ts.map +1 -1
- package/dist/src/connectionHelper/checks/websocket.d.ts.map +1 -1
- package/dist/src/e2ee/E2eeManager.d.ts +4 -2
- package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
- package/dist/src/e2ee/KeyProvider.d.ts +4 -2
- package/dist/src/e2ee/KeyProvider.d.ts.map +1 -1
- package/dist/src/e2ee/constants.d.ts +1 -0
- package/dist/src/e2ee/constants.d.ts.map +1 -1
- package/dist/src/e2ee/types.d.ts +1 -0
- package/dist/src/e2ee/types.d.ts.map +1 -1
- package/dist/src/e2ee/worker/FrameCryptor.d.ts +4 -3
- package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
- package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts +21 -2
- package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/proto/livekit_models_pb.d.ts +1264 -0
- package/dist/src/proto/livekit_models_pb.d.ts.map +1 -0
- package/dist/src/proto/livekit_rtc_pb.d.ts +1373 -0
- package/dist/src/proto/livekit_rtc_pb.d.ts.map +1 -0
- package/dist/src/room/PCTransport.d.ts +2 -1
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +9 -5
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/RegionUrlProvider.d.ts +4 -1
- package/dist/src/room/RegionUrlProvider.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +15 -11
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +2 -2
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/Participant.d.ts +5 -3
- package/dist/src/room/participant/Participant.d.ts.map +1 -1
- package/dist/src/room/participant/ParticipantTrackPermission.d.ts +1 -1
- package/dist/src/room/participant/ParticipantTrackPermission.d.ts.map +1 -1
- package/dist/src/room/participant/RemoteParticipant.d.ts +8 -7
- package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
- package/dist/src/room/timers.d.ts +5 -4
- package/dist/src/room/timers.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrack.d.ts +3 -0
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrackPublication.d.ts +1 -1
- package/dist/src/room/track/LocalTrackPublication.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts +2 -2
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteTrackPublication.d.ts +1 -1
- package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +6 -4
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/room/track/TrackPublication.d.ts +7 -5
- package/dist/src/room/track/TrackPublication.d.ts.map +1 -1
- package/dist/src/room/track/create.d.ts.map +1 -1
- package/dist/src/room/track/options.d.ts +7 -0
- package/dist/src/room/track/options.d.ts.map +1 -1
- package/dist/src/room/track/utils.d.ts +5 -1
- package/dist/src/room/track/utils.d.ts.map +1 -1
- package/dist/src/room/utils.d.ts +3 -1
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/src/test/mocks.d.ts +4 -3
- package/dist/src/test/mocks.d.ts.map +1 -1
- package/dist/src/utils/browserParser.d.ts +2 -0
- package/dist/src/utils/browserParser.d.ts.map +1 -1
- package/dist/ts4.2/src/api/SignalClient.d.ts +2 -2
- package/dist/ts4.2/src/connectionHelper/ConnectionCheck.d.ts +3 -2
- package/dist/ts4.2/src/connectionHelper/checks/Checker.d.ts +3 -2
- package/dist/ts4.2/src/e2ee/E2eeManager.d.ts +4 -2
- package/dist/ts4.2/src/e2ee/KeyProvider.d.ts +4 -2
- package/dist/ts4.2/src/e2ee/constants.d.ts +1 -0
- package/dist/ts4.2/src/e2ee/types.d.ts +1 -0
- package/dist/ts4.2/src/e2ee/worker/FrameCryptor.d.ts +4 -3
- package/dist/ts4.2/src/e2ee/worker/ParticipantKeyHandler.d.ts +21 -2
- package/dist/ts4.2/src/index.d.ts +1 -1
- package/dist/ts4.2/src/proto/livekit_models_pb.d.ts +1264 -0
- package/dist/ts4.2/src/proto/livekit_rtc_pb.d.ts +1373 -0
- package/dist/ts4.2/src/room/PCTransport.d.ts +2 -1
- package/dist/ts4.2/src/room/RTCEngine.d.ts +9 -5
- package/dist/ts4.2/src/room/RegionUrlProvider.d.ts +4 -1
- package/dist/ts4.2/src/room/Room.d.ts +15 -11
- package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +2 -2
- package/dist/ts4.2/src/room/participant/Participant.d.ts +5 -3
- package/dist/ts4.2/src/room/participant/ParticipantTrackPermission.d.ts +1 -1
- package/dist/ts4.2/src/room/participant/RemoteParticipant.d.ts +8 -7
- package/dist/ts4.2/src/room/timers.d.ts +5 -4
- package/dist/ts4.2/src/room/track/LocalTrack.d.ts +3 -0
- package/dist/ts4.2/src/room/track/LocalTrackPublication.d.ts +1 -1
- package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +2 -2
- package/dist/ts4.2/src/room/track/RemoteTrackPublication.d.ts +1 -1
- package/dist/ts4.2/src/room/track/Track.d.ts +6 -4
- package/dist/ts4.2/src/room/track/TrackPublication.d.ts +7 -5
- package/dist/ts4.2/src/room/track/options.d.ts +7 -0
- package/dist/ts4.2/src/room/track/utils.d.ts +5 -1
- package/dist/ts4.2/src/room/utils.d.ts +3 -1
- package/dist/ts4.2/src/test/mocks.d.ts +4 -3
- package/dist/ts4.2/src/utils/browserParser.d.ts +2 -0
- package/package.json +10 -10
- package/src/api/SignalClient.ts +104 -101
- package/src/connectionHelper/ConnectionCheck.ts +3 -2
- package/src/connectionHelper/checks/Checker.ts +3 -3
- package/src/connectionHelper/checks/webrtc.ts +66 -2
- package/src/connectionHelper/checks/websocket.ts +4 -0
- package/src/e2ee/E2eeManager.ts +4 -3
- package/src/e2ee/KeyProvider.ts +3 -2
- package/src/e2ee/constants.ts +4 -0
- package/src/e2ee/types.ts +1 -0
- package/src/e2ee/worker/FrameCryptor.test.ts +1 -3
- package/src/e2ee/worker/FrameCryptor.ts +14 -16
- package/src/e2ee/worker/ParticipantKeyHandler.ts +48 -2
- package/src/e2ee/worker/e2ee.worker.ts +12 -6
- package/src/index.ts +1 -1
- package/src/proto/livekit_models_pb.ts +2096 -0
- package/src/proto/livekit_rtc_pb.ts +2332 -0
- package/src/room/PCTransport.ts +1 -1
- package/src/room/RTCEngine.ts +24 -18
- package/src/room/RegionUrlProvider.ts +11 -2
- package/src/room/Room.test.ts +1 -0
- package/src/room/Room.ts +175 -86
- package/src/room/participant/LocalParticipant.ts +43 -59
- package/src/room/participant/Participant.ts +6 -4
- package/src/room/participant/ParticipantTrackPermission.ts +3 -3
- package/src/room/participant/RemoteParticipant.ts +24 -21
- package/src/room/participant/publishUtils.test.ts +1 -0
- package/src/room/track/LocalTrack.ts +24 -9
- package/src/room/track/LocalTrackPublication.ts +1 -1
- package/src/room/track/LocalVideoTrack.test.ts +2 -1
- package/src/room/track/LocalVideoTrack.ts +22 -22
- package/src/room/track/RemoteTrackPublication.ts +12 -7
- package/src/room/track/RemoteVideoTrack.test.ts +5 -4
- package/src/room/track/Track.ts +9 -6
- package/src/room/track/TrackPublication.ts +7 -5
- package/src/room/track/create.ts +18 -17
- package/src/room/track/facingMode.test.ts +1 -0
- package/src/room/track/options.ts +6 -0
- package/src/room/track/utils.test.ts +1 -0
- package/src/room/track/utils.ts +44 -2
- package/src/room/utils.test.ts +16 -0
- package/src/room/utils.ts +20 -4
- package/src/test/mocks.ts +7 -5
- package/src/utils/AsyncQueue.test.ts +1 -0
- package/src/utils/browserParser.test.ts +33 -3
- package/src/utils/browserParser.ts +5 -0
- package/dist/src/proto/google/protobuf/timestamp.d.ts +0 -146
- package/dist/src/proto/google/protobuf/timestamp.d.ts.map +0 -1
- package/dist/src/proto/livekit_models.d.ts +0 -2399
- package/dist/src/proto/livekit_models.d.ts.map +0 -1
- package/dist/src/proto/livekit_rtc.d.ts +0 -14352
- package/dist/src/proto/livekit_rtc.d.ts.map +0 -1
- package/dist/ts4.2/src/proto/google/protobuf/timestamp.d.ts +0 -150
- package/dist/ts4.2/src/proto/livekit_models.d.ts +0 -2659
- package/dist/ts4.2/src/proto/livekit_rtc.d.ts +0 -15764
- package/src/proto/google/protobuf/timestamp.ts +0 -230
- package/src/proto/livekit_models.ts +0 -4006
- package/src/proto/livekit_rtc.ts +0 -4672
package/src/room/track/Track.ts
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
import EventEmitter from '
|
1
|
+
import { EventEmitter } from 'events';
|
2
|
+
import type TypedEventEmitter from 'typed-emitter';
|
2
3
|
import type { SignalClient } from '../../api/SignalClient';
|
3
4
|
import log from '../../logger';
|
4
|
-
import { TrackSource, TrackType } from '../../proto/
|
5
|
-
import { StreamState as ProtoStreamState } from '../../proto/
|
5
|
+
import { TrackSource, TrackType } from '../../proto/livekit_models_pb';
|
6
|
+
import { StreamState as ProtoStreamState } from '../../proto/livekit_rtc_pb';
|
6
7
|
import { TrackEvent } from '../events';
|
7
8
|
import { isFireFox, isSafari, isWeb } from '../utils';
|
8
9
|
|
@@ -12,7 +13,7 @@ const BACKGROUND_REACTION_DELAY = 5000;
|
|
12
13
|
// Safari tracks which audio elements have been "blessed" by the user.
|
13
14
|
const recycledElements: Array<HTMLAudioElement> = [];
|
14
15
|
|
15
|
-
export abstract class Track extends EventEmitter<TrackEventCallbacks> {
|
16
|
+
export abstract class Track extends (EventEmitter as new () => TypedEventEmitter<TrackEventCallbacks>) {
|
16
17
|
kind: Track.Kind;
|
17
18
|
|
18
19
|
attachedElements: HTMLMediaElement[] = [];
|
@@ -51,6 +52,7 @@ export abstract class Track extends EventEmitter<TrackEventCallbacks> {
|
|
51
52
|
|
52
53
|
protected constructor(mediaTrack: MediaStreamTrack, kind: Track.Kind) {
|
53
54
|
super();
|
55
|
+
this.setMaxListeners(100);
|
54
56
|
this.kind = kind;
|
55
57
|
this._mediaStreamTrack = mediaTrack;
|
56
58
|
this._mediaStreamID = mediaTrack.id;
|
@@ -368,7 +370,8 @@ export namespace Track {
|
|
368
370
|
case Kind.Video:
|
369
371
|
return TrackType.VIDEO;
|
370
372
|
default:
|
371
|
-
|
373
|
+
// FIXME this was UNRECOGNIZED before
|
374
|
+
return TrackType.DATA;
|
372
375
|
}
|
373
376
|
}
|
374
377
|
|
@@ -396,7 +399,7 @@ export namespace Track {
|
|
396
399
|
case Source.ScreenShareAudio:
|
397
400
|
return TrackSource.SCREEN_SHARE_AUDIO;
|
398
401
|
default:
|
399
|
-
return TrackSource.
|
402
|
+
return TrackSource.UNKNOWN;
|
400
403
|
}
|
401
404
|
}
|
402
405
|
|
@@ -1,8 +1,9 @@
|
|
1
|
-
import EventEmitter from '
|
1
|
+
import { EventEmitter } from 'events';
|
2
|
+
import type TypedEventEmitter from 'typed-emitter';
|
2
3
|
import log from '../../logger';
|
3
|
-
import { Encryption_Type } from '../../proto/
|
4
|
-
import type { SubscriptionError, TrackInfo } from '../../proto/
|
5
|
-
import type { UpdateSubscription, UpdateTrackSettings } from '../../proto/
|
4
|
+
import { Encryption_Type } from '../../proto/livekit_models_pb';
|
5
|
+
import type { SubscriptionError, TrackInfo } from '../../proto/livekit_models_pb';
|
6
|
+
import type { UpdateSubscription, UpdateTrackSettings } from '../../proto/livekit_rtc_pb';
|
6
7
|
import { TrackEvent } from '../events';
|
7
8
|
import LocalAudioTrack from './LocalAudioTrack';
|
8
9
|
import LocalVideoTrack from './LocalVideoTrack';
|
@@ -11,7 +12,7 @@ import type RemoteTrack from './RemoteTrack';
|
|
11
12
|
import RemoteVideoTrack from './RemoteVideoTrack';
|
12
13
|
import { Track } from './Track';
|
13
14
|
|
14
|
-
export class TrackPublication extends EventEmitter<PublicationEventCallbacks> {
|
15
|
+
export class TrackPublication extends (EventEmitter as new () => TypedEventEmitter<PublicationEventCallbacks>) {
|
15
16
|
kind: Track.Kind;
|
16
17
|
|
17
18
|
trackName: string;
|
@@ -40,6 +41,7 @@ export class TrackPublication extends EventEmitter<PublicationEventCallbacks> {
|
|
40
41
|
|
41
42
|
constructor(kind: Track.Kind, id: string, name: string) {
|
42
43
|
super();
|
44
|
+
this.setMaxListeners(100);
|
43
45
|
this.kind = kind;
|
44
46
|
this.trackSid = id;
|
45
47
|
this.trackName = name;
|
package/src/room/track/create.ts
CHANGED
@@ -6,14 +6,18 @@ import LocalAudioTrack from './LocalAudioTrack';
|
|
6
6
|
import type LocalTrack from './LocalTrack';
|
7
7
|
import LocalVideoTrack from './LocalVideoTrack';
|
8
8
|
import { Track } from './Track';
|
9
|
-
import {
|
9
|
+
import { ScreenSharePresets } from './options';
|
10
10
|
import type {
|
11
11
|
AudioCaptureOptions,
|
12
12
|
CreateLocalTracksOptions,
|
13
13
|
ScreenShareCaptureOptions,
|
14
14
|
VideoCaptureOptions,
|
15
15
|
} from './options';
|
16
|
-
import {
|
16
|
+
import {
|
17
|
+
constraintsForOptions,
|
18
|
+
mergeDefaultOptions,
|
19
|
+
screenCaptureToDisplayMediaStreamOptions,
|
20
|
+
} from './utils';
|
17
21
|
|
18
22
|
/**
|
19
23
|
* Creates a local video and audio track at the same time. When acquiring both
|
@@ -57,6 +61,15 @@ export async function createLocalTracks(
|
|
57
61
|
if (typeof conOrBool !== 'boolean') {
|
58
62
|
trackConstraints = conOrBool;
|
59
63
|
}
|
64
|
+
|
65
|
+
// update the constraints with the device id the user gave permissions to in the permission prompt
|
66
|
+
// otherwise each track restart (e.g. mute - unmute) will try to initialize the device again -> causing additional permission prompts
|
67
|
+
if (trackConstraints) {
|
68
|
+
trackConstraints.deviceId = mediaStreamTrack.getSettings().deviceId;
|
69
|
+
} else {
|
70
|
+
trackConstraints = { deviceId: mediaStreamTrack.getSettings().deviceId };
|
71
|
+
}
|
72
|
+
|
60
73
|
const track = mediaTrackToLocalTrack(mediaStreamTrack, trackConstraints);
|
61
74
|
if (track.kind === Track.Kind.Video) {
|
62
75
|
track.source = Track.Source.Camera;
|
@@ -104,27 +117,15 @@ export async function createLocalScreenTracks(
|
|
104
117
|
options = {};
|
105
118
|
}
|
106
119
|
if (options.resolution === undefined) {
|
107
|
-
options.resolution =
|
108
|
-
}
|
109
|
-
|
110
|
-
let videoConstraints: MediaTrackConstraints | boolean = true;
|
111
|
-
if (options.resolution) {
|
112
|
-
videoConstraints = {
|
113
|
-
width: options.resolution.width,
|
114
|
-
height: options.resolution.height,
|
115
|
-
};
|
120
|
+
options.resolution = ScreenSharePresets.h1080fps15.resolution;
|
116
121
|
}
|
117
122
|
|
118
123
|
if (navigator.mediaDevices.getDisplayMedia === undefined) {
|
119
124
|
throw new DeviceUnsupportedError('getDisplayMedia not supported');
|
120
125
|
}
|
121
126
|
|
122
|
-
|
123
|
-
|
124
|
-
const stream: MediaStream = await navigator.mediaDevices.getDisplayMedia({
|
125
|
-
audio: options.audio ?? false,
|
126
|
-
video: videoConstraints,
|
127
|
-
});
|
127
|
+
const constraints = screenCaptureToDisplayMediaStreamOptions(options);
|
128
|
+
const stream: MediaStream = await navigator.mediaDevices.getDisplayMedia(constraints);
|
128
129
|
|
129
130
|
const tracks = stream.getVideoTracks();
|
130
131
|
if (tracks.length === 0) {
|
@@ -147,6 +147,12 @@ export interface ScreenShareCaptureOptions {
|
|
147
147
|
*/
|
148
148
|
audio?: boolean | AudioCaptureOptions;
|
149
149
|
|
150
|
+
/**
|
151
|
+
* only allows for 'true' and chrome allows for additional options to be passed in
|
152
|
+
* https://developer.chrome.com/docs/web-platform/screen-sharing-controls/#displaySurface
|
153
|
+
*/
|
154
|
+
video?: true | { displaySurface?: 'window' | 'browser' | 'monitor' };
|
155
|
+
|
150
156
|
/** capture resolution, defaults to full HD */
|
151
157
|
resolution?: VideoResolution;
|
152
158
|
|
package/src/room/track/utils.ts
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
-
import { sleep } from '../utils';
|
1
|
+
import { isSafari, sleep } from '../utils';
|
2
2
|
import { Track } from './Track';
|
3
|
-
import type {
|
3
|
+
import type {
|
4
|
+
AudioCaptureOptions,
|
5
|
+
CreateLocalTracksOptions,
|
6
|
+
ScreenShareCaptureOptions,
|
7
|
+
VideoCaptureOptions,
|
8
|
+
} from './options';
|
4
9
|
import type { AudioTrack } from './types';
|
5
10
|
|
6
11
|
export function mergeDefaultOptions(
|
@@ -139,3 +144,40 @@ export function sourceToKind(source: Track.Source): MediaDeviceKind | undefined
|
|
139
144
|
return undefined;
|
140
145
|
}
|
141
146
|
}
|
147
|
+
|
148
|
+
/**
|
149
|
+
* @internal
|
150
|
+
*/
|
151
|
+
export function screenCaptureToDisplayMediaStreamOptions(
|
152
|
+
options: ScreenShareCaptureOptions,
|
153
|
+
): DisplayMediaStreamOptions {
|
154
|
+
let videoConstraints: MediaTrackConstraints | boolean = options.video ?? true;
|
155
|
+
if (options.resolution) {
|
156
|
+
videoConstraints = typeof videoConstraints === 'boolean' ? {} : videoConstraints;
|
157
|
+
if (isSafari()) {
|
158
|
+
videoConstraints = {
|
159
|
+
...videoConstraints,
|
160
|
+
width: { max: options.resolution.width },
|
161
|
+
height: { max: options.resolution.height },
|
162
|
+
frameRate: options.resolution.frameRate,
|
163
|
+
};
|
164
|
+
} else {
|
165
|
+
videoConstraints = {
|
166
|
+
...videoConstraints,
|
167
|
+
width: { ideal: options.resolution.width },
|
168
|
+
height: { ideal: options.resolution.height },
|
169
|
+
frameRate: options.resolution.frameRate,
|
170
|
+
};
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
return {
|
175
|
+
audio: options.audio ?? false,
|
176
|
+
video: videoConstraints,
|
177
|
+
// @ts-expect-error support for experimental display media features
|
178
|
+
controller: options.controller,
|
179
|
+
selfBrowserSurface: options.selfBrowserSurface,
|
180
|
+
surfaceSwitching: options.surfaceSwitching,
|
181
|
+
systemAudio: options.systemAudio,
|
182
|
+
};
|
183
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
2
|
+
import { toWebsocketUrl } from './utils';
|
3
|
+
|
4
|
+
describe('toWebsocketUrl', () => {
|
5
|
+
it('leaves wss urls alone', () => {
|
6
|
+
expect(toWebsocketUrl('ws://mywebsite.com')).toEqual('ws://mywebsite.com');
|
7
|
+
});
|
8
|
+
|
9
|
+
it('converts https to wss', () => {
|
10
|
+
expect(toWebsocketUrl('https://mywebsite.com')).toEqual('wss://mywebsite.com');
|
11
|
+
});
|
12
|
+
|
13
|
+
it('does not convert other parts of URL', () => {
|
14
|
+
expect(toWebsocketUrl('https://httpsmywebsite.com')).toEqual('wss://httpsmywebsite.com');
|
15
|
+
});
|
16
|
+
});
|
package/src/room/utils.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
import { ClientInfo, ClientInfo_SDK } from '../proto/
|
2
|
-
import { getBrowser } from '../utils/browserParser';
|
1
|
+
import { ClientInfo, ClientInfo_SDK } from '../proto/livekit_models_pb';
|
3
2
|
import type { DetectableBrowser } from '../utils/browserParser';
|
3
|
+
import { getBrowser } from '../utils/browserParser';
|
4
4
|
import { protocolVersion, version } from '../version';
|
5
5
|
import type LocalAudioTrack from './track/LocalAudioTrack';
|
6
6
|
import type RemoteAudioTrack from './track/RemoteAudioTrack';
|
@@ -148,7 +148,9 @@ export function isReactNative(): boolean {
|
|
148
148
|
}
|
149
149
|
|
150
150
|
export function isCloud(serverUrl: URL) {
|
151
|
-
return
|
151
|
+
return (
|
152
|
+
serverUrl.hostname.endsWith('.livekit.cloud') || serverUrl.hostname.endsWith('.livekit.run')
|
153
|
+
);
|
152
154
|
}
|
153
155
|
|
154
156
|
function getLKReactNativeInfo(): LiveKitReactNativeInfo | undefined {
|
@@ -244,7 +246,7 @@ export interface ObservableMediaElement extends HTMLMediaElement {
|
|
244
246
|
}
|
245
247
|
|
246
248
|
export function getClientInfo(): ClientInfo {
|
247
|
-
const info = ClientInfo
|
249
|
+
const info = new ClientInfo({
|
248
250
|
sdk: ClientInfo_SDK.JS,
|
249
251
|
protocol: protocolVersion,
|
250
252
|
version,
|
@@ -483,3 +485,17 @@ export function unwrapConstraint(constraint: ConstrainDOMString): string {
|
|
483
485
|
}
|
484
486
|
throw Error('could not unwrap constraint');
|
485
487
|
}
|
488
|
+
|
489
|
+
export function toWebsocketUrl(url: string): string {
|
490
|
+
if (url.startsWith('http')) {
|
491
|
+
return url.replace(/^(http)/, 'ws');
|
492
|
+
}
|
493
|
+
return url;
|
494
|
+
}
|
495
|
+
|
496
|
+
export function toHttpUrl(url: string): string {
|
497
|
+
if (url.startsWith('ws')) {
|
498
|
+
return url.replace(/^(ws)/, 'http');
|
499
|
+
}
|
500
|
+
return url;
|
501
|
+
}
|
package/src/test/mocks.ts
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
2
|
+
import { MockedClass, vi } from 'vitest';
|
1
3
|
import { SignalClient } from '../api/SignalClient';
|
2
4
|
import RTCEngine from '../room/RTCEngine';
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
+
vi.mock('../api/SignalClient');
|
7
|
+
vi.mock('../room/RTCEngine');
|
6
8
|
|
7
9
|
// mock helpers for testing
|
8
10
|
|
9
11
|
const mocks = {
|
10
|
-
SignalClient: SignalClient as
|
11
|
-
RTCEngine: RTCEngine as
|
12
|
+
SignalClient: SignalClient as MockedClass<typeof SignalClient>,
|
13
|
+
RTCEngine: RTCEngine as MockedClass<typeof RTCEngine>,
|
12
14
|
MockLocalVideoTrack: {
|
13
|
-
stop:
|
15
|
+
stop: vi.fn(),
|
14
16
|
},
|
15
17
|
};
|
16
18
|
|
@@ -1,33 +1,63 @@
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
1
2
|
import { compareVersions } from '../room/utils';
|
2
3
|
import { getBrowser } from './browserParser';
|
3
4
|
|
4
5
|
describe('browser parser', () => {
|
5
|
-
const
|
6
|
+
const macOSSafariUA =
|
6
7
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Safari/605.1.15';
|
8
|
+
|
9
|
+
const iOSSafariUA =
|
10
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1';
|
11
|
+
|
7
12
|
const firefoxUA =
|
8
13
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/112.0';
|
9
14
|
|
15
|
+
const iOSFirefoxUA =
|
16
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/115.0 Mobile/15E148 Safari/605.1.15';
|
17
|
+
|
10
18
|
const chromeUA =
|
11
19
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36';
|
12
20
|
|
21
|
+
const iOSChromeUA =
|
22
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/115.0.5790.130 Mobile/15E148 Safari/604.11';
|
23
|
+
|
13
24
|
const braveUA =
|
14
25
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36';
|
15
26
|
|
16
|
-
it('parses Safari correctly', () => {
|
17
|
-
const details = getBrowser(
|
27
|
+
it('parses Safari macOS correctly', () => {
|
28
|
+
const details = getBrowser(macOSSafariUA, true);
|
18
29
|
expect(details?.name).toBe('Safari');
|
19
30
|
expect(details?.version).toBe('16.3');
|
31
|
+
expect(details?.os).toBe('macOS');
|
32
|
+
});
|
33
|
+
it('parses Safari iOS correctly', () => {
|
34
|
+
const details = getBrowser(iOSSafariUA, true);
|
35
|
+
expect(details?.name).toBe('Safari');
|
36
|
+
expect(details?.version).toBe('16.5');
|
37
|
+
expect(details?.os).toBe('iOS');
|
20
38
|
});
|
21
39
|
it('parses Firefox correctly', () => {
|
22
40
|
const details = getBrowser(firefoxUA, true);
|
23
41
|
expect(details?.name).toBe('Firefox');
|
24
42
|
expect(details?.version).toBe('112.0');
|
25
43
|
});
|
44
|
+
it('parses iOS Firefox correctly', () => {
|
45
|
+
const details = getBrowser(iOSFirefoxUA, true);
|
46
|
+
expect(details?.name).toBe('Firefox');
|
47
|
+
expect(details?.version).toBe('115.0');
|
48
|
+
expect(details?.os).toBe('iOS');
|
49
|
+
});
|
26
50
|
it('parses Chrome correctly', () => {
|
27
51
|
const details = getBrowser(chromeUA, true);
|
28
52
|
expect(details?.name).toBe('Chrome');
|
29
53
|
expect(details?.version).toBe('112.0.0.0');
|
30
54
|
});
|
55
|
+
it('parses iOS Chrome correctly', () => {
|
56
|
+
const details = getBrowser(iOSChromeUA, true);
|
57
|
+
expect(details?.name).toBe('Chrome');
|
58
|
+
expect(details?.version).toBe('115.0.5790.130');
|
59
|
+
expect(details?.os).toBe('iOS');
|
60
|
+
});
|
31
61
|
it('detects brave as chromium based', () => {
|
32
62
|
const details = getBrowser(braveUA, true);
|
33
63
|
expect(details?.name).toBe('Chrome');
|
@@ -4,10 +4,12 @@
|
|
4
4
|
const commonVersionIdentifier = /version\/(\d+(\.?_?\d+)+)/i;
|
5
5
|
|
6
6
|
export type DetectableBrowser = 'Chrome' | 'Firefox' | 'Safari';
|
7
|
+
export type DetectableOS = 'iOS' | 'macOS';
|
7
8
|
|
8
9
|
export type BrowserDetails = {
|
9
10
|
name: DetectableBrowser;
|
10
11
|
version: string;
|
12
|
+
os?: DetectableOS;
|
11
13
|
};
|
12
14
|
|
13
15
|
let browserDetails: BrowserDetails | undefined;
|
@@ -34,6 +36,7 @@ const browsersList = [
|
|
34
36
|
const browser: BrowserDetails = {
|
35
37
|
name: 'Firefox',
|
36
38
|
version: getMatch(/(?:firefox|iceweasel|fxios)[\s/](\d+(\.?_?\d+)+)/i, ua),
|
39
|
+
os: ua.toLowerCase().includes('fxios') ? 'iOS' : undefined,
|
37
40
|
};
|
38
41
|
return browser;
|
39
42
|
},
|
@@ -44,6 +47,7 @@ const browsersList = [
|
|
44
47
|
const browser: BrowserDetails = {
|
45
48
|
name: 'Chrome',
|
46
49
|
version: getMatch(/(?:chrome|chromium|crios|crmo)\/(\d+(\.?_?\d+)+)/i, ua),
|
50
|
+
os: ua.toLowerCase().includes('crios') ? 'iOS' : undefined,
|
47
51
|
};
|
48
52
|
|
49
53
|
return browser;
|
@@ -56,6 +60,7 @@ const browsersList = [
|
|
56
60
|
const browser: BrowserDetails = {
|
57
61
|
name: 'Safari',
|
58
62
|
version: getMatch(commonVersionIdentifier, ua),
|
63
|
+
os: ua.includes('mobile/') ? 'iOS' : 'macOS',
|
59
64
|
};
|
60
65
|
|
61
66
|
return browser;
|
@@ -1,146 +0,0 @@
|
|
1
|
-
import _m0 from "protobufjs/minimal";
|
2
|
-
export declare const protobufPackage = "google.protobuf";
|
3
|
-
/**
|
4
|
-
* A Timestamp represents a point in time independent of any time zone or local
|
5
|
-
* calendar, encoded as a count of seconds and fractions of seconds at
|
6
|
-
* nanosecond resolution. The count is relative to an epoch at UTC midnight on
|
7
|
-
* January 1, 1970, in the proleptic Gregorian calendar which extends the
|
8
|
-
* Gregorian calendar backwards to year one.
|
9
|
-
*
|
10
|
-
* All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
|
11
|
-
* second table is needed for interpretation, using a [24-hour linear
|
12
|
-
* smear](https://developers.google.com/time/smear).
|
13
|
-
*
|
14
|
-
* The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
|
15
|
-
* restricting to that range, we ensure that we can convert to and from [RFC
|
16
|
-
* 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
|
17
|
-
*
|
18
|
-
* # Examples
|
19
|
-
*
|
20
|
-
* Example 1: Compute Timestamp from POSIX `time()`.
|
21
|
-
*
|
22
|
-
* Timestamp timestamp;
|
23
|
-
* timestamp.set_seconds(time(NULL));
|
24
|
-
* timestamp.set_nanos(0);
|
25
|
-
*
|
26
|
-
* Example 2: Compute Timestamp from POSIX `gettimeofday()`.
|
27
|
-
*
|
28
|
-
* struct timeval tv;
|
29
|
-
* gettimeofday(&tv, NULL);
|
30
|
-
*
|
31
|
-
* Timestamp timestamp;
|
32
|
-
* timestamp.set_seconds(tv.tv_sec);
|
33
|
-
* timestamp.set_nanos(tv.tv_usec * 1000);
|
34
|
-
*
|
35
|
-
* Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
|
36
|
-
*
|
37
|
-
* FILETIME ft;
|
38
|
-
* GetSystemTimeAsFileTime(&ft);
|
39
|
-
* UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
40
|
-
*
|
41
|
-
* // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
|
42
|
-
* // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
|
43
|
-
* Timestamp timestamp;
|
44
|
-
* timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
|
45
|
-
* timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
|
46
|
-
*
|
47
|
-
* Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
|
48
|
-
*
|
49
|
-
* long millis = System.currentTimeMillis();
|
50
|
-
*
|
51
|
-
* Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
|
52
|
-
* .setNanos((int) ((millis % 1000) * 1000000)).build();
|
53
|
-
*
|
54
|
-
* Example 5: Compute Timestamp from Java `Instant.now()`.
|
55
|
-
*
|
56
|
-
* Instant now = Instant.now();
|
57
|
-
*
|
58
|
-
* Timestamp timestamp =
|
59
|
-
* Timestamp.newBuilder().setSeconds(now.getEpochSecond())
|
60
|
-
* .setNanos(now.getNano()).build();
|
61
|
-
*
|
62
|
-
* Example 6: Compute Timestamp from current time in Python.
|
63
|
-
*
|
64
|
-
* timestamp = Timestamp()
|
65
|
-
* timestamp.GetCurrentTime()
|
66
|
-
*
|
67
|
-
* # JSON Mapping
|
68
|
-
*
|
69
|
-
* In JSON format, the Timestamp type is encoded as a string in the
|
70
|
-
* [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
|
71
|
-
* format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
|
72
|
-
* where {year} is always expressed using four digits while {month}, {day},
|
73
|
-
* {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
|
74
|
-
* seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
|
75
|
-
* are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
|
76
|
-
* is required. A proto3 JSON serializer should always use UTC (as indicated by
|
77
|
-
* "Z") when printing the Timestamp type and a proto3 JSON parser should be
|
78
|
-
* able to accept both UTC and other timezones (as indicated by an offset).
|
79
|
-
*
|
80
|
-
* For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
|
81
|
-
* 01:30 UTC on January 15, 2017.
|
82
|
-
*
|
83
|
-
* In JavaScript, one can convert a Date object to this format using the
|
84
|
-
* standard
|
85
|
-
* [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
|
86
|
-
* method. In Python, a standard `datetime.datetime` object can be converted
|
87
|
-
* to this format using
|
88
|
-
* [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
|
89
|
-
* the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
|
90
|
-
* the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
91
|
-
* http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
|
92
|
-
* ) to obtain a formatter capable of generating timestamps in this format.
|
93
|
-
*/
|
94
|
-
export interface Timestamp {
|
95
|
-
/**
|
96
|
-
* Represents seconds of UTC time since Unix epoch
|
97
|
-
* 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
|
98
|
-
* 9999-12-31T23:59:59Z inclusive.
|
99
|
-
*/
|
100
|
-
seconds: number;
|
101
|
-
/**
|
102
|
-
* Non-negative fractions of a second at nanosecond resolution. Negative
|
103
|
-
* second values with fractions must still have non-negative nanos values
|
104
|
-
* that count forward in time. Must be from 0 to 999,999,999
|
105
|
-
* inclusive.
|
106
|
-
*/
|
107
|
-
nanos: number;
|
108
|
-
}
|
109
|
-
export declare const Timestamp: {
|
110
|
-
encode(message: Timestamp, writer?: _m0.Writer): _m0.Writer;
|
111
|
-
decode(input: _m0.Reader | Uint8Array, length?: number): Timestamp;
|
112
|
-
fromJSON(object: any): Timestamp;
|
113
|
-
toJSON(message: Timestamp): unknown;
|
114
|
-
create<I extends {
|
115
|
-
seconds?: number | undefined;
|
116
|
-
nanos?: number | undefined;
|
117
|
-
} & {
|
118
|
-
seconds?: number | undefined;
|
119
|
-
nanos?: number | undefined;
|
120
|
-
} & { [K in Exclude<keyof I, keyof Timestamp>]: never; }>(base?: I | undefined): Timestamp;
|
121
|
-
fromPartial<I_1 extends {
|
122
|
-
seconds?: number | undefined;
|
123
|
-
nanos?: number | undefined;
|
124
|
-
} & {
|
125
|
-
seconds?: number | undefined;
|
126
|
-
nanos?: number | undefined;
|
127
|
-
} & { [K_1 in Exclude<keyof I_1, keyof Timestamp>]: never; }>(object: I_1): Timestamp;
|
128
|
-
};
|
129
|
-
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
130
|
-
export type DeepPartial<T> = T extends Builtin ? T : T extends Array<infer U> ? Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : T extends {
|
131
|
-
$case: string;
|
132
|
-
} ? {
|
133
|
-
[K in keyof Omit<T, "$case">]?: DeepPartial<T[K]>;
|
134
|
-
} & {
|
135
|
-
$case: T["$case"];
|
136
|
-
} : T extends {} ? {
|
137
|
-
[K in keyof T]?: DeepPartial<T[K]>;
|
138
|
-
} : Partial<T>;
|
139
|
-
type KeysOfUnion<T> = T extends T ? keyof T : never;
|
140
|
-
export type Exact<P, I extends P> = P extends Builtin ? P : P & {
|
141
|
-
[K in keyof P]: Exact<P[K], I[K]>;
|
142
|
-
} & {
|
143
|
-
[K in Exclude<keyof I, KeysOfUnion<P>>]: never;
|
144
|
-
};
|
145
|
-
export {};
|
146
|
-
//# sourceMappingURL=timestamp.d.ts.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"timestamp.d.ts","sourceRoot":"","sources":["../../../../../src/proto/google/protobuf/timestamp.ts"],"names":[],"mappings":"AAEA,OAAO,GAAG,MAAM,oBAAoB,CAAC;AAErC,eAAO,MAAM,eAAe,oBAAoB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0FG;AACH,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAMD,eAAO,MAAM,SAAS;oBACJ,SAAS,WAAU,IAAI,MAAM,GAAyB,IAAI,MAAM;kBAUlE,IAAI,MAAM,GAAG,UAAU,WAAW,MAAM,GAAG,SAAS;qBA8BjD,GAAG,GAAG,SAAS;oBAOhB,SAAS,GAAG,OAAO;;;;;;;qFAO2B,SAAS;;;;;;;gFAIH,SAAS;CAM9E,CAAC;AAqBF,KAAK,OAAO,GAAG,IAAI,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAEpF,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,GAAG,CAAC,GAC9C,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GACnH,CAAC,SAAS;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;KAAG,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GAAG;IAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;CAAE,GAC3G,CAAC,SAAS,EAAE,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GACrD,OAAO,CAAC,CAAC,CAAC,CAAC;AAEf,KAAK,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC;AACpD,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,OAAO,GAAG,CAAC,GACrD,CAAC,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GAAG;KAAG,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK;CAAE,CAAC"}
|