Search code examples
mobile-safariaudio-streamingweb-mediarecordervideo-conferencingwebrtc-ios

How to record mic WHILE video calling with Daily.co on iOS Safari


Problem

With my iPad's iOS Safari, I can use Daily.co's video API to call other devices. But the moment I start recording my local microphone via the audio-recorder-polyfill library , everybody else will no longer be able to hear me, even though I can still hear them and share my camera. Even when the recording session ends, the audio call remains broken (though the audio-recorder works successfully).

It seems iOS specific, because I have no problems with my Surface's Windows Chrome.

How to reproduce

Takes around 2 minutes

  1. Visit explain.mit.edu with iPad Safari and any other device. Press the green call button.
  2. After confirming the video call works, press the record button on iPad
  3. Note the other device can no longer hear anything

What I tried

First, I guessed the MediaRecorder invalidates the Daily video call's access to the mic, so I used setLocalDevice to re-designate access to Daily every 5 seconds to see what would happen. It made no difference during recording, but when the recording ended and it actually did restore the audio call.

So the remaining problem is that the audio call stream just doesn't work mid-recording: I read the MDN docs about the MediaCapture API, it mentioned that a stream has one input and one output, but I don't know what that really means, and whether a mic stream can be simultaneously accessed by two "things".

Relevant Code

I only use the basic minimum API that Daily and audio-recorder-polyfill provides

Video calling (full code here)

await this.CallObject.join({
  url: conferenceRoom.url,
  userName: this.sessionID
}); 

Audio recording (full code here)

const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
this.recorder = new MediaRecorder(stream); 
this.recorder.start(); 

I don't believe the issue is caused anywhere else, but here's the full repository code if needed

Real-world context For context, I work on https://explain.mit.edu. You go there, request help, then someone else will arrive and use the realtime blackboard and voice chat to explain something to you - and a KhanAcademy-video is made as a by-product. But now if anyone presses "record", the voice chat will stop working.


Solution

  • We can work on a repro case for this, but I have a guess as to what's going on. iOS Safari in the past has stopped any current tracks coming from the local mic/cam any time getUserMedia() is called. So, unlike on desktop browsers and Android Chrome, on iOS you can't request or use multiple streams.

    iOS Safari is a moving target, and I haven't looked at this specific issue lately. But if that is what's going on, probably you can work around it with a fairly small code change.

    Instead of:

    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    

    You can grab the local audio track from the Daily call object and make a stream from that:

    const track = this.callObject.participants().local.tracks.audio.persistentTrack
    if (!track) {
      throw new Error("can't start recording right now ... no audio track");
    }
    this.recorder = new MediaRecorder(new MediaStream([track]));
    this.recorder.start();