mirror of
https://github.com/element-hq/element-call.git
synced 2026-08-14 18:10:38 +00:00
153 lines
4.5 KiB
TypeScript
153 lines
4.5 KiB
TypeScript
/*
|
|
Copyright 2023, 2024 New Vector Ltd.
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
Please see LICENSE in the repository root for full details.
|
|
*/
|
|
|
|
import {
|
|
AudioPresets,
|
|
DefaultReconnectPolicy,
|
|
type RoomOptions,
|
|
type TrackPublishDefaults,
|
|
type VideoPreset,
|
|
VideoPresets,
|
|
VideoPreset as VideoPresetClass,
|
|
} from "livekit-client";
|
|
|
|
import { Config } from "../config/Config";
|
|
import { DEFAULT_CONFIG, type ConfigOptions } from "../config/ConfigOptions";
|
|
|
|
/**
|
|
* Find the closest matching VideoPreset for a given height.
|
|
*/
|
|
function videoPresetForHeight(height: number): VideoPreset {
|
|
if (height <= 180) return VideoPresets.h180;
|
|
if (height <= 360) return VideoPresets.h360;
|
|
if (height <= 540) return VideoPresets.h540;
|
|
if (height <= 720) return VideoPresets.h720;
|
|
if (height <= 1080) return VideoPresets.h1080;
|
|
if (height <= 1440) return VideoPresets.h1440;
|
|
return VideoPresets.h2160;
|
|
}
|
|
|
|
/**
|
|
* Build LiveKit publish options from config, falling back to sensible defaults.
|
|
*/
|
|
function buildPublishOptions(
|
|
mediaQuality: ConfigOptions["media_quality"],
|
|
): TrackPublishDefaults {
|
|
const defaults = DEFAULT_CONFIG.media_quality;
|
|
const videoConf = mediaQuality?.video;
|
|
const screenConf = mediaQuality?.screen_share;
|
|
const codec = mediaQuality?.video_codec ?? defaults.video_codec;
|
|
|
|
// Camera video encoding
|
|
const videoEncoding = {
|
|
maxBitrate: videoConf?.max_bitrate ?? defaults.video.max_bitrate,
|
|
maxFramerate: videoConf?.max_framerate ?? defaults.video.max_framerate,
|
|
};
|
|
|
|
// Camera simulcast layers
|
|
let videoSimulcastLayers: VideoPreset[];
|
|
if (videoConf?.simulcast_layers) {
|
|
videoSimulcastLayers = videoConf.simulcast_layers.map(
|
|
(layer) =>
|
|
new VideoPresetClass(
|
|
Math.round((layer.height * 16) / 9),
|
|
layer.height,
|
|
layer.bitrate,
|
|
videoConf?.max_framerate ?? defaults.video.max_framerate,
|
|
),
|
|
);
|
|
} else {
|
|
videoSimulcastLayers = [VideoPresets.h180, VideoPresets.h360];
|
|
}
|
|
|
|
// Screen share encoding
|
|
const screenShareEncoding = {
|
|
maxBitrate: screenConf?.max_bitrate ?? defaults.screen_share.max_bitrate,
|
|
maxFramerate:
|
|
screenConf?.max_framerate ?? defaults.screen_share.max_framerate,
|
|
};
|
|
|
|
// Screen share simulcast layers
|
|
let screenShareSimulcastLayers: VideoPreset[] | undefined;
|
|
if (screenConf?.simulcast_layers) {
|
|
screenShareSimulcastLayers = screenConf.simulcast_layers.map(
|
|
(layer) =>
|
|
new VideoPresetClass(
|
|
Math.round((layer.height * 16) / 9),
|
|
layer.height,
|
|
layer.bitrate,
|
|
layer.framerate ?? screenConf?.max_framerate ?? 30,
|
|
),
|
|
);
|
|
}
|
|
|
|
return {
|
|
audioPreset: AudioPresets.music,
|
|
dtx: true,
|
|
// disable red because the livekit server strips out red packets for clients
|
|
// that don't support it (firefox) but of course that doesn't work with e2ee.
|
|
red: false,
|
|
forceStereo: false,
|
|
simulcast: true,
|
|
videoSimulcastLayers: videoSimulcastLayers as VideoPreset[],
|
|
screenShareEncoding,
|
|
...(screenShareSimulcastLayers && {
|
|
screenShareSimulcastLayers: screenShareSimulcastLayers as VideoPreset[],
|
|
}),
|
|
stopMicTrackOnMute: false,
|
|
videoCodec: codec,
|
|
videoEncoding,
|
|
backupCodec: {
|
|
codec: "vp8",
|
|
encoding: VideoPresets.h720.encoding,
|
|
},
|
|
} as TrackPublishDefaults;
|
|
}
|
|
|
|
/**
|
|
* Build LiveKit RoomOptions from config.
|
|
* Call this after Config.init() has resolved.
|
|
*/
|
|
export function buildLiveKitOptions(
|
|
mediaQuality?: ConfigOptions["media_quality"],
|
|
): RoomOptions {
|
|
const videoHeight =
|
|
mediaQuality?.video?.max_resolution ??
|
|
DEFAULT_CONFIG.media_quality.video.max_resolution;
|
|
const basePreset = videoPresetForHeight(videoHeight);
|
|
|
|
return {
|
|
// automatically manage subscribed video quality
|
|
adaptiveStream: true,
|
|
|
|
// optimize publishing bandwidth and CPU for published tracks
|
|
dynacast: true,
|
|
|
|
// capture settings
|
|
videoCaptureDefaults: {
|
|
resolution: basePreset.resolution,
|
|
},
|
|
|
|
// publish settings
|
|
publishDefaults: buildPublishOptions(mediaQuality),
|
|
|
|
// default LiveKit options that seem to be sane
|
|
stopLocalTrackOnUnpublish: true,
|
|
reconnectPolicy: new DefaultReconnectPolicy(),
|
|
disconnectOnPageLeave: true,
|
|
webAudioMix: false,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get LiveKit options, reading from the loaded Config singleton.
|
|
* Requires Config.init() to have resolved first.
|
|
*/
|
|
export function getLiveKitOptions(): RoomOptions {
|
|
return buildLiveKitOptions(Config.get().media_quality);
|
|
}
|