fix: eliminate screen share audio feedback loop + upgrade Electron 33→40

Screen sharing with audio captured the app's own voice playback, causing
users to hear themselves echoed back. Fixed via two layers:

- Add restrictOwnAudio constraint (Chrome 141+/Chromium 144) to exclude
  the app's own audio from system audio capture
- Add shareAudio toggle so users can disable system audio entirely
- Remove outdated macOS audio block (now supported via ScreenCaptureKit)
- Upgrade Electron 33→40 (Chromium 130→144) so restrictOwnAudio works
  natively in the desktop app
- Add NSAudioCaptureUsageDescription for macOS 14.2+ audio capture
- Add GTK 3 fallback for Linux GNOME compatibility (Electron 36+)
This commit is contained in:
Jannis Braun
2026-03-16 18:01:40 +01:00
parent 7a86cde67e
commit 46f55643ae
10 changed files with 117 additions and 53 deletions
+8 -2
View File
@@ -10,6 +10,7 @@ export interface ScreenShareConfig {
fps: 60 | 45 | 30;
mode: 'gaming' | 'text';
customBitrateKbps: number | null;
shareAudio: boolean;
}
interface VoiceState {
@@ -134,7 +135,7 @@ export const useVoiceStore = create<VoiceState>()(
inputDeviceId: 'default',
outputDeviceId: 'default',
focusedParticipantId: null,
screenShareConfig: { height: 720, fps: 60, mode: 'gaming', customBitrateKbps: null },
screenShareConfig: { height: 720, fps: 60, mode: 'gaming', customBitrateKbps: null, shareAudio: true },
participantVolumes: new Map(),
setParticipantVolume: (userId, volume) => {
set((state) => {
@@ -527,7 +528,7 @@ export const useVoiceStore = create<VoiceState>()(
}),
{
name: 'backspace-voice-settings',
version: 9,
version: 10,
migrate: (persistedState: any, version: number) => {
if (version === 0) {
persistedState.streamAttenuationEnabled = false;
@@ -566,6 +567,11 @@ export const useVoiceStore = create<VoiceState>()(
if (version < 9) {
delete persistedState.currentVoiceChannelId;
}
if (version < 10) {
if (persistedState.screenShareConfig) {
persistedState.screenShareConfig.shareAudio = true;
}
}
return persistedState;
},
storage: createJSONStorage(() => localStorage),