fix: acquire getUserMedia early in start() to prevent mobile gesture timeout#156
Closed
vapi-tasker[bot] wants to merge 1 commit intomainfrom
Closed
fix: acquire getUserMedia early in start() to prevent mobile gesture timeout#156vapi-tasker[bot] wants to merge 1 commit intomainfrom
vapi-tasker[bot] wants to merge 1 commit intomainfrom
Conversation
…timeout Mobile browsers enforce strict user gesture policies that only allow a short window (~1-5s) between a user tap and a getUserMedia() call. Previously, the SDK made an API call to create the web call BEFORE calling getUserMedia (via DailyIframe.createCallObject), causing NotAllowedError on mobile when the API call took too long. This fix calls getUserMedia() immediately when start() is invoked, within the user gesture window, before any async network calls. The pre-acquired audio track is then passed to DailyIframe.createCallObject. Also adds support for passing a pre-acquired MediaStream via the options.mediaStream parameter for callers who want even more control. VAP-12773
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.
Summary\n\nFixes the
NotAllowedErroron mobile browsers (iOS Safari, Chrome on Android) when callingvapi.start(). Mobile browsers enforce a strict "user gesture" policy that only allowsgetUserMedia()within ~1-5 seconds of a user tap. Previously, the SDK made a network API call to create the web call before invokinggetUserMedia()(viaDailyIframe.createCallObject), causing the gesture window to expire.\n\nRoot cause: In thestart()method,callControllerCreateWebCall(network request) ran first, andDailyIframe.createCallObject({ audioSource: true })ran second. On slow networks or under load, the API call consumed the gesture window, and Daily's internalgetUserMedia()call was rejected by the browser.\n\nFix: Callnavigator.mediaDevices.getUserMedia({ audio: true })immediately whenstart()is invoked (within the gesture window), then pass the pre-acquiredMediaStreamTracktoDailyIframe.createCallObject({ audioSource: track })so Daily does not callgetUserMedia()again.\n\n### Changes\n\n- Early media acquisition:getUserMedia()is called at the top ofstart(), before any network requests\n- Pre-acquired track passthrough: The track is passed asaudioSourcetoDailyIframe.createCallObject()\n- Graceful fallback: If earlygetUserMedia()fails, the SDK falls back to the original behavior (Daily handles it)\n- Track cleanup on error: Pre-acquired tracks are stopped if the call creation fails, freeing the microphone\n- User-provided MediaStream support: NewmediaStreamoption inStartCallOptionsallows callers to pass their own pre-acquiredMediaStream\n- Constructor track detection: IfaudioSourcein constructor options is already aMediaStreamTrack,getUserMedia()is skipped\n\n## Test Plan\n\n- [x] 7 new tests in__tests__/vapi-early-media.test.tscovering:\n -getUserMediais called before the API call (ordering verified via call tracking)\n - Pre-acquired audio track is passed toDailyIframe.createCallObject\n - Fallback works whengetUserMediafails (Permission denied)\n - Only audio is requested (not video)\n - Pre-acquired tracks are stopped on cleanup when call creation fails\n - User-providedMediaStreamis accepted and used (skipping internalgetUserMedia)\n - Constructor-providedMediaStreamTrackskipsgetUserMedia\n- [x] All 13 tests pass (6 existing + 7 new)\n- [x] TypeScript build passes (pre-existing type errors unrelated to this change)\n\n## Linear Issue\n\nResolves VAP-12773