2022 MediaRecorder for IOS
This is only a partial answer.
It only solves the issue of not being able to record the video and not the audio.
You will have to find another solution for the audio when merging it together with the video.
As of Safari 14.5 you can use MediaRecorder API.
Here is a working example using MediaRecorder and getUserMedia()
.
startIOSVideoRecording: function() {
console.log("setting up recorder");
let self = this;
this.data = [];
if (MediaRecorder.isTypeSupported('video/mp4')) {
// IOS does not support webm! So you have to use mp4.
var options = {mimeType: 'video/mp4', videoBitsPerSecond : 1000000};
} else {
// video/webm is recommended for non IOS devices
console.error("ERROR: Is this really an IOS device??");
var options = {mimeType: 'video/webm'};
}
// this has to be a canvas element (not video!)
let stream = document.getElementById('self-canvas').captureStream(15);
this.recorder = new MediaRecorder(stream, options);
this.recorder.ondataavailable = function(evt) {
if (evt.data && evt.data.size > 0) {
self.data.push(evt.data);
console.log('chunk size: ' + evt.data.size);
}
}
this.recorder.onstop = function(evt) {
console.log('recorder stopping');
var blob = new Blob(self.data, {type: "video/mp4"});
// do something with the blob
}
this.recorder.start(1000);
looper();
},
Keep in mind that IOS still does not support video.captureStream()
or video/webm
at all, so you will need to set up a video element to connect the navigator.mediaDevices.getUserMedia()
and a canvas element for the MediaRecorder.
Also (on IOS) you can only declare one and only one getUserMedia()
stream at a time! So it is best to make the video element or the stream global with this.video
or this.localStream
in case other elements want to access the stream.
this.localStream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {width: 430, height: 430, facingMode: "user"}
});
let self = this;
self.video = document.createElement('video');
self.video.srcObject = this.localStream;
const canvas = document.getElementById("self-canvas");
const ctx = canvas.getContext('2d');
function draw_2DCanvas(){
ctx.clearRect(0,0, canvas.width, canvas.height);
ctx.drawImage(self.video, 0, 0, 430, 430);
}
requestAnimationFrame(draw_2DCanvas);
}
draw_2DCanvas();
On any other device you can just use video.captureStream()
without having to go though the pain of setting up a canvas element.
Also video/webm
is recommended in general.
Important Note
If you do not plan to edit the video in any way, directly passing the localStream
to the MediaRecorder will also work, and it will also allow you to record the user's audio.
this.recorder = new MediaRecorder(this.localStream, options);