livekit-client 1.12.0 → 1.12.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/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"}
|