Skip to content

Conversation

@Brazol
Copy link
Contributor

@Brazol Brazol commented Dec 11, 2025

Summary by CodeRabbit

  • Performance Improvements
    • Faster call.join() startup by optimizing WebRTC setup, deferring non‑critical analytics/reporting, and adding SDP caching.
  • New Features
    • New option to enable/disable precaching of generic SDPs at initialization.
    • Enhanced client metadata sent from the SDK (richer device/OS information).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 11, 2025

Walkthrough

Adds global clientDetails, moves client-details setup into StreamVideo initialization, pre-warms generic SDP cache in RtcManager, and converts several non-critical awaits in call lifecycle paths to fire-and-forget to reduce join latency.

Changes

Cohort / File(s) Summary
Changelog
packages/stream_video/CHANGELOG.md
Added Upcoming note describing improved call.join() performance and deferred non-critical operations.
Global state
packages/stream_video/lib/globals.dart
Added ClientDetails? clientDetails (internal) and imported SFU models to store global client metadata.
Call lifecycle
packages/stream_video/lib/src/call/call.dart
Converted multiple awaited tasks (SFU stats, connect options, call-settings application) to fire-and-forget via unawaited(...), preserving error logging where added.
Call session
packages/stream_video/lib/src/call/session/call_session.dart
Removed private _clientDetails and _ensureClientDetails(); call sites now use the global clientDetails; removed device_info/system_info imports.
StreamVideo init
packages/stream_video/lib/src/stream_video.dart
Replaced _setClientVersionDetails() with _setClientDetails() to build richer client metadata; added precacheGenericSdps option and calls to _setClientDetails() and RtcManager.cacheGenericSdp() during initialization.
RTC manager / SDP caching
packages/stream_video/lib/src/webrtc/rtc_manager.dart
Added static _cachedGenericSdp, cacheGenericSdp() to pre-warm RecvOnly/SendOnly SDPs, and changed getGenericSdp() to return cached values when available.
Tests
packages/stream_video/test/src/.../*.dart
Updated StreamVideoOptions usage in multiple tests to include new precacheGenericSdps parameter (e.g., precacheGenericSdps: false).

Sequence Diagram

sequenceDiagram
    participant App as App Startup / Test
    participant SV as StreamVideo
    participant Globals as globals.dart
    participant RM as RtcManager
    participant Call as Call.join()
    participant CS as CallSession
    App->>SV: StreamVideo.create(options)
    SV->>Globals: set global clientDetails (via _setClientDetails)
    SV->>RM: cacheGenericSdp() [unawaited]
    RM->>RM: generate RecvOnly & SendOnly SDPs and populate _cachedGenericSdp
    RM-->>SV: returns (fire-and-forget)
    App->>Call: call.join()
    Call->>CS: construct session (reads global clientDetails)
    CS->>CS: skip local client detail gathering
    par Non-critical (fire-and-forget)
        Call->>Call: unawaited(_applyConnectOptions())
        Call->>Call: unawaited(_sfuStatsReporter.sendSfuStats())
    and Critical path
        Call->>RM: getGenericSdp(direction) -> returns cached SDP
    end
    Call-->>App: join() completes while non-critical tasks continue
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing extra attention:
    • packages/stream_video/lib/src/call/session/call_session.dart — ensure removal of _ensureClientDetails() doesn't create race conditions when clientDetails is not yet set.
    • packages/stream_video/lib/src/stream_video.dart — verify platform-specific client metadata population and error handling.
    • packages/stream_video/lib/src/call/call.dart — confirm that converting awaits to fire-and-forget does not break critical sequencing or error propagation.
    • packages/stream_video/lib/src/webrtc/rtc_manager.dart — validate cache correctness and potential concurrency issues.

Possibly related PRs

Suggested reviewers

  • renefloor
  • xsahil03x

Poem

🐰
I pre-warm SDPs before the race,
tuck client details in a global place.
Fire-and-forget, the non-criticals hop,
join() speeds off — I clap and stop. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided by the author, leaving all required template sections (Goal, Implementation, Testing, etc.) completely unfilled. Add a comprehensive description following the template: explain why the optimization improves join time, detail how fire-and-forget patterns and SDP caching work, describe testing methodology, and complete the contributor checklist.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore(llc): improved join call time' directly aligns with the main change—optimizing call.join() performance by deferring non-critical operations and precaching SDPs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/improve-join-call-time

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.

@Brazol Brazol marked this pull request as ready for review December 11, 2025 17:18
@Brazol Brazol requested a review from a team as a code owner December 11, 2025 17:18
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: 4

🧹 Nitpick comments (5)
packages/stream_video/lib/globals.dart (1)

4-5: Document and constrain lifecycle of global clientDetails

The new internal global is fine for centralizing client metadata, but it would help to:

  • Add a short doc comment explaining when and by whom clientDetails is initialized.
  • Clarify (in docs or invariant) that it’s effectively write-once at startup, so later reads from CallSession can safely assume it’s either fully populated or intentionally null.

This keeps the implicit contract around this shared mutable state explicit.

Also applies to: 21-22

packages/stream_video/lib/src/webrtc/rtc_manager.dart (1)

112-120: SDP caching looks good; consider error semantics and minor concurrency nit

The caching approach is sound and should meaningfully reduce repeated generic SDP generation. Two small suggestions:

  • If offer.sdp ever ends up null, returning '' keeps the join flow running with an invalid SDP and hides the failure behind later errors. Consider making this a hard failure (e.g. throwing or returning a dedicated error type) so callers can surface a clear “failed to generate SDP” message instead of sending an empty SDP.
  • Very minor: if you ever care about avoiding duplicate work under concurrent calls, you could cache Future<String> or use putIfAbsent with an async initializer so simultaneous getGenericSdp(direction) calls share the same computation. Right now you may do redundant work, but it’s harmless.

Also applies to: 121-123, 126-130, 148-155

packages/stream_video/lib/src/call/session/call_session.dart (1)

254-266: Global clientDetails usage: confirm expected null/initialization behavior

Switching from a per-session _clientDetails to the global clientDetails simplifies wiring and avoids repeated device-info collection, which is good for join latency. A couple of behavior points to be explicit about:

  • clientDetails is now effectively best-effort: if join/fastReconnect is initiated before the global has been initialized, SFU will see clientDetails == null rather than the SDK blocking to compute it. If that’s intentional, it’s worth treating “no client details” as an acceptable, non-fatal case on the backend.
  • Because this is global, tests or edge flows that construct CallSession without going through the normal StreamVideo initialization will also send null client details. That’s functionally safe, but you may want a debug log/trace the first time you send a join with clientDetails == null to make this more observable.

If you ever need stricter guarantees, an alternative would be to thread a ClientDetails? into the CallSession constructor instead of reading globals, but the current approach is fine if the looser contract is acceptable.

Also applies to: 296-304, 318-328, 437-451

packages/stream_video/lib/src/call/call.dart (2)

1048-1053: Fire‑and‑forget SFU stats: behavior change looks intentional

All these call sites now treat _sfuStatsReporter?.sendSfuStats(...) as best‑effort telemetry rather than part of the control flow, which aligns with the PR goal of reducing latency and avoiding failures due to non‑critical reporting.

Assuming SfuStatsReporter.sendSfuStats is:

  • internally robust to concurrent invocations, and
  • catching/logging its own errors,

this change is reasonable and should improve responsiveness without affecting correctness.

Also applies to: 1346-1347, 1396-1397, 1532-1533, 1653-1658


1310-1321: Deferring _applyConnectOptions is fine; be aware of “connected vs. configured” window

Moving _applyConnectOptions() to a fire‑and‑forget call with catchError inside onRtcManagerCreatedCallback means:

  • session.start()/join can now complete before camera/mic/screen‑share and audio device preferences have been fully applied.
  • Failures to apply those preferences are logged but no longer fail the join.

This is a good trade‑off for join latency, but it does introduce a brief window where the call is “connected” while local media configuration is still catching up. If that’s acceptable UX‑wise, you’re good; otherwise you might want to:

  • clearly document that connectOptions are applied asynchronously after join, and/or
  • gate specific UI transitions on lightweight signals that media setup has finished.
📜 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 1b3dfc6 and 73ecd57.

📒 Files selected for processing (6)
  • packages/stream_video/CHANGELOG.md (1 hunks)
  • packages/stream_video/lib/globals.dart (2 hunks)
  • packages/stream_video/lib/src/call/call.dart (7 hunks)
  • packages/stream_video/lib/src/call/session/call_session.dart (4 hunks)
  • packages/stream_video/lib/src/stream_video.dart (4 hunks)
  • packages/stream_video/lib/src/webrtc/rtc_manager.dart (2 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
  • GitHub Check: stream_video_push_notification
  • GitHub Check: stream_video_noise_cancellation
  • GitHub Check: stream_video_flutter
  • GitHub Check: iOS Build (Dogfooding)
🔇 Additional comments (3)
packages/stream_video/CHANGELOG.md (1)

1-6: Changelog entry matches implementation

The performance note correctly reflects the async deferrals and SDP caching added in this PR. No issues from a code/API perspective.

packages/stream_video/lib/src/stream_video.dart (2)

11-14: LGTM!

The new imports are correctly added to support the expanded client details collection and SDP caching functionality.

Also applies to: 66-66


1266-1356: LGTM!

The refactored _setClientDetails() comprehensively collects platform-specific device information and constructs the ClientDetails protobuf model correctly. The centralized approach (moving this from CallSession to a global variable) is a sound optimization for join call time.

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 (1)
packages/stream_video/lib/src/stream_video.dart (1)

1358-1365: Add defensive checks for version string parsing.

The version parsing still assumes exactly 3 dot-separated parts. If streamVideoVersion has a format like "1.0" or includes build metadata like "1.0.0+1", skip(1).first will throw. Although the outer try-catch handles this, defensive parsing would prevent silent failures in client details initialization.

Apply this diff to add safe version parsing:

     final versionSplit = streamVideoVersion.split('.');
     clientDetails = sfu_models.ClientDetails(
       sdk: sfu_models.Sdk(
         type: sfu_models.SdkType.SDK_TYPE_FLUTTER,
-        major: versionSplit.first,
-        minor: versionSplit.skip(1).first,
-        patch: versionSplit.last,
+        major: versionSplit.isNotEmpty ? versionSplit[0] : '0',
+        minor: versionSplit.length > 1 ? versionSplit[1] : '0',
+        patch: versionSplit.length > 2 ? versionSplit[2] : '0',
       ),
📜 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 73ecd57 and de23531.

📒 Files selected for processing (5)
  • packages/stream_video/lib/src/call/call.dart (7 hunks)
  • packages/stream_video/lib/src/stream_video.dart (7 hunks)
  • packages/stream_video/test/src/call/call_allow_multiple_active_calls_test.dart (2 hunks)
  • packages/stream_video/test/src/call/call_apply_settings_test.dart (1 hunks)
  • packages/stream_video/test/src/core/client_state_test.dart (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • 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). (9)
  • GitHub Check: stream_video_push_notification
  • GitHub Check: stream_video
  • GitHub Check: stream_video_screen_sharing
  • GitHub Check: stream_video_flutter
  • GitHub Check: stream_video_noise_cancellation
  • GitHub Check: analyze
  • GitHub Check: build
  • GitHub Check: analyze_legacy_version
  • GitHub Check: iOS Build (Dogfooding)
🔇 Additional comments (5)
packages/stream_video/test/src/call/call_apply_settings_test.dart (1)

59-59: LGTM! Test appropriately disables SDP precaching.

The addition of precacheGenericSdps: false is appropriate for the test context, where performance optimizations are not needed and may add unnecessary complexity or timing issues.

packages/stream_video/test/src/call/call_allow_multiple_active_calls_test.dart (1)

81-81: LGTM! Consistent test configuration.

Both test groups appropriately disable SDP precaching for deterministic test behavior.

Also applies to: 209-209

packages/stream_video/test/src/core/client_state_test.dart (1)

66-66: LGTM! Test configuration aligned with other test files.

Disabling SDP precaching maintains consistency across the test suite.

Also applies to: 187-187

packages/stream_video/lib/src/stream_video.dart (2)

11-11: LGTM! Imports properly support new functionality.

The new imports for system_info2, protobuf models, and rtc_manager are appropriately added to support client details gathering and SDP precaching.

Also applies to: 14-14, 66-66


131-131: LGTM! Parameter properly added to API surface.

The precacheGenericSdps parameter is correctly threaded through the factory and private constructor with a sensible default value of true for production use.

Also applies to: 141-141, 154-154

@codecov
Copy link

codecov bot commented Dec 11, 2025

Codecov Report

❌ Patch coverage is 15.90909% with 74 lines in your changes missing coverage. Please review.
✅ Project coverage is 6.30%. Comparing base (1b3dfc6) to head (de23531).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
packages/stream_video/lib/src/stream_video.dart 7.27% 51 Missing ⚠️
packages/stream_video/lib/src/call/call.dart 41.66% 14 Missing ⚠️
...kages/stream_video/lib/src/webrtc/rtc_manager.dart 0.00% 9 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff          @@
##            main   #1126   +/-   ##
=====================================
  Coverage   6.29%   6.30%           
=====================================
  Files        593     593           
  Lines      40887   40894    +7     
=====================================
+ Hits        2574    2578    +4     
- Misses     38313   38316    +3     

☔ 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.

@Brazol Brazol merged commit 0126924 into main Dec 12, 2025
16 of 17 checks passed
@Brazol Brazol deleted the chore/improve-join-call-time branch December 12, 2025 13:22
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