Reputation: 344
I want to record video from smartphone cam by using the WebRTC and the script of github.io (demo: https://webrtc.github.io/samples/src/content/getusermedia/record/). But the demo link just doesn't work on iPhone Safari.
I tried also the source script here
Here is the original code of the record demo:
'use strict';
/* globals MediaRecorder */
const mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', handleSourceOpen, false);
let mediaRecorder;
let recordedBlobs;
let sourceBuffer;
const errorMsgElement = document.querySelector('span#errorMsg');
const recordedVideo = document.querySelector('video#recorded');
const recordButton = document.querySelector('button#record');
recordButton.addEventListener('click', () => {
if (recordButton.textContent === 'Start Recording') {
startRecording();
} else {
stopRecording();
recordButton.textContent = 'Start Recording';
playButton.disabled = false;
downloadButton.disabled = false;
}
});
const playButton = document.querySelector('button#play');
playButton.addEventListener('click', () => {
const superBuffer = new Blob(recordedBlobs, {type: 'video/webm'});
recordedVideo.src = null;
recordedVideo.srcObject = null;
recordedVideo.src = window.URL.createObjectURL(superBuffer);
recordedVideo.controls = true;
recordedVideo.play();
});
const downloadButton = document.querySelector('button#download');
downloadButton.addEventListener('click', () => {
const blob = new Blob(recordedBlobs, {type: 'video/webm'});
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'test.webm';
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 100);
});
function handleSourceOpen(event) {
console.log('MediaSource opened');
sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp8"');
console.log('Source buffer: ', sourceBuffer);
}
function handleDataAvailable(event) {
if (event.data && event.data.size > 0) {
recordedBlobs.push(event.data);
}
}
function startRecording() {
recordedBlobs = [];
let options = {mimeType: 'video/webm;codecs=vp9'};
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = {mimeType: 'video/webm;codecs=vp8'};
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = {mimeType: 'video/webm'};
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
console.error(`${options.mimeType} is not Supported`);
errorMsgElement.innerHTML = `${options.mimeType} is not Supported`;
options = {mimeType: ''};
}
}
}
try {
mediaRecorder = new MediaRecorder(window.stream, options);
} catch (e) {
console.error('Exception while creating MediaRecorder:', e);
errorMsgElement.innerHTML = `Exception while creating MediaRecorder: ${JSON.stringify(e)}`;
return;
}
console.log('Created MediaRecorder', mediaRecorder, 'with options', options);
recordButton.textContent = 'Stop Recording';
playButton.disabled = true;
downloadButton.disabled = true;
mediaRecorder.onstop = (event) => {
console.log('Recorder stopped: ', event);
};
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start(10); // collect 10ms of data
console.log('MediaRecorder started', mediaRecorder);
}
function stopRecording() {
mediaRecorder.stop();
console.log('Recorded Blobs: ', recordedBlobs);
}
function handleSuccess(stream) {
recordButton.disabled = false;
console.log('getUserMedia() got stream:', stream);
window.stream = stream;
const gumVideo = document.querySelector('video#gum');
gumVideo.srcObject = stream;
}
async function init(constraints) {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
handleSuccess(stream);
} catch (e) {
console.error('navigator.getUserMedia error:', e);
errorMsgElement.innerHTML = `navigator.getUserMedia error:${e.toString()}`;
}
}
document.querySelector('button#start').addEventListener('click', async () => {
const hasEchoCancellation = document.querySelector('#echoCancellation').checked;
const constraints = {
audio: {
echoCancellation: {exact: hasEchoCancellation}
},
video: {
width: 1280, height: 720
}
};
console.log('Using media constraints:', constraints);
await init(constraints);
});
I also tested the script in fiddle on different smartphones. It only doesn't work on the iPhone apparently.
Upvotes: 4
Views: 6656
Reputation: 546
I know this might not be answering OP's question, but I spent many days working on this problem until I discovered it was futile. Then I resorted to this solution as substitute.
<input type="file" accept="video/*" capture="user" />
Instead of recording in the browser directly (like you can on android and desktops) you can record directly to the phone on ios. And then immediately have it uploaded to the browser as if it was. Also don't forget to grab the data from onChange and depending on how you want to use it, you can change it to a dataURL as well.
Upvotes: 0
Reputation: 3058
Check this out: https://en.wikipedia.org/wiki/WebM WebM video working on safari too.
There are 2 ways -
Solution #1 (NOT GUARANTEED) :
new Blob(recordedBlobs, {'video/webm;codecs=vp8'});
Solution #2 (GUARANTEED) :
Record with video/webm;codecs=h264
, as MP4 and Webm supports h264 codec
.
check for available containers here -> video_codec_and_container
Now you just need to change the video container from WEBM
to MP4
.
Which is way easy using tool such as ffmpeg -
Note: copy the video codec, so that re-encoding will be avoided
ffmpeg -i INPUT.webm -codec:v copy OUTPUT.mp4
Recommendation: Convert videos to MP4
because WEBM
has support for limited browsers.
Upvotes: 3
Reputation: 21
Exactly, mediaSource isnt available on iOS Safari yet, although its in Experimental state. Check this thread for more info: https://bugs.webkit.org/show_bug.cgi?id=85851
Upvotes: 2