Skip to content

Conversation

@Brazol
Copy link
Contributor

@Brazol Brazol commented Oct 24, 2025

resolves FLU-306

This PR introduces several fixes and improvements related to audio and video device management on the web platform. It addresses issues encountered during initial device setup and when switching between input/output devices during the call.

It also adds a sample implementation of device setup on the Dogfooding's lobby screen.

Summary by CodeRabbit

  • New Features

    • Audio/video input pickers in the lobby.
    • Ability to change audio output during calls with runtime support detection.
    • Lobby video respects an initial camera device preference.
  • Bug Fixes

    • Improved web audio/video device constraint handling.
    • Added iOS audio-output fallback when none reported.
    • Fixed a media-constraint typo.
  • UI

    • Updated camera/blur controls with clearer tooltips and live device labels.
  • Behavior

    • Settings menu hides audio-output option when unsupported; permission-aware device controls.

@Brazol Brazol requested a review from a team as a code owner October 24, 2025 11:19
@coderabbitai
Copy link

coderabbitai bot commented Oct 24, 2025

Warning

Rate limit exceeded

@Brazol has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 0 minutes and 59 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between f400a89 and 95638fe.

📒 Files selected for processing (1)
  • packages/stream_video/lib/src/webrtc/rtc_media_device/rtc_media_device_notifier.dart (3 hunks)

Walkthrough

Adds lobby device-selection UI and state, threads initial camera device into StreamLobbyVideo, adds Call APIs to check/set audio output with platform guards, adjusts web media constraint shapes to exact deviceId matches, updates rtc_audio implementations and device enumeration (including iOS earpiece fallback), and minor fixes/changelog updates.

Changes

Cohort / File(s) Summary
UI — Lobby & Device Pickers
dogfooding/lib/screens/lobby_screen.dart
Adds audio/video device lists and selection state, subscribes to device notifier, handles device changes, adds modal pickers and list tiles, and passes selected devices into join options.
Settings Menu
dogfooding/lib/widgets/settings_menu/settings_menu.dart
Renders the audio-output menu item only when call.checkIfAudioOutputChangeSupported() is true (replaces unconditional branch).
Lobby Video Widget
packages/stream_video_flutter/lib/src/call_screen/lobby_video.dart
Adds public initialCameraDevice property and applies its device id in camera track creation/toggle via CameraConstraints.
Call API — Audio Output
packages/stream_video/lib/src/call/call.dart
Adds Future<Result<None>> setAudioOutputDevice(RtcMediaDevice) and bool checkIfAudioOutputChangeSupported() and imports rtc_audio API.
RTC Audio API Implementations
packages/stream_video/lib/src/webrtc/rtc_audio_api/rtc_audio_html.dart, .../rtc_audio_native.dart, .../rtc_audio_stub.dart
Adds checkIfAudioOutputChangeSupported() across platforms; web probes and guards setSinkId, native returns true, stub unimplemented.
RTC Manager & Device Notifier
packages/stream_video/lib/src/webrtc/rtc_manager.dart, packages/stream_video/lib/src/webrtc/rtc_media_device/rtc_media_device_notifier.dart
RtcManager short-circuits with an error when web audio-output changes unsupported; notifier injects iOS earpiece fallback if missing and emits devices immediately.
Web Media Constraints
packages/stream_video/lib/src/webrtc/media/audio_constraints.dart, packages/stream_video/lib/src/webrtc/media/camera_constraints.dart
On Web, deviceId constraints are now exact-match objects ({'exact': deviceId}); non-web behavior preserved.
Misc. Media Fixes
packages/stream_video/lib/src/webrtc/media/media_constraints.dart, packages/stream_video/lib/src/sorting/call_participant_sorting_presets.dart
Fixes typo straemDumpstreamDump and removes an unused import.
Changelogs
packages/stream_video/CHANGELOG.md, packages/stream_video_flutter/CHANGELOG.md
Updates Unreleased headings and documents input/output device fixes and checkIfAudioOutputChangeSupported().

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LobbyScreen
    participant DevicePicker
    participant Call
    participant RtcManager
    participant RtcAudioAPI
    participant Browser

    User->>LobbyScreen: open device picker
    LobbyScreen->>DevicePicker: show device list
    DevicePicker-->>LobbyScreen: selected device
    LobbyScreen->>LobbyScreen: update selectedAudio/Video

    User->>LobbyScreen: Join call (with selected devices)
    LobbyScreen->>Call: join(..., audioInputDevice, videoInputDevice)

    Note over LobbyScreen,Call: During call — change audio output
    LobbyScreen->>Call: setAudioOutputDevice(device)
    Call->>Call: checkIfAudioOutputChangeSupported()
    alt platform == web
        Call->>RtcAudioAPI: checkIfAudioOutputChangeSupported()
        RtcAudioAPI->>Browser: try audioElement.setSinkId(deviceId)
        Browser-->>RtcAudioAPI: success / throws
        RtcAudioAPI-->>Call: true / false
    else
        RtcAudioAPI-->>Call: true
    end
    alt supported
        Call->>RtcManager: apply sinkId to remote audio tracks
        RtcManager-->>Call: Result success
    else not supported
        Call-->>LobbyScreen: Result error
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Points needing extra attention:

  • Web constraint shape changes in audio_constraints.dart and camera_constraints.dart.
  • Runtime capability checks and early returns in rtc_audio_html.dart and how RtcManager handles unsupported cases.
  • initialCameraDevice propagation and null-safety through StreamLobbyVideo lifecycle and camera toggle logic.
  • Device enumeration behavior and the iOS earpiece fallback in rtc_media_device_notifier.dart.
  • UI state/subscription lifecycle and modal interactions in dogfooding/lib/screens/lobby_screen.dart.

Possibly related PRs

Suggested reviewers

  • renefloor
  • xsahil03x

Poem

🐰 I hopped through code to pick a mic and cam,
I nudged the sink and taught the browser a dram.
A lobby picker, camera keeps its tune,
iOS found an earpiece beneath the moon.
Hooray — a rabbit's tiny celebratory ram! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description is largely incomplete compared to the required template. While it does provide an issue reference (FLU-306) and a brief two-sentence summary explaining that the PR addresses fixes and improvements for audio/video device management on web and adds a sample dogfooding implementation, it is missing most required sections: the Goal section is absent, Implementation details are not described, UI Changes section with screenshots/videos is missing, Testing explanation is not provided, and both the Contributor Checklist and Reviewer Checklist sections are completely absent. The description reads more like a brief summary than a complete PR documentation following the template structure. The author should expand the pull request description to follow the provided template more closely. At minimum, add explicit sections for Goal (why these changes are needed), Implementation details (how the fixes were implemented), Testing (how to verify the changes work), and complete the Contributor Checklist by confirming the PR is assigned, a Slack thread was started, and the issue link is added. UI Changes section with before/after screenshots or videos would be particularly valuable for demonstrating the device selection functionality added to the lobby screen. The current description provides only a high-level overview and lacks the detailed documentation needed for effective code review.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "fix(llc): fixes for input/output device setting on web" directly reflects the main changes in the changeset. The title captures the primary objective of fixing input and output device setting functionality on the web platform, which aligns with the overarching goal stated in both the PR description and the linked issue FLU-306. The title is concise, specific, and clearly communicates the primary focus of the changes to someone reviewing the repository history. While it does not explicitly mention the sample dogfooding implementation, that aspect is appropriately described in the PR description as secondary ("also adds a sample implementation").
Out of Scope Changes Check ✅ Passed The vast majority of changes are directly in scope and address the linked issue FLU-306. The core fixes for web device handling, device management APIs, and platform-specific constraint handling are all clearly aligned with the objective. However, there are two minor out-of-scope cleanup items: the variable name typo fix in media_constraints.dart (straemDump → streamDump) and the removal of an unused import in call_participant_sorting_presets.dart. These are maintenance improvements rather than fixes directly related to device switching functionality. Additionally, permission request ordering changes in home_screen.dart could be viewed as tangentially related since they ensure permissions are requested in a logical sequence for device access.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Oct 24, 2025

Codecov Report

❌ Patch coverage is 6.25000% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 4.83%. Comparing base (1769457) to head (95638fe).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...kages/stream_video/lib/src/webrtc/rtc_manager.dart 0.00% 4 Missing ⚠️
...video_flutter/lib/src/call_screen/lobby_video.dart 0.00% 3 Missing ⚠️
packages/stream_video/lib/src/call/call.dart 0.00% 2 Missing ⚠️
..._video/lib/src/webrtc/media/media_constraints.dart 0.00% 2 Missing ⚠️
..._video/lib/src/webrtc/media/audio_constraints.dart 0.00% 1 Missing ⚠️
...video/lib/src/webrtc/media/camera_constraints.dart 0.00% 1 Missing ⚠️
...lib/src/webrtc/rtc_audio_api/rtc_audio_native.dart 0.00% 1 Missing ⚠️
...tc/rtc_media_device/rtc_media_device_notifier.dart 50.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##            main   #1086      +/-   ##
========================================
- Coverage   4.84%   4.83%   -0.01%     
========================================
  Files        591     591              
  Lines      40500   40508       +8     
========================================
- Hits        1961    1960       -1     
- Misses     38539   38548       +9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 29d99c5 and 3cc3d76.

📒 Files selected for processing (1)
  • dogfooding/lib/screens/lobby_screen.dart (7 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: analyze
  • GitHub Check: build
  • GitHub Check: stream_video_noise_cancellation
  • GitHub Check: stream_video_push_notification
  • GitHub Check: stream_video_flutter
  • GitHub Check: stream_video
  • GitHub Check: analyze_legacy_version
🔇 Additional comments (11)
dogfooding/lib/screens/lobby_screen.dart (11)

2-2: LGTM - Required import for device subscription handling.

The dart:async import is necessary for StreamSubscription and unawaited used in the device management implementation.


31-38: LGTM - Device state management setup.

The state variables are properly typed and initialized for tracking device selection and managing device change subscriptions.


66-72: LGTM - Device options correctly applied to call connection.

The selected devices are properly passed to CallConnectOptions when joining the call.


84-84: LGTM - Proper subscription cleanup.

The device change subscription is correctly canceled on dispose.


88-102: LGTM - Robust device change handler.

The implementation correctly filters devices by kind and includes a mounted check before updating state. Using growable: false is a good optimization.


104-125: LGTM - Audio input picker correctly implemented.

The modal flow properly checks for mounted state after the async operation and updates state correctly.


204-206: Verify ValueKey usage doesn't cause unintended side effects.

Using ValueKey(_cameraTrack) will cause the entire StreamLobbyVideo widget to be recreated whenever the camera track changes. While this might be intentional to reset the video view state, it could also cause:

  • Loss of internal widget state
  • Brief visual flickers during device switching
  • Unnecessary rebuilds

Please verify that recreating the entire widget is the desired behavior when switching video input devices, rather than just updating the existing track.


220-246: LGTM - Improved UX with tooltip for blur control.

The blur control is now wrapped in a Tooltip with appropriate messages, improving discoverability while preserving the existing functionality.


250-314: LGTM - Well-implemented device selection UI.

The device selection controls are properly implemented with:

  • Appropriate tooltips for accessibility
  • Correct enablement logic based on device availability
  • Proper text overflow handling
  • Clear visual feedback of selected devices

366-430: LGTM - Robust device picker implementation.

The device picker sheet is well-implemented with:

  • "System default" option for resetting to default device
  • Proper fallback to device ID when label is empty (good defensive coding)
  • Appropriate size constraints for the list

432-467: LGTM - Clean device list tile implementation.

The device list tile provides clear visual feedback for selection state using modern Flutter color APIs and appropriate styling.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e093607 and 9ef682a.

📒 Files selected for processing (1)
  • dogfooding/lib/screens/home_screen.dart (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: analyze
  • GitHub Check: build
  • GitHub Check: stream_video_noise_cancellation
  • GitHub Check: stream_video_push_notification
  • GitHub Check: stream_video
  • GitHub Check: stream_video_flutter
  • GitHub Check: analyze_legacy_version

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
dogfooding/lib/screens/lobby_screen.dart (2)

54-54: Error handling for device enumeration is still missing.

This issue was previously flagged. The unawaited call will silently ignore enumeration errors, leaving device lists empty without user feedback.


157-166: Mounted check and error handling still needed after async camera operations.

This issue was previously flagged. After the async camera track operations (lines 158-164), there's no mounted check before calling setState at line 166. Additionally, the camera operations lack error handling.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9ef682a and fc8765f.

📒 Files selected for processing (1)
  • dogfooding/lib/screens/lobby_screen.dart (7 hunks)
🔇 Additional comments (2)
dogfooding/lib/screens/lobby_screen.dart (2)

32-39: Clean device management implementation.

The device state management, change handling, and audio input picker are well-structured with appropriate mounted checks and clean separation of concerns.

Also applies to: 44-45, 98-112, 114-135


382-483: Nice device picker UI components.

The _DevicePickerSheet and _DeviceListTile widgets provide a clean, accessible device selection experience with proper visual feedback for the selected state and a "System default" option.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/stream_video/lib/src/webrtc/rtc_media_device/rtc_media_device_notifier.dart (1)

109-116: Remove duplicate emission to the device stream.

With the addition of _devicesController.add(mediaDevices) at line 149, this method now emits the device list twice:

  1. Once inside enumerateDevices() at line 149
  2. Again at line 115

This causes duplicate emissions to subscribers of onDeviceChange stream, potentially triggering unnecessary UI updates.

Apply this diff to remove the duplicate emission:

 Future<void> _onDeviceChange(_) async {
   final devicesResult = await enumerateDevices();
   final devices = devicesResult.getDataOrNull();
   
-  if (devices == null) return;
-  
-  _devicesController.add(devices);
+  // Devices are now emitted within enumerateDevices() at line 149
 }

Alternatively, if you want to keep emission only in _onDeviceChange, remove line 149 instead and ensure all callers go through the stream subscription rather than direct enumerateDevices() calls.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fc8765f and f400a89.

📒 Files selected for processing (5)
  • packages/stream_video/CHANGELOG.md (1 hunks)
  • packages/stream_video/lib/src/call/call.dart (3 hunks)
  • packages/stream_video/lib/src/webrtc/rtc_manager.dart (2 hunks)
  • packages/stream_video/lib/src/webrtc/rtc_media_device/rtc_media_device_notifier.dart (2 hunks)
  • packages/stream_video_flutter/CHANGELOG.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/stream_video_flutter/CHANGELOG.md
  • packages/stream_video/lib/src/call/call.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: analyze
  • GitHub Check: build
🔇 Additional comments (4)
packages/stream_video/lib/src/webrtc/rtc_manager.dart (2)

35-36: LGTM! Clean import with appropriate scoping.

The use of the show clause to import only checkIfAudioOutputChangeSupported is good practice, keeping the namespace clean and making dependencies explicit.


1114-1122: Good defensive check for browser capability.

The capability check correctly prevents attempting to set audio output on browsers that don't support setSinkId. The early return with a descriptive error message ensures graceful handling of unsupported platforms.

packages/stream_video/CHANGELOG.md (1)

1-11: LGTM! Changelog properly documents the changes.

The changelog updates are well-formatted and clearly document:

  • The web platform fixes for input/output device handling
  • The new capability check API

The heading level change to ## is consistent with the rest of the changelog structure.

packages/stream_video/lib/src/webrtc/rtc_media_device/rtc_media_device_notifier.dart (1)

134-147: LGTM! iOS earpiece fallback is correctly implemented.

The earpiece enum value is used consistently throughout the codebase and properly parsed from the API. The iOS fallback logic correctly injects the device using the canonical AudioSettingsRequestDefaultDeviceEnum.earpiece value, matching existing patterns across the SDK and test suite.

@Brazol Brazol merged commit c8683bf into main Oct 29, 2025
12 of 13 checks passed
@Brazol Brazol deleted the fix/fixes-for-output-input-devices-on-web branch October 29, 2025 10:39
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.

3 participants