Skip to content

isE2EESimulcastSupported() returns undefined` for an unrecognized User-Agent, silently disabling simulcast on E2EE calls #2026

Description

@drewwells

Describe the bug

What I'm expecting

The ability to make calls between two element X iOS apps running on iPhones. The user-agent this app uses is not recognized by this library: Element X/26.07.4 (iPhone Air; iOS 26.5.2; Scale/1.00)

We could could change this app to fail open when not recognizing a user agent. The guard exists to work around a specific, long-fixed WebKit bug https://bugs.webkit.org/show_bug.cgi?id=257803, so I think it's safe to enable simulcast by default now rather than disabling by default and having the current behavior of catching up to network bandwidth.

export function isE2EESimulcastSupported() {
  const browser = getBrowser();
  if (!browser) {
    // Unknown UA (embedded webview, native wrapper). The guard below targets a
    // specific WebKit bug fixed in 17.2; don't punish clients we can't identify.
    return true;
  }
  …
}

What happens instead

The phones provide only a single resolution even when multiple are supported. On network slowness, the video hangs then fast forwards to catch up

Reproduction

Both clients below joined the same room, with the same SDK
(2.19.2)
, same codec (VP8), same E2EE (GCM) and same 1280x720 capture.
Only the UA differs.

Have two clients join a call. One with an agent like this used in Element X

Element X/26.07.4 (iPhone Air; iOS 26.5.2; Scale/1.00)     <-- no regex matches

What the SFU recorded for the two publishers:

iOS 26.5.2 / WKWebView (custom UA)    simulcast: False
  layers (1): HIGH 1280x720@1700k

Mac OS X / Firefox 153.0              simulcast: True
  layers (3): LOW 320x180@160k rid=q, MEDIUM 640x360@450k rid=h, HIGH 1280x720@1700k rid=f

The iOS app only publishes a single SFU with no fallback

iPhone  video/VP8  bitrate med=1700000 max=1700000    <-- pinned, no fallback
Firefox video/VP8  bitrate med=450000  max=1700000    <-- SFU using the 450k layer

Logs

System Info

- livekit-client **2.19.2**
- livekit-server **1.13.4**
- Publisher: iOS 26.5.2 / 18.7.9, `WKWebView` with a custom UA (Element X 26.07.4)
- Comparison publisher: Firefox 153.0 / macOS

Severity

annoyance

Additional Information

No response

Activity

  1. lukasIO commented on Jul 30, 2026

    @lukasIO
    Contributor

    Thanks for the report, I'm a bit hesitant to enable it by default as that could potentially break things for apps that don't support it (while the current situation is "only" simulcast not being available for those).
    Wouldn't it be fair to say element x iOS should mimic the actual Safari UA more closely given that's what they're ultimately using?

  2. drewwells commented on Jul 30, 2026

    @drewwells
    Author

    Certainly could feed a Safari UA in the runtime. I think it's still better to identify itself separately from a browser though.

    If you did enable simulcast by default, wouldn't those other apps still just choose the first resolution in the array they are already selecting from? Worst cast, enabling simulcast presents their first choice as a different resolution than the one being used today. It feels heavy handed to make this a breaking change.

    Honestly, the problem goes away if we don't try to alter behavior based on a UA. That gives you less work in the future. If you think this would break clients... it could be drafted as a separate API to call then deprecate the current "UA aware" one later.

  3. lukasIO commented on Jul 31, 2026

    @lukasIO
    Contributor

    the problem goes away if we don't try to alter behavior based on a UA.

    there is quite a lot of code in this SDK that's enabling/disabling behaviour based on UA parsing. Unfortunately that is the only way (to my knowledge) to determine certain cross browser bugs that cannot be gated on behaviour/feature ability

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions