mirror of
https://github.com/vector-im/element-call.git
synced 2026-08-20 20:49:20 +00:00
feat: add user-configurable screen share quality settings UI
Adds a "Screen sharing" section to Settings > Video with controls for: - Resolution (576p to 4K) - Framerate (5-60 fps slider) - Bitrate (0.5-15 Mbps slider) - Codec (VP8/VP9/H.264/AV1) Gated behind an "Advanced screen share settings" toggle. When enabled, settings are passed to LiveKit's setScreenShareEnabled as both capture constraints and publish options. When disabled, falls back to config.json media_quality defaults. Settings are persisted in localStorage via the existing Setting<T> system. The Slider component is extended with a tooltipFormatter prop for custom tooltip display. Inspired by pirosuki's advanced-screen-share-settings branch, but reimplemented cleanly: settings are read directly in LocalMember.ts (no signature changes), the existing Slider is extended (no component duplication), and proper form components are used throughout. Signed-off-by: Ryan Emmick <ryanemmick4@gmail.com>
This commit is contained in:
@@ -10,10 +10,9 @@ import {
|
||||
ParticipantEvent,
|
||||
type LocalParticipant,
|
||||
type ScreenShareCaptureOptions,
|
||||
type TrackPublishOptions,
|
||||
RoomEvent,
|
||||
MediaDeviceFailure,
|
||||
type ScreenSharePreset,
|
||||
VideoPreset as VideoPresetClass,
|
||||
} from "livekit-client";
|
||||
import { observeParticipantEvents } from "@livekit/components-core";
|
||||
import {
|
||||
@@ -55,7 +54,14 @@ import {
|
||||
import { ElementWidgetActions, widget } from "../../../widget.ts";
|
||||
import { getUrlParams } from "../../../UrlParams.ts";
|
||||
import { PosthogAnalytics } from "../../../analytics/PosthogAnalytics.ts";
|
||||
import { MatrixRTCMode } from "../../../settings/settings.ts";
|
||||
import {
|
||||
MatrixRTCMode,
|
||||
advancedScreenShare,
|
||||
screenShareResolution,
|
||||
screenShareFramerate,
|
||||
screenShareBitrate,
|
||||
screenShareCodec,
|
||||
} from "../../../settings/settings.ts";
|
||||
import { Config } from "../../../config/Config.ts";
|
||||
import {
|
||||
ConnectionState,
|
||||
@@ -663,7 +669,6 @@ export const createLocalMembership$ = ({
|
||||
!getUrlParams().hideScreensharing
|
||||
) {
|
||||
toggleScreenSharing = (): void => {
|
||||
const screenConf = Config.get().media_quality?.screen_share;
|
||||
const screenshareSettings: ScreenShareCaptureOptions = {
|
||||
// Screen share audio shouldn't have any filtering.
|
||||
// "echoCancellation" is purposely excluded, as setting it to
|
||||
@@ -677,14 +682,44 @@ export const createLocalMembership$ = ({
|
||||
selfBrowserSurface: "include",
|
||||
surfaceSwitching: "include",
|
||||
systemAudio: "include",
|
||||
...(screenConf?.max_resolution && {
|
||||
resolution: {
|
||||
};
|
||||
|
||||
let publishOptions: TrackPublishOptions | undefined;
|
||||
|
||||
if (advancedScreenShare.getValue()) {
|
||||
// User has advanced screen share settings enabled
|
||||
const resParts = screenShareResolution.getValue().split("x");
|
||||
const width = Number(resParts[0]);
|
||||
const height = Number(resParts[1]);
|
||||
const fps = screenShareFramerate.getValue();
|
||||
const bps = screenShareBitrate.getValue();
|
||||
const codec = screenShareCodec.getValue();
|
||||
|
||||
screenshareSettings.resolution = {
|
||||
width,
|
||||
height,
|
||||
frameRate: fps,
|
||||
};
|
||||
|
||||
publishOptions = {
|
||||
screenShareEncoding: {
|
||||
maxBitrate: bps,
|
||||
maxFramerate: fps,
|
||||
},
|
||||
videoCodec: codec,
|
||||
};
|
||||
} else {
|
||||
// Fall back to config.json settings if available
|
||||
const screenConf = Config.get().media_quality?.screen_share;
|
||||
if (screenConf?.max_resolution) {
|
||||
screenshareSettings.resolution = {
|
||||
width: Math.round((screenConf.max_resolution * 16) / 9),
|
||||
height: screenConf.max_resolution,
|
||||
frameRate: screenConf.max_framerate ?? 30,
|
||||
},
|
||||
}),
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const targetScreenshareState = !sharingScreen$.value;
|
||||
logger.info(
|
||||
`toggleScreenSharing called. Switching ${
|
||||
@@ -700,7 +735,11 @@ export const createLocalMembership$ = ({
|
||||
// is still initializing or publishing tracks, because there's no
|
||||
// technical reason to disallow this. LiveKit will publish if it can.
|
||||
participant$.value
|
||||
?.setScreenShareEnabled(targetScreenshareState, screenshareSettings)
|
||||
?.setScreenShareEnabled(
|
||||
targetScreenshareState,
|
||||
screenshareSettings,
|
||||
publishOptions,
|
||||
)
|
||||
.catch(logger.error);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user