feat: screenshare hardware acceleration

This commit is contained in:
Hampus Kraft
2026-02-19 16:48:13 +00:00
parent 1a1d13b571
commit 868ddecda4
43 changed files with 1077 additions and 1378 deletions

View File

@@ -57,6 +57,7 @@ type VoiceSettingsUpdate = Partial<{
showVoiceConnectionId: boolean;
pauseOwnScreenSharePreviewOnUnfocus: boolean;
disablePictureInPicturePopout: boolean;
screenShareHardwareAcceleration: boolean;
}>;
class VoiceSettingsStore {
@@ -82,6 +83,7 @@ class VoiceSettingsStore {
showVoiceConnectionIdPrefV2 = true;
pauseOwnScreenSharePreviewOnUnfocusPrefV2 = true;
disablePictureInPicturePopout = false;
screenShareHardwareAcceleration = true;
constructor() {
makeAutoObservable(
@@ -109,6 +111,7 @@ class VoiceSettingsStore {
getShowVoiceConnectionId: false,
getDisablePictureInPicturePopout: false,
getPauseOwnScreenSharePreviewOnUnfocus: false,
getScreenShareHardwareAcceleration: false,
},
{autoBind: true},
);
@@ -138,6 +141,7 @@ class VoiceSettingsStore {
'showVoiceConnectionIdPrefV2',
'pauseOwnScreenSharePreviewOnUnfocusPrefV2',
'disablePictureInPicturePopout',
'screenShareHardwareAcceleration',
]);
}
@@ -296,6 +300,10 @@ class VoiceSettingsStore {
return this.pauseOwnScreenSharePreviewOnUnfocus;
}
getScreenShareHardwareAcceleration(): boolean {
return this.screenShareHardwareAcceleration;
}
updateSettings(data: VoiceSettingsUpdate): void {
const validated = this.validateSettings(data);
@@ -326,6 +334,8 @@ class VoiceSettingsStore {
this.pauseOwnScreenSharePreviewOnUnfocus = validated.pauseOwnScreenSharePreviewOnUnfocus;
if (validated.disablePictureInPicturePopout !== undefined)
this.disablePictureInPicturePopout = validated.disablePictureInPicturePopout;
if (validated.screenShareHardwareAcceleration !== undefined)
this.screenShareHardwareAcceleration = validated.screenShareHardwareAcceleration;
}
private validateSettings(data: VoiceSettingsUpdate): VoiceSettingsUpdate {
@@ -387,6 +397,7 @@ class VoiceSettingsStore {
pauseOwnScreenSharePreviewOnUnfocus:
data.pauseOwnScreenSharePreviewOnUnfocus ?? this.pauseOwnScreenSharePreviewOnUnfocus,
disablePictureInPicturePopout: data.disablePictureInPicturePopout ?? this.disablePictureInPicturePopout,
screenShareHardwareAcceleration: data.screenShareHardwareAcceleration ?? this.screenShareHardwareAcceleration,
};
}
}

View File

@@ -23,6 +23,7 @@ import {Logger} from '@app/lib/Logger';
import {Platform} from '@app/lib/Platform';
import LocalVoiceStateStore from '@app/stores/LocalVoiceStateStore';
import MediaPermissionStore from '@app/stores/MediaPermissionStore';
import VoiceSettingsStore from '@app/stores/VoiceSettingsStore';
import VoiceConnectionManager from '@app/stores/voice/VoiceConnectionManager';
import {syncLocalVoiceStateWithServer, updateLocalParticipantFromRoom} from '@app/stores/voice/VoiceMediaEngineBridge';
import VoiceMediaStateCoordinator from '@app/stores/voice/VoiceMediaStateCoordinator';
@@ -30,11 +31,25 @@ import {ScreenRecordingPermissionDeniedError} from '@app/utils/errors/ScreenReco
import {ensureNativePermission} from '@app/utils/NativePermissions';
import {isDesktop, isNativeMacOS} from '@app/utils/NativeUtils';
import {SoundType} from '@app/utils/SoundUtils';
import {type Room, type ScreenShareCaptureOptions, Track, type TrackPublishOptions} from 'livekit-client';
import {
type Room,
type ScreenShareCaptureOptions,
Track,
type TrackPublishOptions,
type VideoCodec,
} from 'livekit-client';
import {makeAutoObservable, runInAction} from 'mobx';
const logger = new Logger('VoiceScreenShareManager');
function getPreferredScreenShareCodec(): VideoCodec {
if (VoiceSettingsStore.getScreenShareHardwareAcceleration()) {
return 'h265';
}
return 'vp9';
}
class VoiceScreenShareManager {
isScreenSharePending = false;
@@ -160,8 +175,16 @@ class VoiceScreenShareManager {
this.isScreenSharePending = true;
});
const preferredVideoCodec = publishOptions?.videoCodec ?? getPreferredScreenShareCodec();
const effectivePublishOptions = enabled
? {
...publishOptions,
videoCodec: preferredVideoCodec,
}
: publishOptions;
try {
await participant.setScreenShareEnabled(enabled, restOptions, publishOptions);
await participant.setScreenShareEnabled(enabled, restOptions, effectivePublishOptions);
if (enabled) applyState(true);
updateLocalParticipantFromRoom(room);