Is it possible to figure out whether a user has a webcam or not using only JavaScript? I don't want to use any plugin for this.
You don't necessarily need to get the permission to know if the user has a webcam, you can check it with enumerateDevices:
function detectWebcam(callback) {
let md = navigator.mediaDevices;
if (!md || !md.enumerateDevices) return callback(false);
md.enumerateDevices().then(devices => {
callback(devices.some(device => 'videoinput' === device.kind));
})
}
detectWebcam(function(hasWebcam) {
console.log('Webcam: ' + (hasWebcam ? 'yes' : 'no'));
})
You can use a new HTML5 API to check if they give you permission to use the webcam. After all, if they deny permission, they might as well not have a webcam, from the code's perspective.
See navigator.getUserMedia().
EDIT:
navigator.getMedia = ( navigator.getUserMedia || // use the proper vendor prefix
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
navigator.getMedia({video: true}, function() {
// webcam is available
}, function() {
// webcam is not available
});
You can check if the user has a webcam using this plugin: http://www.xarg.org/project/jquery-webcam-plugin/
if(webcam.getCameraList().length == 0){
alert('You don\'t have a web camera');
}
Taken from here: How can I check if user has a webcam or not?
Edit: I see you updated your question to say that you don't want to use a plugin. In this case, you could try using the getUserMedia API:
function success(stream){
// The success function receives an argument which points to the webcam stream
document.getElementById('myVideo').src = stream;
}
function error(){
alert("No webcam for you, matey!");
}
if (navigator.getUserMedia) {
navigator.getUserMedia({video:true, audio:false}, success, error);
} else {
error();
}
Source: http://www.iandevlin.com/blog/2012/06/html5/filtering-a-webcam-using-getusermedia-and-html5-canvas
There is NO way you can read current browser settings.
the only thing we can do is try to access the webcam/microphone and see if we are able to access that device like...
navigator.getMedia({video: true}, function() {
// webcam is available
}, function() {
// webcam is not available
});
BUT **** One important thing to note here, if you follow this approach then be aware that ....
Also please note that, you have to use HTTPS to use webcam/microphone and it will prompt you the browser specific permission popup with allow and block buttons ONLY ONCE, you will NOT see this permission popup again as HTTPS save the permission.
The only way to get this permission popup again is to:
Clear your cache and
Reset the browser settings
Open a new instance of the browser.
FYI ... You cannot manipulate browser specific setting using JavaScript
So don't event go that way, unless you have time to kill
Navigator.getUserMedia() is being depreciated as of 2019. To access webcam, use MediaDevices.getUserMedia() instead.
Note that navigator.mediaDevices will return undefined if the current document isn't loaded securely. URLs served from localhost are usually OK.
Sample code to test for and access webcam:
const constraints = {
audio: false,
video: { width: 1280, height: 720 },
};
if (!navigator.mediaDevices) {
console.log("Document not secure. Unable to capture WebCam.");
} else {
navigator.mediaDevices
.getUserMedia(constraints)
.then(function(stream) {
//show webcam stream
let videoIn = document.createElement("video");
videoIn.autoplay = true;
document.body.appendChild(videoIn);
videoIn.srcObject = stream;
})
.catch(function(err) {
console.log("Unable to capture WebCam.", err);
});
}
While here, and inspired by other answers, as part of an implementation I'm working on I am using the following function to return a boolean checking for an active stream.
The project is a little old, hence jQuery and ES5, though hope this can prove useful to someone:
function() {
var deferred = $.Deferred();
navigator.mediaDevices.getUserMedia(VIDEO_CONSTRAINTS)
.then(function(stream) { deferred.resolve(stream.active); })
.catch(function() { deferred.resolve(false) })
return deferred.promise()
}
This can then be used as follows:
checkStreamActive()
.then(function(activeStream) {
if(activeStream) {
// do something
} else {
// do something else
}
})
async function detectWebcam() {
try {
var md = navigator.mediaDevices;
var results = false;
if (!md || !md.enumerateDevices) results = false;
const devices = await md.enumerateDevices();
results = devices.some(device => 'videoinput' === device.kind);
return results;
} catch (error) { return false; }
}
strong textTry this code to check whether the device has webcam or not by javascript alertcheck this image
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
webcam_check_func();
});
function webcam_check_func() {
var hasWebcam = false;
var device = [];
if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
navigator.enumerateDevices = function (callback) {
navigator.mediaDevices.enumerateDevices().then(callback);
};
navigator.enumerateDevices(function (devices) {
devices.forEach(function (my_device) {
if (my_device.kind === 'videoinput') {
debugger;
hasWebcam = true;
}
}
);
alert("Has Web Camera -->" + hasWebcam);
});
}
}
</script>
</head>
<body>
</body>
</html>
Related
How can I catch with serviceworker or simple js code, when user who previously allowed the web push notifications for my site disable them? For Firefox and Chrome browsers.
You can use the Permissions API to detect the current state of given permissions, as well as listen for changes.
This article has more detail. Here's a relevant code snippet:
navigator.permissions.query({name: 'push'}).then(function(status) {
// Initial permission status is `status.state`
status.onchange = function() {
// Status changed to `this.state`
};
});
You can try this:
navigator.permissions.query({name:'notifications'}).then(function(status) {
//alert(status.state); // status.state == { "prompt", "granted", "denied" }
status.onchange = function() {
if(this.state=="denied" || this.state=="prompt"){ push_unsubscribe(); }
};
});
or this:
navigator.permissions.query({name:'push', userVisibleOnly:true}).then(function(status) {
//alert(status.state); // status.state == { "prompt", "granted", "denied" }
status.onchange = function() {
if(this.state=="denied" || this.state=="prompt"){ push_unsubscribe(); }
};
});
I use it to send information to the server that the user has canceled or disabled notifications. Note that the code is not executed if the user does so in the site settings.
I am trying to use LinkedIn Javascript SDK to retrieve some information including positions fields. I copied the code from the internet but it seems something is not working quite right because the code i copied doesn't return positions fields as supposed to be. I tried on ApiGee it worked fine and it returned the list of positions as i am expected. If you look at the code below , do you think i missed something or the javascript SDK itself has some buggy problems ?
<script type="text/javascript" src="//platform.linkedin.com/in.js">
api_key: yourapikey
authorize: true
onLoad: onLoad
</script>
<script type="text/javascript">
function onLoad() {
IN.Event.on(IN, "auth", getProfileData);
}
// Handle the successful return from the API call
function onSuccess(data) {
alert(JSON.stringify(data));
}
// Handle an error response from the API call
function onError(error) {
console.log(error);
}
// Use the API call wrapper to share content on LinkedIn
function getProfileData() {
//alert(IN.ENV.auth.oauth_token);
IN.API.Raw("/people/~:(id,positions)?format=json").result(onSuccess).error(onError);
}
</script>
Return result is showing this :
{"id":"wQplQQjzLa","positions":{"_total":0}}
Hello there #John Hadikusumo,
Well, I do understand that this reply would be happening only a year later but, I too was facing some problems with the linkedin api integration especially when it came to the "positions" object values.
Apparently when I got an error, what it meant was that the user who is using his linkedin profile to authorize, that particular user has not initiated his experience details and thus has no value;
To circumvent this particular problem here is what I had done which had helped me:
function onLinkedInLoad() {
IN.Event.on(IN, "auth", getProfileData);
}
function onSuccess(data) {
console.log(data);
}
function onError(error) {
console.log(error);
}
function getProfileData(){
IN.API.Profile("me").fields(["firstName","lastName", "email-address", "positions"]).result(function(data) {
var profileData = data.values[0];
var profileFName = profileData.firstName;
var profileLName = profileData.lastName;
//this is the piece of code that helped me out;
//might work for you as well;
if(data.values[0].positions._total == "0" || data.values[0].positions._total == 0 || data.values[0].positions._total == undefined) {
console.log("Error on position details");
var profileCName = "Details Are Undefined";
}
else {
var profileCName = profileData.positions.values["0"].company.name;
}
var profileEName = profileData.emailAddress;
//and other logic/code continues...
});
}
So I do hope this helps you out. Do let me know if you had faced any other errors, I could use some help in case I would need to improve my existing code.
Cheers and Have a nice day.
I would like to find out if the user's device has an attached camera and microphone, and if so, has permissions been granted to get the audio and video stream using Javascript. I want to make this check to be made across Chrome and Firefox at the very least. What's a consistent API for this?
Live Demo:
https://www.webrtc-experiment.com/DetectRTC/
If user didn't allow webcam and/or microphone, then media-devices will be having "NULL" value for the "label" attribute. Above page will show this message: "Please invoke getUserMedia once."
PS. You can type "DetectRTC.MediaDevices" in the Chrome Console developers tool.
Note: It works only in Chrome. Firefox isn't supporting similar API yet. (Updated: Firefox supports as well)
Updated at Dec 16, 2015
Note: Following code snippet works both in Chrome and Firefox.
if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
// Firefox 38+ seems having support of enumerateDevicesx
navigator.enumerateDevices = function(callback) {
navigator.mediaDevices.enumerateDevices().then(callback);
};
}
var MediaDevices = [];
var isHTTPs = location.protocol === 'https:';
var canEnumerate = false;
if (typeof MediaStreamTrack !== 'undefined' && 'getSources' in MediaStreamTrack) {
canEnumerate = true;
} else if (navigator.mediaDevices && !!navigator.mediaDevices.enumerateDevices) {
canEnumerate = true;
}
var hasMicrophone = false;
var hasSpeakers = false;
var hasWebcam = false;
var isMicrophoneAlreadyCaptured = false;
var isWebcamAlreadyCaptured = false;
function checkDeviceSupport(callback) {
if (!canEnumerate) {
return;
}
if (!navigator.enumerateDevices && window.MediaStreamTrack && window.MediaStreamTrack.getSources) {
navigator.enumerateDevices = window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack);
}
if (!navigator.enumerateDevices && navigator.enumerateDevices) {
navigator.enumerateDevices = navigator.enumerateDevices.bind(navigator);
}
if (!navigator.enumerateDevices) {
if (callback) {
callback();
}
return;
}
MediaDevices = [];
navigator.enumerateDevices(function(devices) {
devices.forEach(function(_device) {
var device = {};
for (var d in _device) {
device[d] = _device[d];
}
if (device.kind === 'audio') {
device.kind = 'audioinput';
}
if (device.kind === 'video') {
device.kind = 'videoinput';
}
var skip;
MediaDevices.forEach(function(d) {
if (d.id === device.id && d.kind === device.kind) {
skip = true;
}
});
if (skip) {
return;
}
if (!device.deviceId) {
device.deviceId = device.id;
}
if (!device.id) {
device.id = device.deviceId;
}
if (!device.label) {
device.label = 'Please invoke getUserMedia once.';
if (!isHTTPs) {
device.label = 'HTTPs is required to get label of this ' + device.kind + ' device.';
}
} else {
if (device.kind === 'videoinput' && !isWebcamAlreadyCaptured) {
isWebcamAlreadyCaptured = true;
}
if (device.kind === 'audioinput' && !isMicrophoneAlreadyCaptured) {
isMicrophoneAlreadyCaptured = true;
}
}
if (device.kind === 'audioinput') {
hasMicrophone = true;
}
if (device.kind === 'audiooutput') {
hasSpeakers = true;
}
if (device.kind === 'videoinput') {
hasWebcam = true;
}
// there is no 'videoouput' in the spec.
MediaDevices.push(device);
});
if (callback) {
callback();
}
});
}
// check for microphone/camera support!
checkDeviceSupport(function() {
document.write('hasWebCam: ', hasWebcam, '<br>');
document.write('hasMicrophone: ', hasMicrophone, '<br>');
document.write('isMicrophoneAlreadyCaptured: ', isMicrophoneAlreadyCaptured, '<br>');
document.write('isWebcamAlreadyCaptured: ', isWebcamAlreadyCaptured, '<br>');
});
Now you can use navigator.permissions also to check permissions already exist
navigator.permissions.query({ name: "camera" }).then(res => {
if(res.state == "granted"){
// has permission
}
});
See MDN for more info.
But note that support is patchy as of Jan 2021:
Chrome supports navigator.permissions.query as of Chrome 43+, and supports querying camera and microphone permissions, at least as of Chrome 87+.
Firefox supports navigator.permissions.query as of Firefox 46+, but does not support querying camera or microphone permissions as of Firefox 84.
Safari does not even support navigator.permissions.query.
Yes it is quite possible to detect whether a microphone and a camera is available after granting the permission.
Using the old API:
navigator.getUserMedia({ audio: true, video: true}, function (stream) {
if (stream.getVideoTracks().length > 0 && stream.getAudioTracks().length > 0) {
//code for when none of the devices are available
} else {
// code for when both devices are available
}
}, function (error) {
// code for when there is an error
});
Using the newer, promise-based API:
navigator.mediaDevices.getUserMedia({ audio: true, video: true})
.then(function (stream) {
if (stream.getVideoTracks().length > 0 && stream.getAudioTracks().length > 0){
//code for when none of the devices are available
} else {
// code for when both devices are available
}
})
.catch(function (error) {
// code for when there is an error
});
1)You should be using Media Recorder and understand promise
2)Check if browser support the API enumerateDevices
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
console.log("This browser does not support the API yet");
}
3) Check if user has conected audio and camera, the only values are "videoinput", "audioinput" or "audiooutput" DeviceInfo.kind
let checking=["audioinput","videoinput"];
let onlyHas=[];
navigator.mediaDevices.enumerateDevices()
.then((devices)=> {
let haveAllDevices=true;
devices.forEach((device)=>{
onlyHas.push(device.kind);
if(!(device.kind==checking[0] || device.kind==checking[1])){
haveAllDevices=false;
}
});
//do something about ...
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
});
4)Permissions are reused,it means that if user already has denied permission then when you call getUserMedia the bowser won't prompt anything and will reject the promise promise throwing an error of type DOMException, otherwise it will resolve the promise.
When the promise rejects it can be many reasons read, one of then is when user has denied access, when this happens it will throw an DOMException of type NotAllowedError, so for now we are only interested in this error.
If you read DOMException you can see you can acces DOMException.name, this is the one that you should be compared, so:
let constraints={audio:true,video:true};
navigator.mediaDevices.getUserMedia(constraints)
.then((stream)=>{.....})
.catch((err)=>
{if(err.name=="NotAllowedError"){console.log("User has denied accessed")}
});
PS: About cross browser compatibility MediaRecorder as for today 09/06/2018 it is only supported in chrome and firefox, and the brothers IE and IOS don't
https://caniuse.com/#search=MediaRecorder
This function checks if the user have audio and video access:
checkMediaAccess = async() => {
navigator.mediaDevices.enumerateDevices().then( devices =>
devices.forEach( device => {
if(device.kind == 'audioinput' && device.label) console.log('Has Audio Access');
if(device.kind == 'videoinput' && device.label) console.log('Has Video Access');
}
));
}
You can use the MediaStreamTrack which represent a media stream, then you can use its getSources method as explained here: html5rocks
If you don't get any media sources then your client hasn't a webcam.
It's not supported by firefox.
Please try my simple cross browser code.
Attention!!! Use https protocol for open web page with my code! Please go to demo
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h1>Web camera</h1>
<video autoplay></video>
<script>
function errorMessage(message, e) {
console.error(message, typeof e == 'undefined' ? '' : e);
//alert(message);
}
if (location.protocol === 'https:') {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia({ audio: true, video: true }, function (stream) {
document.querySelector('video').src = window.URL.createObjectURL(stream);
var mediaStreamTrack = stream.getVideoTracks()[0];
if (typeof mediaStreamTrack != "undefined") {
mediaStreamTrack.onended = function () {//for Chrome.
errorMessage('Your webcam is busy!')
}
} else errorMessage('Permission denied!');
}, function (e) {
var message;
switch (e.name) {
case 'NotFoundError':
case 'DevicesNotFoundError':
message = 'Please setup your webcam first.';
break;
case 'SourceUnavailableError':
message = 'Your webcam is busy';
break;
case 'PermissionDeniedError':
case 'SecurityError':
message = 'Permission denied!';
break;
default: errorMessage('Reeeejected!', e);
return;
}
errorMessage(message);
});
} else errorMessage('Uncompatible browser!');
} else errorMessage('Use https protocol for open this page.')
</script>
</body>
</html>
I have tested it into follow browsers:
Windows 10
Chrome 52
Edge 25
Firefox 47
IE11 Uncompatible browser!
Opera 39
Safari 5 Uncompatible browser!
Android
Chrome 52
Firefox 48
Opera 37
I have an issue with capturing a newly created tab in chrome.
I create the new tab with chrome.tabs.create and pass the tabid to my callback function which captures it.
function createtab(url) {
chrome.tabs.create({'url': url,'active':false}, function(tab) {
captureWindowTab((tab.id);
});
}
function captureWindowTab(tabid) {
chrome.tabs.update(tabid, {}, function() {
chrome.tabs.captureVisibleTab(27, {format:"png"}, function(dataUrl) {
capturecallback(dataUrl);
});
});
}
function capturecallback(dataurl) {
console.log(dataurl);
}
It works ONLY when i do it on current existing tabs. i cannot get it to work on newly created tabs. always returns undefined.
I dont understand whats the issue.
Based on the documentation it seems you need the host permission (or all hosts permission) to be able to capture it. See the docuemtation at:
https://developer.chrome.com/extensions/tabs.html#method-captureVisibleTab
Do you have the host permission or all hosts permission set?
I think you might also need the "tabs" permission, if you don't already have it.
Resolved it like this:
chrome.tabs.onUpdated.addListener(function(tabid , info) {
//console.log('loading tab'+tabid);
if(info.status == "complete") {
chrome.tabs.get(tabid,function(tab) {
chrome.topSites.get(function(sites){
tab.url = NewTab.getHostFromUrl(tab.url);
console.log(tab.url);
//console.log('loaded '+tab.url);
for (var i = 8 - 1; i >= 0; i--) {
sites[i].url = NewTab.getHostFromUrl(sites[i].url);
//console.log('checking '+sites[i].url);
if(tab.url == sites[i].url && tab.url != 'newtab') {
chrome.tabs.update(tabid, {'highlighted':true,'active':true}, function(tab){
chrome.tabs.captureVisibleTab(chrome.windows.WINDOW_ID_CURRENT, {format:"jpeg","quality":30}, function(dataUrl) {
// add data URL to array
if(dataUrl) {
console.log('its a winner!');
window.localStorage['topsite_'+encodeURI(NewTab.getHostFromUrl(tab.url))+'_thumbnail'] = dataUrl;
NewTab.getTopSites();
}
});
});
}
};
});
});
}
});
I try setup a JS function to auto load a index page in a different language, regardig the setting device o my reader.
I try with this...but don't work :
<script src="cordova-2.2.0.js"></script>
<script type="text/javascript" charset="utf-8">
function checkLanguage() {
if (navigator.globalization.getPreferredLanguage()='en_EN')
{
window.location.replace("index_en.html");
}
else if (navigator.globalization.getPreferredLanguage()='fr_FR')
{
window.location.replace("index_fr.html");
}
else
{
window.location.replace("index_other.html");
}
}
</script>
Is this method can be use, or do I have to consider other option to deal with my multilanguage app ?
Thanks in advance for any help.
You need to use the callback of getPreferredLanguage:
var handleDeviceReady = function (event)
{
navigator.globalization.getPreferredLanguage(
function (language)
{
console.log("language: " + language.value + '\n');
redirectToLocaleSpecificLogin(language.value);
},
function ()
{
console.log("Error getting language\n");
redirectToLocaleSpecificLogin("en");
}
);
};
document.addEventListener("deviceready", handleDeviceReady, false);
Then inside of your callback (redirectToLocaleSpecificLogin in this case), you can do your redirects.
most of the browsers use language property, IE uses userLanguage
var lang = window.navigator.userLanguage || window.navigator.language;
this should work in IE, SAFARI, CHROME and FF
Edit:
JavaScript for detecting browser language preference this link has more detailed discussion on this topic