livekit-client 2.0.10 → 2.1.0
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/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 +203 -140
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +3876 -6838
- 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 -1
- 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/e2ee/worker/FrameCryptor.d.ts.map +1 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +1 -0
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +5 -1
- package/dist/src/room/events.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +1 -0
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts +7 -0
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrackPublication.d.ts +3 -2
- package/dist/src/room/track/LocalTrackPublication.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +2 -1
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/room/track/options.d.ts +1 -1
- package/dist/src/room/track/options.d.ts.map +1 -1
- package/dist/src/room/utils.d.ts +3 -0
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/ts4.2/src/api/SignalClient.d.ts +2 -1
- package/dist/ts4.2/src/connectionHelper/ConnectionCheck.d.ts +3 -2
- package/dist/ts4.2/src/index.d.ts +3 -2
- package/dist/ts4.2/src/room/RTCEngine.d.ts +1 -0
- package/dist/ts4.2/src/room/events.d.ts +5 -1
- package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +1 -0
- package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +7 -0
- package/dist/ts4.2/src/room/track/LocalTrackPublication.d.ts +3 -2
- package/dist/ts4.2/src/room/track/Track.d.ts +2 -1
- package/dist/ts4.2/src/room/track/options.d.ts +1 -1
- package/dist/ts4.2/src/room/utils.d.ts +3 -0
- package/package.json +10 -10
- package/src/api/SignalClient.ts +9 -0
- package/src/connectionHelper/ConnectionCheck.ts +6 -3
- package/src/e2ee/worker/FrameCryptor.ts +0 -1
- package/src/e2ee/worker/e2ee.worker.ts +3 -1
- package/src/index.ts +3 -0
- package/src/room/RTCEngine.ts +11 -1
- package/src/room/events.ts +5 -0
- package/src/room/participant/LocalParticipant.ts +14 -0
- package/src/room/participant/publishUtils.ts +2 -1
- package/src/room/track/LocalAudioTrack.ts +40 -0
- package/src/room/track/LocalTrackPublication.ts +28 -2
- package/src/room/track/LocalVideoTrack.ts +7 -3
- package/src/room/track/Track.ts +13 -0
- package/src/room/track/options.ts +22 -1
- package/src/room/utils.ts +3 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "livekit-client",
|
3
|
-
"version": "2.0
|
3
|
+
"version": "2.1.0",
|
4
4
|
"description": "JavaScript/TypeScript client SDK for LiveKit",
|
5
5
|
"main": "./dist/livekit-client.umd.js",
|
6
6
|
"unpkg": "./dist/livekit-client.umd.js",
|
@@ -36,7 +36,7 @@
|
|
36
36
|
"author": "David Zhao <david@davidzhao.com>",
|
37
37
|
"license": "Apache-2.0",
|
38
38
|
"dependencies": {
|
39
|
-
"@livekit/protocol": "1.
|
39
|
+
"@livekit/protocol": "1.13.0",
|
40
40
|
"events": "^3.3.0",
|
41
41
|
"loglevel": "^1.8.0",
|
42
42
|
"sdp-transform": "^2.14.1",
|
@@ -46,8 +46,8 @@
|
|
46
46
|
"webrtc-adapter": "^8.1.1"
|
47
47
|
},
|
48
48
|
"devDependencies": {
|
49
|
-
"@babel/core": "7.
|
50
|
-
"@babel/preset-env": "7.
|
49
|
+
"@babel/core": "7.24.4",
|
50
|
+
"@babel/preset-env": "7.24.4",
|
51
51
|
"@bufbuild/protoc-gen-es": "^1.3.0",
|
52
52
|
"@changesets/cli": "2.27.1",
|
53
53
|
"@livekit/changesets-changelog-github": "^0.0.4",
|
@@ -65,23 +65,23 @@
|
|
65
65
|
"@typescript-eslint/eslint-plugin": "5.62.0",
|
66
66
|
"@typescript-eslint/parser": "5.62.0",
|
67
67
|
"downlevel-dts": "^0.11.0",
|
68
|
-
"eslint": "8.
|
69
|
-
"eslint-config-airbnb-typescript": "
|
68
|
+
"eslint": "8.57.0",
|
69
|
+
"eslint-config-airbnb-typescript": "18.0.0",
|
70
70
|
"eslint-config-prettier": "9.1.0",
|
71
71
|
"eslint-plugin-ecmascript-compat": "^3.0.0",
|
72
72
|
"eslint-plugin-import": "2.29.1",
|
73
73
|
"gh-pages": "6.1.1",
|
74
74
|
"jsdom": "^24.0.0",
|
75
75
|
"prettier": "^3.0.0",
|
76
|
-
"rollup": "4.
|
76
|
+
"rollup": "4.14.0",
|
77
77
|
"rollup-plugin-delete": "^2.0.0",
|
78
78
|
"rollup-plugin-re": "1.0.7",
|
79
79
|
"rollup-plugin-typescript2": "0.36.0",
|
80
80
|
"size-limit": "^8.2.4",
|
81
|
-
"typedoc": "0.25.
|
81
|
+
"typedoc": "0.25.12",
|
82
82
|
"typedoc-plugin-no-inherit": "1.4.0",
|
83
|
-
"typescript": "5.
|
84
|
-
"vite": "5.0.
|
83
|
+
"typescript": "5.4.3",
|
84
|
+
"vite": "5.0.13",
|
85
85
|
"vitest": "^1.0.0"
|
86
86
|
},
|
87
87
|
"scripts": {
|
package/src/api/SignalClient.ts
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import {
|
2
2
|
AddTrackRequest,
|
3
|
+
AudioTrackFeature,
|
3
4
|
ClientInfo,
|
4
5
|
ConnectionQualityUpdate,
|
5
6
|
DisconnectReason,
|
@@ -27,6 +28,7 @@ import {
|
|
27
28
|
TrackPublishedResponse,
|
28
29
|
TrackUnpublishedResponse,
|
29
30
|
TrickleRequest,
|
31
|
+
UpdateLocalAudioTrack,
|
30
32
|
UpdateParticipantMetadata,
|
31
33
|
UpdateSubscription,
|
32
34
|
UpdateTrackSettings,
|
@@ -583,6 +585,13 @@ export class SignalClient {
|
|
583
585
|
]);
|
584
586
|
}
|
585
587
|
|
588
|
+
sendUpdateLocalAudioTrack(trackSid: string, features: AudioTrackFeature[]) {
|
589
|
+
return this.sendRequest({
|
590
|
+
case: 'updateAudioTrack',
|
591
|
+
value: new UpdateLocalAudioTrack({ trackSid, features }),
|
592
|
+
});
|
593
|
+
}
|
594
|
+
|
586
595
|
sendLeave() {
|
587
596
|
return this.sendRequest({
|
588
597
|
case: 'leave',
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { EventEmitter } from 'events';
|
2
2
|
import type TypedEmitter from 'typed-emitter';
|
3
|
+
import type { CheckInfo, CheckerOptions, InstantiableCheck } from './checks/Checker';
|
3
4
|
import { CheckStatus, Checker } from './checks/Checker';
|
4
|
-
import type { CheckInfo, InstantiableCheck } from './checks/Checker';
|
5
5
|
import { PublishAudioCheck } from './checks/publishAudio';
|
6
6
|
import { PublishVideoCheck } from './checks/publishVideo';
|
7
7
|
import { ReconnectCheck } from './checks/reconnect';
|
@@ -16,12 +16,15 @@ export class ConnectionCheck extends (EventEmitter as new () => TypedEmitter<Con
|
|
16
16
|
|
17
17
|
url: string;
|
18
18
|
|
19
|
+
options: CheckerOptions = {};
|
20
|
+
|
19
21
|
private checkResults: Map<number, CheckInfo> = new Map();
|
20
22
|
|
21
|
-
constructor(url: string, token: string) {
|
23
|
+
constructor(url: string, token: string, options: CheckerOptions = {}) {
|
22
24
|
super();
|
23
25
|
this.url = url;
|
24
26
|
this.token = token;
|
27
|
+
this.options = options;
|
25
28
|
}
|
26
29
|
|
27
30
|
private getNextCheckId() {
|
@@ -50,7 +53,7 @@ export class ConnectionCheck extends (EventEmitter as new () => TypedEmitter<Con
|
|
50
53
|
|
51
54
|
async createAndRunCheck<T extends Checker>(check: InstantiableCheck<T>) {
|
52
55
|
const checkId = this.getNextCheckId();
|
53
|
-
const test = new check(this.url, this.token);
|
56
|
+
const test = new check(this.url, this.token, this.options);
|
54
57
|
const handleUpdate = (info: CheckInfo) => {
|
55
58
|
this.updateCheck(checkId, info);
|
56
59
|
};
|
@@ -607,7 +607,6 @@ export class FrameCryptor extends BaseFrameCryptor {
|
|
607
607
|
if (this.rtpMap.size === 0) {
|
608
608
|
return undefined;
|
609
609
|
}
|
610
|
-
// @ts-expect-error payloadType is not yet part of the typescript definition and currently not supported in Safari
|
611
610
|
const payloadType = frame.getMetadata().payloadType;
|
612
611
|
const codec = payloadType ? this.rtpMap.get(payloadType) : undefined;
|
613
612
|
return codec;
|
@@ -245,9 +245,11 @@ function handleSifTrailer(trailer: Uint8Array) {
|
|
245
245
|
if (self.RTCTransformEvent) {
|
246
246
|
workerLogger.debug('setup transform event');
|
247
247
|
// @ts-ignore
|
248
|
-
self.onrtctransform = (event) => {
|
248
|
+
self.onrtctransform = (event: RTCTransformEvent) => {
|
249
|
+
// @ts-ignore .transformer property is part of RTCTransformEvent
|
249
250
|
const transformer = event.transformer;
|
250
251
|
workerLogger.debug('transformer', transformer);
|
252
|
+
// @ts-ignore monkey patching non standard flag
|
251
253
|
transformer.handled = true;
|
252
254
|
const { kind, participantIdentity, trackId, codec } = transformer.options;
|
253
255
|
const cryptor = getTrackCryptor(participantIdentity, trackId);
|
package/src/index.ts
CHANGED
@@ -20,6 +20,7 @@ import { TrackPublication } from './room/track/TrackPublication';
|
|
20
20
|
import type { LiveKitReactNativeInfo } from './room/types';
|
21
21
|
import type { AudioAnalyserOptions } from './room/utils';
|
22
22
|
import {
|
23
|
+
Mutex,
|
23
24
|
createAudioAnalyser,
|
24
25
|
getEmptyAudioStreamTrack,
|
25
26
|
getEmptyVideoStreamTrack,
|
@@ -32,6 +33,7 @@ import {
|
|
32
33
|
import { getBrowser } from './utils/browserParser';
|
33
34
|
|
34
35
|
export * from './connectionHelper/ConnectionCheck';
|
36
|
+
export * from './connectionHelper/checks/Checker';
|
35
37
|
export * from './e2ee';
|
36
38
|
export * from './options';
|
37
39
|
export * from './room/errors';
|
@@ -79,6 +81,7 @@ export {
|
|
79
81
|
supportsAdaptiveStream,
|
80
82
|
supportsDynacast,
|
81
83
|
supportsVP9,
|
84
|
+
Mutex,
|
82
85
|
};
|
83
86
|
export type {
|
84
87
|
AudioAnalyserOptions,
|
package/src/room/RTCEngine.ts
CHANGED
@@ -169,6 +169,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
169
169
|
|
170
170
|
private loggerOptions: LoggerOptions;
|
171
171
|
|
172
|
+
private publisherConnectionPromise: Promise<void> | undefined;
|
173
|
+
|
172
174
|
constructor(private options: InternalRoomOptions) {
|
173
175
|
super();
|
174
176
|
this.log = getLogger(options.loggerName ?? LoggerNames.Engine);
|
@@ -398,6 +400,11 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
398
400
|
this.pcManager.onDataChannel = this.handleDataChannel;
|
399
401
|
this.pcManager.onStateChange = async (connectionState, publisherState, subscriberState) => {
|
400
402
|
this.log.debug(`primary PC state changed ${connectionState}`, this.logContext);
|
403
|
+
|
404
|
+
if (['closed', 'disconnected', 'failed'].includes(publisherState)) {
|
405
|
+
// reset publisher connection promise
|
406
|
+
this.publisherConnectionPromise = undefined;
|
407
|
+
}
|
401
408
|
if (connectionState === PCTransportState.CONNECTED) {
|
402
409
|
const shouldEmit = this.pcState === PCState.New;
|
403
410
|
this.pcState = PCState.Connected;
|
@@ -1179,7 +1186,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
1179
1186
|
}
|
1180
1187
|
|
1181
1188
|
private async ensurePublisherConnected(kind: DataPacket_Kind) {
|
1182
|
-
|
1189
|
+
if (!this.publisherConnectionPromise) {
|
1190
|
+
this.publisherConnectionPromise = this.ensureDataTransportConnected(kind, false);
|
1191
|
+
}
|
1192
|
+
await this.publisherConnectionPromise;
|
1183
1193
|
}
|
1184
1194
|
|
1185
1195
|
/* @internal */
|
package/src/room/events.ts
CHANGED
@@ -685,6 +685,7 @@ export default class LocalParticipant extends Participant {
|
|
685
685
|
track.on(TrackEvent.Ended, this.handleTrackEnded);
|
686
686
|
track.on(TrackEvent.UpstreamPaused, this.onTrackUpstreamPaused);
|
687
687
|
track.on(TrackEvent.UpstreamResumed, this.onTrackUpstreamResumed);
|
688
|
+
track.on(TrackEvent.AudioTrackFeatureUpdate, this.onTrackFeatureUpdate);
|
688
689
|
|
689
690
|
// create track publication from track
|
690
691
|
const req = new AddTrackRequest({
|
@@ -1037,6 +1038,7 @@ export default class LocalParticipant extends Participant {
|
|
1037
1038
|
track.off(TrackEvent.Ended, this.handleTrackEnded);
|
1038
1039
|
track.off(TrackEvent.UpstreamPaused, this.onTrackUpstreamPaused);
|
1039
1040
|
track.off(TrackEvent.UpstreamResumed, this.onTrackUpstreamResumed);
|
1041
|
+
track.off(TrackEvent.AudioTrackFeatureUpdate, this.onTrackFeatureUpdate);
|
1040
1042
|
|
1041
1043
|
if (stopOnUnpublish === undefined) {
|
1042
1044
|
stopOnUnpublish = this.roomOptions?.stopLocalTrackOnUnpublish ?? true;
|
@@ -1293,6 +1295,18 @@ export default class LocalParticipant extends Participant {
|
|
1293
1295
|
this.onTrackMuted(track, track.isMuted);
|
1294
1296
|
};
|
1295
1297
|
|
1298
|
+
private onTrackFeatureUpdate = (track: LocalAudioTrack) => {
|
1299
|
+
const pub = this.audioTrackPublications.get(track.sid!);
|
1300
|
+
if (!pub) {
|
1301
|
+
this.log.warn(
|
1302
|
+
`Could not update local audio track settings, missing publication for track ${track.sid}`,
|
1303
|
+
this.logContext,
|
1304
|
+
);
|
1305
|
+
return;
|
1306
|
+
}
|
1307
|
+
this.engine.client.sendUpdateLocalAudioTrack(pub.trackSid, pub.getTrackFeatures());
|
1308
|
+
};
|
1309
|
+
|
1296
1310
|
private handleSubscribedQualityUpdate = async (update: SubscribedQualityUpdate) => {
|
1297
1311
|
if (!this.roomOptions?.dynacast) {
|
1298
1312
|
return;
|
@@ -150,11 +150,12 @@ export function computeVideoEncodings(
|
|
150
150
|
isSafari() ||
|
151
151
|
(browser?.name === 'Chrome' && compareVersions(browser?.version, '113') < 0)
|
152
152
|
) {
|
153
|
+
const bitratesRatio = sm.suffix == 'h' ? 2 : 3;
|
153
154
|
for (let i = 0; i < sm.spatial; i += 1) {
|
154
155
|
// in legacy SVC, scaleResolutionDownBy cannot be set
|
155
156
|
encodings.push({
|
156
157
|
rid: videoRids[2 - i],
|
157
|
-
maxBitrate: videoEncoding.maxBitrate /
|
158
|
+
maxBitrate: videoEncoding.maxBitrate / bitratesRatio ** i,
|
158
159
|
maxFramerate: original.encoding.maxFramerate,
|
159
160
|
});
|
160
161
|
}
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import { AudioTrackFeature } from '@livekit/protocol';
|
1
2
|
import { TrackEvent } from '../events';
|
2
3
|
import { computeBitrate, monitorFrequency } from '../stats';
|
3
4
|
import type { AudioSenderStats } from '../stats';
|
@@ -15,8 +16,17 @@ export default class LocalAudioTrack extends LocalTrack<Track.Kind.Audio> {
|
|
15
16
|
|
16
17
|
private prevStats?: AudioSenderStats;
|
17
18
|
|
19
|
+
private isKrispNoiseFilterEnabled = false;
|
20
|
+
|
18
21
|
protected processor?: TrackProcessor<Track.Kind.Audio, AudioProcessorOptions> | undefined;
|
19
22
|
|
23
|
+
/**
|
24
|
+
* boolean indicating whether enhanced noise cancellation is currently being used on this track
|
25
|
+
*/
|
26
|
+
get enhancedNoiseCancellation() {
|
27
|
+
return this.isKrispNoiseFilterEnabled;
|
28
|
+
}
|
29
|
+
|
20
30
|
/**
|
21
31
|
*
|
22
32
|
* @param mediaTrack
|
@@ -152,6 +162,28 @@ export default class LocalAudioTrack extends LocalTrack<Track.Kind.Audio> {
|
|
152
162
|
this.prevStats = stats;
|
153
163
|
};
|
154
164
|
|
165
|
+
private handleKrispNoiseFilterEnable = () => {
|
166
|
+
this.isKrispNoiseFilterEnabled = true;
|
167
|
+
this.log.debug(`Krisp noise filter enabled`, this.logContext);
|
168
|
+
this.emit(
|
169
|
+
TrackEvent.AudioTrackFeatureUpdate,
|
170
|
+
this,
|
171
|
+
AudioTrackFeature.TF_ENHANCED_NOISE_CANCELLATION,
|
172
|
+
true,
|
173
|
+
);
|
174
|
+
};
|
175
|
+
|
176
|
+
private handleKrispNoiseFilterDisable = () => {
|
177
|
+
this.isKrispNoiseFilterEnabled = false;
|
178
|
+
this.log.debug(`Krisp noise filter disabled`, this.logContext);
|
179
|
+
this.emit(
|
180
|
+
TrackEvent.AudioTrackFeatureUpdate,
|
181
|
+
this,
|
182
|
+
AudioTrackFeature.TF_ENHANCED_NOISE_CANCELLATION,
|
183
|
+
false,
|
184
|
+
);
|
185
|
+
};
|
186
|
+
|
155
187
|
async setProcessor(processor: TrackProcessor<Track.Kind.Audio, AudioProcessorOptions>) {
|
156
188
|
const unlock = await this.processorLock.lock();
|
157
189
|
try {
|
@@ -175,6 +207,14 @@ export default class LocalAudioTrack extends LocalTrack<Track.Kind.Audio> {
|
|
175
207
|
this.processor = processor;
|
176
208
|
if (this.processor.processedTrack) {
|
177
209
|
await this.sender?.replaceTrack(this.processor.processedTrack);
|
210
|
+
this.processor.processedTrack.addEventListener(
|
211
|
+
'enable-lk-krisp-noise-filter',
|
212
|
+
this.handleKrispNoiseFilterEnable,
|
213
|
+
);
|
214
|
+
this.processor.processedTrack.addEventListener(
|
215
|
+
'disable-lk-krisp-noise-filter',
|
216
|
+
this.handleKrispNoiseFilterDisable,
|
217
|
+
);
|
178
218
|
}
|
179
219
|
this.emit(TrackEvent.TrackProcessorUpdate, this.processor);
|
180
220
|
} finally {
|
@@ -1,7 +1,7 @@
|
|
1
|
-
import
|
1
|
+
import { AudioTrackFeature, TrackInfo } from '@livekit/protocol';
|
2
2
|
import { TrackEvent } from '../events';
|
3
3
|
import type { LoggerOptions } from '../types';
|
4
|
-
import
|
4
|
+
import LocalAudioTrack from './LocalAudioTrack';
|
5
5
|
import type LocalTrack from './LocalTrack';
|
6
6
|
import type LocalVideoTrack from './LocalVideoTrack';
|
7
7
|
import type { Track } from './Track';
|
@@ -82,6 +82,32 @@ export default class LocalTrackPublication extends TrackPublication {
|
|
82
82
|
await this.track?.resumeUpstream();
|
83
83
|
}
|
84
84
|
|
85
|
+
getTrackFeatures() {
|
86
|
+
if (this.track instanceof LocalAudioTrack) {
|
87
|
+
const settings = this.track!.mediaStreamTrack.getSettings();
|
88
|
+
const features: Set<AudioTrackFeature> = new Set();
|
89
|
+
if (settings.autoGainControl) {
|
90
|
+
features.add(AudioTrackFeature.TF_AUTO_GAIN_CONTROL);
|
91
|
+
}
|
92
|
+
if (settings.echoCancellation) {
|
93
|
+
features.add(AudioTrackFeature.TF_ECHO_CANCELLATION);
|
94
|
+
}
|
95
|
+
if (settings.noiseSuppression) {
|
96
|
+
features.add(AudioTrackFeature.TF_NOISE_SUPPRESSION);
|
97
|
+
}
|
98
|
+
if (settings.channelCount && settings.channelCount > 1) {
|
99
|
+
features.add(AudioTrackFeature.TF_STEREO);
|
100
|
+
}
|
101
|
+
if (!this.options?.dtx) {
|
102
|
+
features.add(AudioTrackFeature.TF_STEREO);
|
103
|
+
}
|
104
|
+
if (this.track.enhancedNoiseCancellation) {
|
105
|
+
features.add(AudioTrackFeature.TF_ENHANCED_NOISE_CANCELLATION);
|
106
|
+
}
|
107
|
+
return Array.from(features.values());
|
108
|
+
} else return [];
|
109
|
+
}
|
110
|
+
|
85
111
|
handleTrackEnded = () => {
|
86
112
|
this.emit(TrackEvent.Ended);
|
87
113
|
};
|
@@ -572,13 +572,17 @@ export function videoLayersFromEncodings(
|
|
572
572
|
const encodingSM = encodings[0].scalabilityMode as string;
|
573
573
|
const sm = new ScalabilityMode(encodingSM);
|
574
574
|
const layers = [];
|
575
|
+
const resRatio = sm.suffix == 'h' ? 1.5 : 2;
|
576
|
+
const bitratesRatio = sm.suffix == 'h' ? 2 : 3;
|
575
577
|
for (let i = 0; i < sm.spatial; i += 1) {
|
576
578
|
layers.push(
|
577
579
|
new VideoLayer({
|
578
580
|
quality: VideoQuality.HIGH - i,
|
579
|
-
width: Math.ceil(width /
|
580
|
-
height: Math.ceil(height /
|
581
|
-
bitrate: encodings[0].maxBitrate
|
581
|
+
width: Math.ceil(width / resRatio ** i),
|
582
|
+
height: Math.ceil(height / resRatio ** i),
|
583
|
+
bitrate: encodings[0].maxBitrate
|
584
|
+
? Math.ceil(encodings[0].maxBitrate / bitratesRatio ** i)
|
585
|
+
: 0,
|
582
586
|
ssrc: 0,
|
583
587
|
}),
|
584
588
|
);
|
package/src/room/track/Track.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import {
|
2
|
+
AudioTrackFeature,
|
2
3
|
VideoQuality as ProtoQuality,
|
3
4
|
StreamState as ProtoStreamState,
|
4
5
|
TrackSource,
|
@@ -300,6 +301,17 @@ export abstract class Track<
|
|
300
301
|
|
301
302
|
protected async handleAppVisibilityChanged() {
|
302
303
|
this.isInBackground = document.visibilityState === 'hidden';
|
304
|
+
if (!this.isInBackground && this.kind === Track.Kind.Video) {
|
305
|
+
setTimeout(
|
306
|
+
() =>
|
307
|
+
this.attachedElements.forEach((el) =>
|
308
|
+
el.play().catch(() => {
|
309
|
+
/** catch clause necessary for Safari */
|
310
|
+
}),
|
311
|
+
),
|
312
|
+
0,
|
313
|
+
);
|
314
|
+
}
|
303
315
|
}
|
304
316
|
|
305
317
|
protected addAppVisibilityListener() {
|
@@ -504,4 +516,5 @@ export type TrackEventCallbacks = {
|
|
504
516
|
upstreamPaused: (track: any) => void;
|
505
517
|
upstreamResumed: (track: any) => void;
|
506
518
|
trackProcessorUpdate: (processor?: TrackProcessor<Track.Kind, any>) => void;
|
519
|
+
audioTrackFeatureUpdate: (track: any, feature: AudioTrackFeature, enabled: boolean) => void;
|
507
520
|
};
|
@@ -350,7 +350,28 @@ export function isBackupCodec(codec: string): codec is BackupVideoCodec {
|
|
350
350
|
/**
|
351
351
|
* scalability modes for svc.
|
352
352
|
*/
|
353
|
-
export type ScalabilityMode =
|
353
|
+
export type ScalabilityMode =
|
354
|
+
| 'L1T1'
|
355
|
+
| 'L1T2'
|
356
|
+
| 'L1T3'
|
357
|
+
| 'L2T1'
|
358
|
+
| 'L2T1h'
|
359
|
+
| 'L2T1_KEY'
|
360
|
+
| 'L2T2'
|
361
|
+
| 'L2T2h'
|
362
|
+
| 'L2T2_KEY'
|
363
|
+
| 'L2T3'
|
364
|
+
| 'L2T3h'
|
365
|
+
| 'L2T3_KEY'
|
366
|
+
| 'L3T1'
|
367
|
+
| 'L3T1h'
|
368
|
+
| 'L3T1_KEY'
|
369
|
+
| 'L3T2'
|
370
|
+
| 'L3T2h'
|
371
|
+
| 'L3T2_KEY'
|
372
|
+
| 'L3T3'
|
373
|
+
| 'L3T3h'
|
374
|
+
| 'L3T3_KEY';
|
354
375
|
|
355
376
|
export namespace AudioPresets {
|
356
377
|
export const telephone: AudioPreset = {
|