Skip to content

Fix 288ms UI hang in video publishing flow #838

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

sampepose
Copy link

🔗 Issue Links

N/A - Performance improvement identified through profiling

🎯 Goal

Fix a 288ms UI hang that occurs when publishing video, caused by synchronous camera initialization blocking the main thread.

📝 Summary

  • Eliminated 288ms UI hang when enabling video by making camera startup asynchronous
  • Used Task.detached to move blocking RTCCameraVideoCapturer.startCapture() off the critical path
  • No functional changes - camera still initializes, just doesn't block UI
  • Faster video publishing - transceivers set up immediately while camera starts in parallel

🛠 Implementation

Instruments profiling revealed that RTCCameraVideoCapturer.startCapture() (Google's WebRTC code) was blocking the main thread for 288ms with a __psynch_cvwait during camera initialization.

Root cause: The video publishing flow was waiting synchronously for the camera to start before continuing with transceiver setup.

Screenshot 2025-06-06 at 12 08 03 PM

Solution: Wrap the startVideoCapturingSession() call in a Task.detached to allow camera initialization to happen in parallel while the rest of the publish flow continues immediately.

// Camera starts async, doesn't block publish flow
Task.detached { [weak self] in
    do {
        try await self?.startVideoCapturingSession()
    } catch {
        log.error("Failed to start camera: \(error)")
    }
}

This approach ensures the UI remains responsive while the camera hardware initializes in the background.

🎨 Showcase

Before After
288ms hang when enabling video 0ms - instant response
Publishing blocked by camera init Publishing proceeds immediately
UI freezes during camera startup Smooth 60fps maintained

🧪 Manual Testing Notes

  1. Join a call with video disabled
  2. Enable video during the call
  3. Verify no UI hang when toggling video on
  4. Confirm video appears once camera initializes (~300ms later)
  5. Test rapid video on/off toggling
  6. Verify camera position changes (front/back) remain smooth
  7. Check that video quality is unaffected

☑️ Contributor Checklist

@sampepose sampepose requested a review from a team as a code owner June 6, 2025 16:08
@sampepose sampepose force-pushed the video-init-blocking branch 2 times, most recently from a7848fc to 4d9dc5f Compare June 9, 2025 04:41
@sampepose sampepose force-pushed the video-init-blocking branch from 4d9dc5f to b980524 Compare June 9, 2025 05:07
@ipavlidakis
Copy link
Contributor

Hey @sampepose, thank you for this PR. We are currently in the process of resolving many performance issues (you can take see a sneak peek in the open PRs).

We are now in a state where we have resolved all the hungs and for that reason I'm not going to accept this PR.

I'm going to keep open though as I reminder to check again once the changes have been merged.

Thanks,
Ilias

@sampepose
Copy link
Author

Hey! I noticed #829 still has this bug. It's blocking MainActor in LocalAudioMediaAdapter.swift

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