fix(llc): mute camera in background on devices without multitasking camera access - #1346
Draft
renefloor wants to merge 2 commits into
Draft
fix(llc): mute camera in background on devices without multitasking camera access#1346renefloor wants to merge 2 commits into
renefloor wants to merge 2 commits into
Conversation
…amera access iOS suspends camera capture in the background unless the device supports multitasking camera access, leaving other participants with a frozen frame. On those devices the camera track is now muted while the app is backgrounded and restored on resume. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v2 #1346 +/- ##
=====================================
Coverage ? 31.16%
=====================================
Files ? 375
Lines ? 28799
Branches ? 0
=====================================
Hits ? 8975
Misses ? 19824
Partials ? 0 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…state The mute decision now reads isIOSMultitaskingCameraAccessSupported from the capture session in use instead of inferring it from whether the SDK managed to turn multitasking camera access on, which also reads false when it was never asked for. Requires the plugin fix in GetStream/webrtc-flutter#88, pinned here through a git override until it ships. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🎯 Goal
On iOS, the OS suspends camera capture as soon as the app goes to the background unless the device supports multitasking camera access (effectively M1 iPads and later). On every other device — older iPads, and any device on iOS 15 — the outgoing video track stays "on" while no frames are produced, so the other participants are left staring at a frozen frame for as long as the app is backgrounded. This is easy to hit with Picture-in-Picture, where backgrounding the app is the whole point.
The Swift SDK fixed this in 1.15.0 with
ApplicationLifecycleVideoMuteAdapter: on devices whereisMultitaskingCameraAccessSupportedisfalse, it mutes the video track on background and unmutes on foreground, so remote participants see a clear camera-off state instead of a stuck image. This ports that behaviour to Flutter.🛠 Implementation details
The decision lives in a new pure function,
shouldMuteCameraInBackgroundinpackages/stream_video/lib/src/internal/_background_mute_policy.dart:StreamVideo._onAppStatecalls it in place of the previous_options.muteVideoWhenInBackground && isVideoEnabledcheck, passingCurrentPlatform.typeand the device's multitasking camera access support, read once per background transition. The resume path is unchanged —_mutedCameraByStateChangealready restores the camera and does not care why it was muted.muteVideoWhenInBackgroundkeeps its meaning as the explicit, all-platforms override and now has a doc comment noting that iOS may mute regardless.internal/is not exported from the barrel, so no public API is added.Two deliberate departures from the Swift implementation:
setCameraEnabled(enabled: false), which also tears down capture. On iOS that costs nothing extra — the OS has already suspended the session — and it keeps a single resume path rather than two.isMultitaskingCameraAccessSupporteddirectly, and so does this now — throughHelper.isIOSMultitaskingCameraAccessSupported(), added in GetStream/webrtc-flutter#88.null(support could not be read) is treated as "mute", so the frozen frame is never the fallback.This needs GetStream/webrtc-flutter#88, pinned here through a
dependency_overridesentry on commit3bb8787. The override must be dropped once astream_webrtc_flutterrelease carries the fix.That PR also fixes the bug underneath this one: a capture session is created per
getUserMediacall and starts without multitasking camera access, so toggling the camera off and on lost it — even on an M1 iPad. Without it, this PR would correctly decide not to mute on a capable device that had silently lost the capability, and the frozen frame would come back.🎨 UI Changes
No UI changes in this repo. The visible effect is on the remote side: a backgrounded participant on an unsupported device now renders as camera-off (avatar) rather than a frozen frame.
🧪 Testing
packages/stream_video/test/src/internal/background_mute_policy_test.dartcover the platform gate, the multitasking-supported case, support that could not be read, the explicit option on every platform, and the camera-already-off cases.stream_videosuite: 688 tests passing.flutter build ios --simulator --debugondogfoodingsucceeds against the git-sourced plugin, so the override resolves end to end.On-device behaviour is not verified. Reproducing it needs a pre-M1 iPad (or an iOS 15 device) in a call with a second participant watching: background the app and check whether the remote tile freezes or goes to camera-off. The device this was found on cannot currently run debug builds.
☑️Contributor Checklist
General
☑️Reviewer Checklist
🤖 Generated with Claude Code