Skip to content

Commit

Permalink
Add support for local priority in presets (#677)
Browse files Browse the repository at this point in the history
* wip

* Add support for local priority in presets

* remove default values on video presets

* address comment

* also set network priority

* fix explicit type imports

* fix tests

* fix eslint

* Create large-zebras-press.md
  • Loading branch information
lukasIO committed May 3, 2023
1 parent 8088387 commit c7b3fc0
Show file tree
Hide file tree
Showing 21 changed files with 100 additions and 59 deletions.
5 changes: 5 additions & 0 deletions .changeset/large-zebras-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"livekit-client": patch
---

Add support for local priority in presets
2 changes: 1 addition & 1 deletion jest.config.cjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = {
clearMocks: true,
modulePathIgnorePatterns: ['<rootDir>/dist/'],
modulePathIgnorePatterns: ['<rootDir>/dist/', '<rootDir>/example/'],
preset: 'ts-jest',
testEnvironment: 'node',
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
"ts-proto": "1.147.1",
"typedoc": "0.24.6",
"typedoc-plugin-no-inherit": "1.4.0",
"typescript": "4.9.5",
"typescript": "5.0.4",
"vite": "4.3.4"
},
"browserslist": [
Expand Down
3 changes: 2 additions & 1 deletion src/connectionHelper/ConnectionCheck.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import EventEmitter from 'events';
import type TypedEmitter from 'typed-emitter';
import { CheckInfo, CheckStatus, Checker, InstantiableCheck } from './checks/Checker';
import { CheckStatus, Checker } from './checks/Checker';
import type { CheckInfo, InstantiableCheck } from './checks/Checker';
import { PublishAudioCheck } from './checks/publishAudio';
import { PublishVideoCheck } from './checks/publishVideo';
import { ReconnectCheck } from './checks/reconnect';
Expand Down
14 changes: 9 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ import LocalVideoTrack from './room/track/LocalVideoTrack';
import RemoteAudioTrack from './room/track/RemoteAudioTrack';
import RemoteTrack from './room/track/RemoteTrack';
import RemoteTrackPublication from './room/track/RemoteTrackPublication';
import RemoteVideoTrack, { type ElementInfo } from './room/track/RemoteVideoTrack';
import type { ElementInfo } from './room/track/RemoteVideoTrack';
import RemoteVideoTrack from './room/track/RemoteVideoTrack';
import { TrackPublication } from './room/track/TrackPublication';
import type { LiveKitReactNativeInfo } from './room/types';
import {
type AudioAnalyserOptions,
createAudioAnalyser,
getEmptyAudioStreamTrack,
getEmptyVideoStreamTrack,
Expand All @@ -27,6 +27,7 @@ import {
supportsAdaptiveStream,
supportsDynacast,
} from './room/utils';
import type { AudioAnalyserOptions } from './room/utils';

export * from './options';
export * from './room/errors';
Expand All @@ -48,7 +49,6 @@ export {
supportsDynacast,
supportsAV1,
createAudioAnalyser,
AudioAnalyserOptions,
LogLevel,
Room,
ConnectionState,
Expand All @@ -66,12 +66,16 @@ export {
RemoteAudioTrack,
RemoteVideoTrack,
RemoteTrackPublication,
ParticipantTrackPermission,
TrackPublication,
VideoQuality,
ConnectionQuality,
ElementInfo,
DefaultReconnectPolicy,
CriticalTimers,
};

export type {
ElementInfo,
ParticipantTrackPermission,
AudioAnalyserOptions,
LiveKitReactNativeInfo,
};
12 changes: 8 additions & 4 deletions src/room/PCTransport.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import EventEmitter from 'events';
import { MediaDescription, parse, write } from 'sdp-transform';
import { parse, write } from 'sdp-transform';
import type { MediaDescription } from 'sdp-transform';
import { debounce } from 'ts-debounce';
import log from '../logger';
import { NegotiationError } from './errors';
import { ddExtensionURI, isSVCCodec } from './utils';
import { ddExtensionURI, isChromiumBased, isSVCCodec } from './utils';

/** @internal */
interface TrackBitrateInfo {
Expand Down Expand Up @@ -35,9 +36,12 @@ export default class PCTransport extends EventEmitter {

onOffer?: (offer: RTCSessionDescriptionInit) => void;

constructor(config?: RTCConfiguration) {
constructor(config?: RTCConfiguration, mediaConstraints: Record<string, unknown> = {}) {
super();
this.pc = new RTCPeerConnection(config);
this.pc = isChromiumBased()
? // @ts-expect-error chrome allows additional media constraints to be passed into the RTCPeerConnection constructor
new RTCPeerConnection(config, mediaConstraints)
: new RTCPeerConnection(config);
}

get isICEConnected(): boolean {
Expand Down
7 changes: 4 additions & 3 deletions src/room/RTCEngine.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { EventEmitter } from 'events';
import type TypedEventEmitter from 'typed-emitter';
import { SignalClient, SignalOptions } from '../api/SignalClient';
import { SignalClient } from '../api/SignalClient';
import type { SignalOptions } from '../api/SignalClient';
import log from '../logger';
import type { InternalRoomOptions } from '../options';
import {
Expand Down Expand Up @@ -307,8 +308,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
this.participantSid = joinResponse.participant?.sid;

const rtcConfig = this.makeRTCConfiguration(joinResponse);

this.publisher = new PCTransport(rtcConfig);
const googConstraints = { optional: [{ googDscp: true }] };
this.publisher = new PCTransport(rtcConfig, googConstraints);
this.subscriber = new PCTransport(rtcConfig);

this.emit(EngineEvent.TransportsCreated, this.publisher, this.subscriber);
Expand Down
10 changes: 6 additions & 4 deletions src/room/defaults.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import type { InternalRoomConnectOptions, InternalRoomOptions } from '../options';
import DefaultReconnectPolicy from './DefaultReconnectPolicy';
import {
import { AudioPresets, ScreenSharePresets, VideoPresets } from './track/options';
import type {
AudioCaptureOptions,
AudioPresets,
ScreenSharePresets,
TrackPublishDefaults,
VideoCaptureOptions,
VideoPresets,
} from './track/options';

export const publishDefaults: TrackPublishDefaults = {
/**
* @deprecated
*/
audioBitrate: AudioPresets.music.maxBitrate,
audioPreset: AudioPresets.music,
dtx: true,
red: true,
forceStereo: false,
Expand Down
15 changes: 8 additions & 7 deletions src/room/participant/LocalParticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,21 @@ import LocalTrack from '../track/LocalTrack';
import LocalTrackPublication from '../track/LocalTrackPublication';
import LocalVideoTrack, { videoLayersFromEncodings } from '../track/LocalVideoTrack';
import { Track } from '../track/Track';
import {
import { ScreenSharePresets, isBackupCodec, isCodecEqual } from '../track/options';
import type {
AudioCaptureOptions,
BackupVideoCodec,
CreateLocalTracksOptions,
ScreenShareCaptureOptions,
ScreenSharePresets,
TrackPublishOptions,
VideoCaptureOptions,
isBackupCodec,
isCodecEqual,
} from '../track/options';
import { constraintsForOptions, mergeDefaultOptions } from '../track/utils';
import type { DataPublishOptions } from '../types';
import { Future, isFireFox, isSVCCodec, isSafari, isWeb, supportsAV1, supportsVP9 } from '../utils';
import Participant from './Participant';
import { ParticipantTrackPermission, trackPermissionToProto } from './ParticipantTrackPermission';
import { trackPermissionToProto } from './ParticipantTrackPermission';
import type { ParticipantTrackPermission } from './ParticipantTrackPermission';
import RemoteParticipant from './RemoteParticipant';
import {
computeTrackBackupEncodings,
Expand Down Expand Up @@ -651,10 +650,12 @@ export default class LocalParticipant extends Participant {
opts,
);
req.layers = videoLayersFromEncodings(req.width, req.height, simEncodings ?? encodings);
} else if (track.kind === Track.Kind.Audio && opts.audioBitrate) {
} else if (track.kind === Track.Kind.Audio) {
encodings = [
{
maxBitrate: opts.audioBitrate,
maxBitrate: opts.audioPreset?.maxBitrate ?? opts.audioBitrate,
priority: opts.audioPreset?.priority ?? 'high',
networkPriority: opts.audioPreset?.priority ?? 'high',
},
];
}
Expand Down
3 changes: 2 additions & 1 deletion src/room/participant/RemoteParticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import { Track } from '../track/Track';
import type { TrackPublication } from '../track/TrackPublication';
import type { AudioOutputOptions } from '../track/options';
import type { AdaptiveStreamSettings } from '../track/types';
import Participant, { ParticipantEventCallbacks } from './Participant';
import Participant from './Participant';
import type { ParticipantEventCallbacks } from './Participant';

export default class RemoteParticipant extends Participant {
audioTracks: Map<string, RemoteTrackPublication>;
Expand Down
12 changes: 7 additions & 5 deletions src/room/participant/publishUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@ import { TrackInvalidError } from '../errors';
import LocalAudioTrack from '../track/LocalAudioTrack';
import LocalVideoTrack from '../track/LocalVideoTrack';
import { Track } from '../track/Track';
import {
import { ScreenSharePresets, VideoPreset, VideoPresets, VideoPresets43 } from '../track/options';
import type {
BackupVideoCodec,
ScreenSharePresets,
TrackPublishOptions,
VideoCodec,
VideoEncoding,
VideoPreset,
VideoPresets,
VideoPresets43,
} from '../track/options';
import { isSVCCodec } from '../utils';

Expand Down Expand Up @@ -61,6 +58,7 @@ export const computeDefaultScreenShareSimulcastPresets = (fromPreset: VideoPrese
),
),
t.fps,
fromPreset.encoding.priority,
),
);
};
Expand Down Expand Up @@ -317,6 +315,10 @@ function encodingsFromPresets(
if (preset.encoding.maxFramerate) {
encoding.maxFramerate = preset.encoding.maxFramerate;
}
if (preset.encoding.priority) {
encoding.priority = preset.encoding.priority;
encoding.networkPriority = preset.encoding.priority;
}
encodings.push(encoding);
});
return encodings;
Expand Down
3 changes: 2 additions & 1 deletion src/room/track/LocalAudioTrack.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import log from '../../logger';
import { TrackEvent } from '../events';
import { AudioSenderStats, computeBitrate, monitorFrequency } from '../stats';
import { computeBitrate, monitorFrequency } from '../stats';
import type { AudioSenderStats } from '../stats';
import { isWeb } from '../utils';
import LocalTrack from './LocalTrack';
import { Track } from './Track';
Expand Down
3 changes: 2 additions & 1 deletion src/room/track/LocalVideoTrack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import type { SignalClient } from '../../api/SignalClient';
import log from '../../logger';
import { VideoLayer, VideoQuality } from '../../proto/livekit_models';
import type { SubscribedCodec, SubscribedQuality } from '../../proto/livekit_rtc';
import { VideoSenderStats, computeBitrate, monitorFrequency } from '../stats';
import { computeBitrate, monitorFrequency } from '../stats';
import type { VideoSenderStats } from '../stats';
import { Mutex, isFireFox, isMobile, isWeb } from '../utils';
import LocalTrack from './LocalTrack';
import { Track } from './Track';
Expand Down
3 changes: 2 additions & 1 deletion src/room/track/RemoteAudioTrack.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import log from '../../logger';
import { TrackEvent } from '../events';
import { AudioReceiverStats, computeBitrate } from '../stats';
import { computeBitrate } from '../stats';
import type { AudioReceiverStats } from '../stats';
import { supportsSetSinkId } from '../utils';
import RemoteTrack from './RemoteTrack';
import { Track } from './Track';
Expand Down
12 changes: 4 additions & 8 deletions src/room/track/RemoteVideoTrack.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { debounce } from 'ts-debounce';
import log from '../../logger';
import { TrackEvent } from '../events';
import { VideoReceiverStats, computeBitrate } from '../stats';
import { computeBitrate } from '../stats';
import type { VideoReceiverStats } from '../stats';
import CriticalTimers from '../timers';
import {
ObservableMediaElement,
getDevicePixelRatio,
getIntersectionObserver,
getResizeObserver,
isWeb,
} from '../utils';
import { getDevicePixelRatio, getIntersectionObserver, getResizeObserver, isWeb } from '../utils';
import type { ObservableMediaElement } from '../utils';
import RemoteTrack from './RemoteTrack';
import { Track, attachToElement, detachTrack } from './Track';
import type { AdaptiveStreamSettings } from './types';
Expand Down
4 changes: 2 additions & 2 deletions src/room/track/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import LocalAudioTrack from './LocalAudioTrack';
import type LocalTrack from './LocalTrack';
import LocalVideoTrack from './LocalVideoTrack';
import { Track } from './Track';
import {
import { VideoPresets } from './options';
import type {
AudioCaptureOptions,
CreateLocalTracksOptions,
ScreenShareCaptureOptions,
VideoCaptureOptions,
VideoPresets,
} from './options';
import { constraintsForOptions, mergeDefaultOptions } from './utils';

Expand Down
30 changes: 23 additions & 7 deletions src/room/track/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,17 @@ export interface TrackPublishDefaults {
videoCodec?: VideoCodec;

/**
* max audio bitrate, defaults to [[AudioPresets.speech]]
* max audio bitrate, defaults to [[AudioPresets.music]]
* @deprecated use `audioPreset` instead
*/
audioBitrate?: number;

/**
* which audio preset should be used for publishing (audio) tracks
* defaults to [[AudioPresets.music]]
*/
audioPreset?: AudioPreset;

/**
* dtx (Discontinuous Transmission of audio), enabled by default for mono tracks.
*/
Expand Down Expand Up @@ -215,6 +222,7 @@ export interface VideoResolution {
export interface VideoEncoding {
maxBitrate: number;
maxFramerate?: number;
priority?: RTCPriorityType;
}

export class VideoPreset {
Expand All @@ -224,12 +232,19 @@ export class VideoPreset {

height: number;

constructor(width: number, height: number, maxBitrate: number, maxFramerate?: number) {
constructor(
width: number,
height: number,
maxBitrate: number,
maxFramerate?: number,
priority?: RTCPriorityType,
) {
this.width = width;
this.height = height;
this.encoding = {
maxBitrate,
maxFramerate,
priority,
};
}

Expand All @@ -245,6 +260,7 @@ export class VideoPreset {

export interface AudioPreset {
maxBitrate: number;
priority?: RTCPriorityType;
}

const codecs = ['vp8', 'h264', 'vp9', 'av1'] as const;
Expand Down Expand Up @@ -322,9 +338,9 @@ export const VideoPresets43 = {
} as const;

export const ScreenSharePresets = {
h360fps3: new VideoPreset(640, 360, 200_000, 3),
h720fps5: new VideoPreset(1280, 720, 400_000, 5),
h720fps15: new VideoPreset(1280, 720, 1_000_000, 15),
h1080fps15: new VideoPreset(1920, 1080, 1_500_000, 15),
h1080fps30: new VideoPreset(1920, 1080, 3_000_000, 30),
h360fps3: new VideoPreset(640, 360, 200_000, 3, 'medium'),
h720fps5: new VideoPreset(1280, 720, 400_000, 5, 'medium'),
h720fps15: new VideoPreset(1280, 720, 1_000_000, 15, 'medium'),
h1080fps15: new VideoPreset(1920, 1080, 1_500_000, 15, 'medium'),
h1080fps30: new VideoPreset(1920, 1080, 3_000_000, 30, 'medium'),
} as const;
5 changes: 5 additions & 0 deletions src/room/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ export function isFireFox(): boolean {
return navigator.userAgent.indexOf('Firefox') !== -1;
}

export function isChromiumBased(): boolean {
if (!isWeb()) return false;
return navigator.userAgent.indexOf('Chrom') !== -1;
}

export function isSafari(): boolean {
if (!isWeb()) return false;
return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
Expand Down
3 changes: 1 addition & 2 deletions tsconfig.eslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
"src/**/*.ts",
"src/**/*.js",
"example/**/*.ts",
"example/**/*.js",
".eslintrc.js",
"jest.config.js",
"rollup.config.js",
"rollup.config.dev.js"
],
"exclude": []
"exclude": ["dist/**"]
}
Loading

0 comments on commit c7b3fc0

Please sign in to comment.