Reputation: 81
I have a plugin where in I capture Image using Web camera present on the laptop or mobile and then place it in the canvas. All this works well in Chrome but when using Firefox , it simply doesn't work. I suspect its the navigator.getUserMedia which is causing the problem in firefox as it is deprecated.
link : https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getUserMedia
And Google developer suggests the use of navigator.getUserMedia and it is also compatible with my app.
link: https://developers.google.com/web/updates/2015/10/media-devices
So please do suggest what changes should be done in the below code for it to work in firefox.
Thanks in Advance.
<script type="text/javascript">
var ctx = null;
var canvas = document.getElementById("tmpImage");
var localMediaStream = null;
var video = document.querySelector('video');
function snapshot() {
if (localMediaStream) {
ctx.drawImage(video, 0, 0);
var img = document.getElementById('CaptureImage');
// "image/webp" works in Chrome 18. In other browsers, this will fall back to image/png.
img.src = canvas.toDataURL('image/webp');
}
}
function hasGetUserMedia() {
// Note: Opera builds are unprefixed.
return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia || navigator.msGetUserMedia);
}
function onFailSoHard(e) {
if (e.code == 1) {
alert('User denied access to their camera');
} else {
alert('getUserMedia() not supported in your browser.');
}
}
function start() {
if (hasGetUserMedia()) {
if (navigator.webkitGetUserMedia)
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
//var getUserMedia = navigator.webkitGetUserMedia || navigator.getUserMedia;
//var gumOptions = { video: true, toString: function () { return 'video'; } };
if (navigator.getUserMedia) {
navigator.getUserMedia({
video: true,
audio: false
}, function (stream) {
if (navigator.webkitGetUserMedia) {
video.src = window.webkitURL.createObjectURL(stream);
} else {
video.src = stream; // Opera
}
localMediaStream = stream;
}, onFailSoHard);
} else {
video.src = 'somevideo.webm'; // fallback.
}
}
}
function stop() {
video.pause();
video = document.getElementById('sourcevid');
video.src = "";
localMediaStream.stop();
}
function ResizeCanvas() {
canvas.height = video.videoHeight;
canvas.width = video.videoWidth;
}
$(document).ready(function () {
ctx = canvas.getContext('2d');
});
Upvotes: 1
Views: 1599
Reputation: 42530
Use the official adapter.js polyfill. Problem solved.
E.g. this fiddle works in all supported browsers.
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => video.srcObject = stream)
.catch(e => console.error(e));
Supports modern constraints syntax as well.
Upvotes: 2
Reputation: 137171
Yes, getUserMedia
API is evolving.
The new syntax is navigator.mediaDevices.getUserMedia
.
Edge and Firefox, already implement this new syntax, that will return a Promise, forcing us to rewrite our codes...
Chrome is really late about it and even still uses some never standardized video constraint syntax.
The process now becomes a bit complicated but there are some libraries that handle these cases.
I've also written my own implementation that should handle most GUM enabled browsers :
I'm not sure Chrome does allow getUserMedia from stack snippets so here is a jsfiddle
var video,canvas,ctx;
var settings = {
video_constraints: {
width: {
min: 1200,
max: 1920
},
height: {
min: 720,
max: 1080
},
require: ["width", "height"],
facingMode: "user",
},
audio: false,
}
function getStream(video) {
video.streaming = false;
if (navigator.webkitGetUserMedia)
setWebkitConstraints();
navigator.getUserMedia = navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
if (!navigator.getUserMedia && !navigator.mediaDevices) {
alert('GUM is not supported by this browser');
return false;
}
var opts = {
video: settings.video_constraints,
audio: settings.audio
};
var then = function(stream) {
if (navigator.mozGetUserMedia)
video.mozSrcObject = stream;
else {
var URL = window.URL || window.webkitURL;
video.src = URL.createObjectURL(stream);
}
video.play();
loopStart(video);
};
var error = function(err) {
console.log("An error occured! ", err)
if (err.name.indexOf('Permission') == 0) return;
};
if (navigator.mediaDevices) {
navigator.mediaDevices.getUserMedia(opts).then(then, error).catch(error);
} else {
navigator.getUserMedia(opts, then, error);
}
};
// handle webkit old and deprecated constraint syntax
var setWebkitConstraints = function() {
var wkConstraints = {
mandatory: {}
};
var c = settings.video_constraints;
for (var i in c) {
switch (i) {
case 'width':
for (j in c[i]) {
switch (j) {
case 'max':
wkConstraints.mandatory.maxWidth = c[i][j];
break;
case 'min':
wkConstraints.mandatory.minWidth = c[i][j];
break;
case 'exact':
wkConstraints.mandatory.minWidth = wkConstraints.mandatory.maxWidth = c[i][j];
break;
}
};
break;
case 'height':
for (var j in c[i]) {
switch (j) {
case 'max':
wkConstraints.mandatory.maxHeight = c[i][j];
break;
case 'min':
wkConstraints.mandatory.minHeight = c[i][j];
break;
case 'exact':
wkConstraints.mandatory.minHeight = wkConstraints.mandatory.maxHeight = c[i][j];
break;
}
};
break;
default:
break;
}
}
settings.video_constraints = wkConstraints;
};
var loopStart= function(video){
if (!video.streaming) {
if(video.videoHeight === 0){
window.setTimeout(function() {
video.pause();
video.play();
loopStart(video);
}, 100);
}
else {
video.streaming = true;
video.dispatchEvent(new Event('streaming'));
}
}else{return;}
};
(function init(){
video = document.createElement('video');
canvas = document.createElement('canvas');
document.body.appendChild(canvas);
ctx = canvas.getContext('2d');
video.addEventListener('streaming', copy2canvas, false);
getStream(video);
})()
function copy2canvas(){
console.log('succesfully streaming');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
draw();
}
function draw(){
ctx.drawImage(video, 0,0);
requestAnimationFrame(draw);
}
canvas{border: 1px solid red}
Upvotes: 0