Skip to content

WebScreenShareFixes: fix malformed SDP rejected by Discord on niri/wlroots#4159

Open
coleleavitt wants to merge 1 commit into
Vendicated:mainfrom
coleleavitt:fix/wssf-malformed-sdp
Open

WebScreenShareFixes: fix malformed SDP rejected by Discord on niri/wlroots#4159
coleleavitt wants to merge 1 commit into
Vendicated:mainfrom
coleleavitt:fix/wssf-malformed-sdp

Conversation

@coleleavitt
Copy link
Copy Markdown

Summary

The WebScreenShareFixes plugin generates SDP that Discord's RTC server silently rejects on non-Mutter Wayland compositors (niri, hyprland, sway), causing "chooser appears, you pick, viewers see nothing" for Vesktop users on those compositors. Two specific bugs in the plugin:

  1. x-google-max-bitrate=80_000 — JavaScript numeric-literal underscore separator. The 80_000 is a valid JS literal (= 80000) but the replacement string is interpolated literally into the SDP, producing x-google-max-bitrate=80_000 (with underscore) on the wire. RFC 4566 requires plain integers; Discord's parser rejects this fmtp parameter and falls back to a codec the encoder isn't configured to send.

  2. b=AS:800000 injected inside an a=fmtp: line. b=AS: is a session/media-level bandwidth attribute (its own SDP line per RFC 4566), not an fmtp parameter. Injecting it inside a=fmtp:96 ...;b=AS:800000;level-asymmetry-allowed=1;... produces malformed SDP. Discord rejects the entire H.264 codec line.

Why this only surfaces now

Discord-in-Firefox uses the web JS pipeline (no Vencord, no SDP munging) and sends valid SDP — works everywhere. Discord-in-Chromium-via-Vencord on GNOME/Mutter also worked because Mutter's WebRTC stack has lenient SDP parsing OR because the codec falls back gracefully. On niri/hyprland/sway the rejection is fatal.

Fix

-                    replace: '"x-google-max-bitrate=80_000"'
+                    replace: '"x-google-max-bitrate=80000"'
-                {
-                    match: ";level-asymmetry-allowed=1",
-                    replace: ";b=AS:800000;level-asymmetry-allowed=1"
-                },

Removed the entire b=AS: injection — it was never valid SDP. The 80 Mbps bitrate cap removal (which is the legitimate purpose of the plugin per its description) still works via the corrected x-google-max-bitrate=80000 line.

Test plan

Empirically verified on Vesktop 1.6.5 + Vencord v1.14.10 + niri 26.04 + Electron 40.4.0 + Chromium 144 + xdg-desktop-portal-gnome 48:

  • Before: chooser dialog opens, source picked, stream "starts" but viewers see no video. Discord side: stream session ends after ~700ms.
  • After: chooser opens, source picked, stream starts cleanly, viewers see the screenshare.

No regression on Mutter/GNOME — verified the corrected SDP is still accepted there.

Refs

@coleleavitt coleleavitt force-pushed the fix/wssf-malformed-sdp branch from 8e3def4 to 100f02a Compare May 1, 2026 01:54
…roots

- x-google-max-bitrate=80_000 -> 80000 (underscore invalid in SDP per RFC 4566)
- remove b=AS:800000 fmtp injection (b=AS is session-level, not fmtp)

Both caused Discord RTC server to reject the video codec on niri/wlroots.
Firefox-Discord (no Vencord) was unaffected, masking the bug on Mutter.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes WebScreenShareFixes generating malformed SDP in the web (Chromium/Vesktop) pipeline, which could cause Discord’s RTC server to reject the offer/answer on some Wayland compositors (wlroots/niri/hyprland/sway), resulting in screenshare starting but showing no video to viewers.

Changes:

  • Replace the injected SDP fmtp value x-google-max-bitrate=80_000 with x-google-max-bitrate=80000 to avoid sending an underscore in the SDP integer.
  • Remove the invalid injection of b=AS:800000 inside an a=fmtp: parameter list (not valid SDP syntax in that position).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants