MediaRecorder API

Safari Technology Preview 105 and Safari in the latest iOS 14.3 beta enabled support for the MediaRecorder API by default. This API takes as input live audio/video content to produce compressed media. While the immediate use case is to record from the camera and/or microphone, this API can take any MediaStreamTrack as input, be it a capture track, coming from the network using WebRTC, or generated from HTML (Canvas, WebAudio), as illustrated in the chart below.

The generated output, exposed as blobs, can be readily rendered in a video element to preview the content, edit it, and/or upload to servers for sharing with others.

This API can be feature-detected, as can the set of supported file/container formats and audio/video codecs. Safari currently supports the MP4 file format with H.264 as video codec and AAC as audio codec. MediaRecorder support can be checked as follows:

function supportsRecording(mimeType)
{
    if (!window.MediaRecorder)
        return false;
    if (!MediaRecorder.isTypeSupported)
        return mimeType.startsWith("audio/mp4") || mimeType.startsWith("video/mp4");
    return MediaRecorder.isTypeSupported(mimeType);
}

The following example shows how camera and microphone can be recorded as mp4 content and locally previewed on the same page.

<html>
<body>
<button onclick="startRecording()">start</button><br>
<button onclick="endRecording()">end</button>
<video id="video" autoplay playsInline muted></video>
<script>
let blobs = [];
let stream;
let mediaRecorder;
async function startRecording()
{
    stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
    mediaRecorder = new MediaRecorder(stream);
    mediaRecorder.ondataavailable = (event) => {
       // Let's append blobs for now, we could also upload them to the network.
       if (event.data)
            blobs.push(event.data);
    }
    mediaRecorder.onstop = doPreview;
    // Let's receive 1 second blobs
    mediaRecorder.start(1000);
}
function endRecording()
{
    // Let's stop capture and recording
    mediaRecorder.stop();
    stream.getTracks().forEach(track => track.stop());
}
function doPreview()
{
    if (!blobs.length)
        return;
    // Let's concatenate blobs to preview the recorded content
    video.src = URL.createObjectURL(new Blob(blobs, { type: mediaRecorder.mimeType }));
}
</script>
</body>
</html>

Future work may extend the support to additional codecs as well as supporting options like video/audio bitrates.

getUserMedia in WKWebView

Speaking of Safari in latest iOS 14.3 beta and local capture, navigator.mediaDevices.getUserMedia can now be exposed to WKWebView applications. navigator.mediaDevices.getUserMedia is automatically exposed if the embedding application is able to natively capture either audio or video. Please refer to Apple documentation to meet these requirements. Access to camera and microphone is gated by a user prompt similar to Safari and SafariViewController prompts. We hope to extend WKWebView APIs to allow applications to further control their camera and microphone management in future releases.

We hope you will like these new features. As always, please let us know if you encounter any bugs (or if you have ideas for future enhancements) by filing bugs on bugs.webkit.org.