fix(desktop): enable PulseAudio loopback flag so screen share starts on Linux
Chromium gates the PulseAudio loopback path behind the PulseaudioLoopbackForScreenShare feature flag. Without it, returning audio: 'loopback' from setDisplayMediaRequestHandler rejects the whole getDisplayMedia request, so screen share never starts when the user has "Share system audio" enabled. Also surface a clear warning toast on loopback failure (PipeWire-only without pulse compat, macOS without Catap) instead of failing silently — no auto-retry, since the picker selection is already consumed.
This commit is contained in:
+14
-1
@@ -206,7 +206,7 @@ ScreenShareConfig {
|
|||||||
fps: number, // 30-120
|
fps: number, // 30-120
|
||||||
mode: 'gaming' | 'text', // Affects bitrate & content hint
|
mode: 'gaming' | 'text', // Affects bitrate & content hint
|
||||||
customBitrateKbps: number | null, // Admin override (if allowed)
|
customBitrateKbps: number | null, // Admin override (if allowed)
|
||||||
shareAudio: boolean // System audio (disabled in Electron)
|
shareAudio: boolean // System audio loopback (see Platform Support below)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -234,6 +234,19 @@ ScreenShareConfig {
|
|||||||
- `allowCustomBitrate` toggle
|
- `allowCustomBitrate` toggle
|
||||||
- `bitrateMatrixOverrides` (JSON sparse overrides)
|
- `bitrateMatrixOverrides` (JSON sparse overrides)
|
||||||
|
|
||||||
|
### System Audio Loopback (`shareAudio`)
|
||||||
|
|
||||||
|
The "Share system audio" toggle in `ScreenSharePicker` adds an audio track to the screen-share publication. In the browser it maps to `getDisplayMedia({ audio: true })`. In Electron, the `setDisplayMediaRequestHandler` callback (`packages/desktop/src/main.ts`) returns `audio: 'loopback'` to opt into Chromium's system-audio loopback path.
|
||||||
|
|
||||||
|
| Platform | Mechanism | Notes |
|
||||||
|
|----------|-----------|-------|
|
||||||
|
| Browser (Chrome/Edge) | `getDisplayMedia({ audio: true })` | Tab/window/system audio per the user's pick |
|
||||||
|
| Electron / Windows | Chromium native loopback | Works out of the box |
|
||||||
|
| Electron / macOS 13+ | CoreAudio Tap (Catap) | Requires `NSAudioCaptureUsageDescription` (set by `electron-builder.yml#mac.extendInfo`) |
|
||||||
|
| Electron / Linux | PulseAudio loopback | **Requires** the `PulseaudioLoopbackForScreenShare` Chromium feature flag — enabled at startup in `main.ts` for Linux. Works on PulseAudio and on PipeWire systems with the `pipewire-pulse` compat layer. PipeWire-only systems without pulse compat will fail. |
|
||||||
|
|
||||||
|
**Failure handling.** When loopback is not supported, Chromium rejects the entire `getDisplayMedia` request — the source-picker selection has already been consumed, so silently retrying without audio would re-prompt the picker. `startScreenShare` (`utils/screenShare.ts`) instead surfaces a warning toast directing the user to disable "Share system audio" if their system does not support loopback. We do **not** auto-mutate the user's `shareAudio` preference.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Voice Fullscreen
|
## Voice Fullscreen
|
||||||
|
|||||||
@@ -739,6 +739,11 @@ function handleDeepLink(url: string): void {
|
|||||||
// libraries are loaded in the same process. Force GTK 3 for compatibility.
|
// libraries are loaded in the same process. Force GTK 3 for compatibility.
|
||||||
if (process.platform === 'linux') {
|
if (process.platform === 'linux') {
|
||||||
app.commandLine.appendSwitch('gtk-version', '3');
|
app.commandLine.appendSwitch('gtk-version', '3');
|
||||||
|
// Chromium ships PulseAudio loopback for screen-share behind a feature flag.
|
||||||
|
// Without it, returning `audio: 'loopback'` from setDisplayMediaRequestHandler
|
||||||
|
// fails the whole getDisplayMedia request — screen share never starts when the
|
||||||
|
// user has "Share system audio" enabled.
|
||||||
|
app.commandLine.appendSwitch('enable-features', 'PulseaudioLoopbackForScreenShare');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set as default protocol handler
|
// Set as default protocol handler
|
||||||
@@ -896,8 +901,15 @@ if (!gotTheLock) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide the selected source — Electron creates the MediaStream
|
// Provide the selected source — Electron creates the MediaStream.
|
||||||
// System audio loopback: Windows/Linux native, macOS 13+ via ScreenCaptureKit
|
// System audio loopback support varies:
|
||||||
|
// - Windows: native (Chromium default).
|
||||||
|
// - macOS 13+: CoreAudio Tap; requires NSAudioCaptureUsageDescription
|
||||||
|
// in Info.plist (electron-builder injects it via mac.extendInfo).
|
||||||
|
// - Linux: PulseAudio loopback, gated behind the
|
||||||
|
// `PulseaudioLoopbackForScreenShare` feature flag we enable above.
|
||||||
|
// Fails on PipeWire-only systems without pulse compat — the
|
||||||
|
// renderer catches that and toasts the user.
|
||||||
callback({ video: selected, ...(shareAudio ? { audio: 'loopback' } : {}) });
|
callback({ video: selected, ...(shareAudio ? { audio: 'loopback' } : {}) });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[Main:ScreenShare] Handler error:', err);
|
console.error('[Main:ScreenShare] Handler error:', err);
|
||||||
|
|||||||
@@ -306,6 +306,16 @@ export async function startScreenShare(room: Room): Promise<boolean> {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[ScreenShare] Failed to start screen share:', err);
|
console.error('[ScreenShare] Failed to start screen share:', err);
|
||||||
if (hwOverdrive) deactivateHwOverdrive();
|
if (hwOverdrive) deactivateHwOverdrive();
|
||||||
|
// Loopback unsupported (Linux without pulse, macOS without Catap) makes
|
||||||
|
// the whole getDisplayMedia call reject. No auto-retry: the picker
|
||||||
|
// selection was consumed, retrying would re-prompt it.
|
||||||
|
if (config.shareAudio && err instanceof Error && err.name !== 'NotAllowedError') {
|
||||||
|
useUIStore.getState().addToast(
|
||||||
|
'Could not start stream with system audio. Disable "Share system audio" in the picker if your system does not support it.',
|
||||||
|
'warning',
|
||||||
|
8000,
|
||||||
|
);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user