I am trying to give my browser access to my devices camera, so that I can feed the media stream into a video, but when I am testing on google chrome getUserMedia is not supported, but when I use safari I am having no issues.
Does google chrome not have any support for getUserMedia anymore?
I have already read this article, but have had no luck.
This is the implementation I am currently using:
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
let constraints = {
audio: false,
video: { facingMode: "user" }
}
if (navigator.getUserMedia) {
navigator.getUserMedia(constraints,
function(stream) {
var video = document.querySelector('video');
video.srcObject = stream;
video.onloadedmetadata = function(e) {
video.play();
};
},
function(err) {
alert("The following error occured: " + err.name);
}
);
} else {
console.log("getUserMedia not supported");
}
Having the same troubles on iOS 11.2x. My researches showed that FF and Chrome are supported on OS but NOT on iOS even they would be able to support media devices. You can test easy mediaDevice availability:
if (navigator.mediaDevices) {
alert ("Media device supported");
}
else {
alert ("Media device not supported");
}
You can check that here too: HTML5Test
FF and Chrome on iOS will show "Media device not supported" while Safari says its supported. The reason looks like Apple has still not given free the access to other browsers using mediaDevices.You can imagine some reasons why that is. ;/ So don't blame Chrome or Firefox this time.
Would be interesting to know if it now works in iOS 12.
This works with FF and Chrome on desktop and phone. Note: width and height are reversed on desktop and phone. Note: FF and Chrome allow it to run on localhost and https. Chrome will NOT allow it to run on a http site.
function fnStreamVideo(){
navigator.mediaDevices.getUserMedia({ video:true })
.then(function(stream) {
let video = document.getElementById('video');
video.srcObject = stream;
video.onloadedmetadata = function(e) {
video.play();
video.width=480;
video.height=320;
};
})
.catch(function(e){});
}
I'm on localhost and trying to use the MediaDevices.getUserMedia method in Chrome. I receive the error as titled. I understand that in Chrome it is only possible to use this function with a secure origin and that localhost is considered a secure origin. Also, this works in Firefox.
This is how I'm using it as shown on the Google Developers website https://developers.google.com/web/updates/2015/10/media-devices?hl=en:
var constraints = window.constraints = {
audio: false,
video: true
};
navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
callFactory.broadcastAssembly(stream);
...
});
On some latest browsers navigator.getUserMedia does not perform well. So, try using navigator.mediaDevices.getUserMedia. Or, better you check if navigator.mediaDevices.getUserMedia is available for the browser use navigator.mediaDevices.getUserMedia or else use navigator.getUserMedia.
navigator.getWebcam = (navigator.getUserMedia || navigator.webKitGetUserMedia || navigator.moxGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
if (navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ audio: true, video: true })
.then(function (stream) {
//Display the video stream in the video object
})
.catch(function (e) { logError(e.name + ": " + e.message); });
}
else {
navigator.getWebcam({ audio: true, video: true },
function (stream) {
//Display the video stream in the video object
},
function () { logError("Web cam is not accessible."); });
}
Hope this will solve your problem.
Try enabling: chrome://flags/#enable-experimental-web-platform-features
Worked for me in chromium
I too had the same problem in my chrome browser.
first check your phone is supported by testing it in https://test.webrtc.org/
if your phone passes all the cases, then check step 2
step 2:
If your hosting a webpage or running a third party webpage,see whether camera permissions are enabled on your phone.
Also the main issue is WEBRTC is not supported in HTTP site and it is supported only in HTTPS site
This is the https site which allows web
This is the http site which gives a error
I got stuck in the same issue. One solution is to follow and download the extension Web Server for Chrome shared in the comment above by #ellerynz, or
if you have python installed you could also do
python -m SimpleHTTPServer [port]
After you hit enter, you should see the following message:
Serving HTTP on 0.0.0.0 port 8000 ...
Open the browser and put
http://127.0.0.1:[port]
Have you tried to include adapter.js polyfill ? Check this page :
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#Browser_compatibility
It looks like this or enabling chrome://flags/#enable-experimental-web-platform-features as per #Simon Malone's note, is needed for Chrome.
I was having this problem too and changing flags didn't seem to work. I came across this chrome extension — Web Server for Chrome in Google's WebRTC tutorial which seemed to do the trick.
Use navigator.getUserMedia() instead.
navigator.getUserMedia(constraints, successCallback, errorCallback);
I am playing around with getUserMedia to gain access to the users microphone in Chrome(Version 28.0.1500.72 m). I am able to record and play back the users input when they use an internal microphone with internal speakers.
As soon as I plug in a usb microphone headset I am no longer able to record the users input. I have switched the device in the chrome setting under privacy and content settings. So chrome does see the newly plugged in microphone. I have restarted chrome and tried it again after plugging in the mic as well. Still no user input.
Thanks In Advance.
Below is the current code I am using.
window.AudioContext = window.AudioContext||window.webkitAudioContext;
var html5Recorder;
var audioContext = new AudioContext();
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
if(navigator.getUserMedia){
navigator.getUserMedia({audio:true},handleAudioStream, audioError)
}else{
console.log('Use Flash')
}
function handleAudioStream(stream){
var mediaStream = audioContext.createMediaStreamSource(stream);
mediaStream.connect( audioContext.destination );
html5Recorder = new HTML5Recorder(mediaStream);
html5Recorder.stop();
html5Recorder.clear();
}
function audioError(error){
console.log(error);
}
function record(){
html5Recorder.record();
}
function stopRecording(){
html5Recorder.stop();
html5Recorder.exportWAV(function(e){
console.log(e);
console.log(window.URL.createObjectURL(e));
document.getElementById('audio1').src = window.URL.createObjectURL(e);
HTML5Recorder.forceDownload(e);
});
}
This was a bug in the current chrome build I was using (28). Chrome canary works fine.
Can you check the sampling rate on the two audio devices?
There is an existing bug that the non-default microphone only works if the sample rate is the same as the default microphone: https://code.google.com/p/chromium/issues/detail?id=164058.
Also, are you on OSX or Linux? The comments in the bug make it look like it should be fixed on Windows.
Try selecting the USB mic as the default one. Chrome does not mange audio devices and it always uses the default mic.
I'm wondering if it's possible to detect whether a browser is running on iOS, similar to how you can feature detect with Modernizr (although this is obviously device detection rather than feature detection).
Normally I would favour feature detection instead, but I need to find out whether a device is iOS because of the way they handle videos as per this question YouTube API not working with iPad / iPhone / non-Flash device
Detecting iOS
With iOS 13 iPad both User agent and platform strings are changed and differentiating between iPad and MacOS seems possible, so all answers below needs to take that into account now.
This might be the shortest alternative that also covers iOS 13:
function iOS() {
return [
'iPad Simulator',
'iPhone Simulator',
'iPod Simulator',
'iPad',
'iPhone',
'iPod'
].includes(navigator.platform)
// iPad on iOS 13 detection
|| (navigator.userAgent.includes("Mac") && "ontouchend" in document)
}
iOS will be either true or false
Worse option: User agent sniffing
User Agent sniffing is more dangerous and problems appear often.
On iPad iOS 13, the user agent is identical with that of a MacOS 13 computer, but if you ignore iPads this might work still for a while:
var iOS = !window.MSStream && /iPad|iPhone|iPod/.test(navigator.userAgent); // fails on iPad iOS 13
The !window.MSStream is to not incorrectly detect IE11, see here and here.
Note: Both navigator.userAgent and navigator.platform can be faked by the user or a browser extension.
Browser extensions to change userAgent or platform exist because websites use too heavy-handed detection and often disable some features even if the user's browser would otherwise be able to use that feature.
To de-escalate this conflict with users it's recommended to detect specifically for each case the exact features that your website needs. Then when the user gets a browser with the needed feature it will already work without additional code changes.
Detecting iOS version
The most common way of detecting the iOS version is by parsing it from the User Agent string. But there is also feature detection inference*;
We know for a fact that history API was introduced in iOS4 - matchMedia API in iOS5 - webAudio API in iOS6 - WebSpeech API in iOS7 and so on.
Note: The following code is not reliable and will break if any of these HTML5 features is deprecated in a newer iOS version. You have been warned!
function iOSversion() {
if (iOS) { // <-- Use the one here above
if (window.indexedDB) { return 'iOS 8 and up'; }
if (window.SpeechSynthesisUtterance) { return 'iOS 7'; }
if (window.webkitAudioContext) { return 'iOS 6'; }
if (window.matchMedia) { return 'iOS 5'; }
if (window.history && 'pushState' in window.history) { return 'iOS 4'; }
return 'iOS 3 or earlier';
}
return 'Not an iOS device';
}
After iOS 13 you should detect iOS devices like this, since iPad will not be detected as iOS devices by old ways (due to new "desktop" options, enabled by default):
let isIOS = /iPad|iPhone|iPod/.test(navigator.platform)
|| (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
The first condition for iOS < 13 or iPhone or iPad with disabled Desktop mode, the second condition for iPadOS 13 in the default configuration, since it position itself like Macintosh Intel, but actually is the only Macintosh with multi-touch.
Rather a hack than a real solution, but work reliably for me
P.S. As being said earlier, you probably should add IE checkup
let isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream
None of the previous answers here work for all major browsers on all versions of iOS, including iOS 13. Here is a solution that works for Safari, Chrome and Firefox for all iOS versions:
var isIOS = (function () {
var iosQuirkPresent = function () {
var audio = new Audio();
audio.volume = 0.5;
return audio.volume === 1; // volume cannot be changed from "1" on iOS 12 and below
};
var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
var isAppleDevice = navigator.userAgent.includes('Macintosh');
var isTouchScreen = navigator.maxTouchPoints >= 1; // true for iOS 13 (and hopefully beyond)
return isIOS || (isAppleDevice && (isTouchScreen || iosQuirkPresent()));
})();
Note that this code snippet was written with priority on readability, not conciseness or performance.
Explanation:
If the user agent contains any of "iPod|iPhone|iPad" then clearly the device is iOS. Otherwise, continue...
Any other user agent that does not contain "Macintosh" is not an Apple device and therefore cannot be iOS. Otherwise, it is an Apple device, so continue...
If maxTouchPoints has a value of 1 or greater then the Apple device has a touch screen and therefore must be iOS since there are no Macs with touch screens (kudos to kikiwora for mentioning maxTouchPoints). Note that maxTouchPoints is undefined for iOS 12 and below, so we need a different solution for that scenario...
iOS 12 and below has a quirk that does not exist in Mac OS. The quirk is that the volume property of an Audio element cannot be successfully set to any value other than 1. This is because Apple does not allow volume changes on the Audio element for iOS devices, but does for Mac OS. That quirk can be used as the final fallback method for distinguishing an iOS device from a Mac OS device.
This sets the variable _iOSDevice to true or false
_iOSDevice = !!navigator.platform.match(/iPhone|iPod|iPad/);
If you are using Modernizr, you can add a custom test for it.
It doesn't matter which detection mode you decide to use (userAgent, navigator.vendor or navigator.platform), you can always wrap it up for a easier use later.
//Add Modernizr test
Modernizr.addTest('isios', function() {
return navigator.userAgent.match(/(iPad|iPhone|iPod)/g);
});
//usage
if (Modernizr.isios) {
//this adds ios class to body
Modernizr.prefixed('ios');
} else {
//this adds notios class to body
Modernizr.prefixed('notios');
}
A simplified, easy to extend version.
var iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
UPDATE: My original answer doesn't cover iPad in desktop mode (the default changes to desktop mode in upcoming iPadOS 13 and higher).
That's fine for my usecases, if it's not for you, use this update:
// iPhone and iPad including iPadOS 13+ regardless of desktop mode settings
iOSiPadOS = /^iP/.test(navigator.platform) ||
/^Mac/.test(navigator.platform) && navigator.maxTouchPoints > 4;
This should be safe as long as
desktop Macs don't support touch events at all
or not more than 4 touch points (current iOS devices support 5 touch points)
It's fast because the regexp ^ first checks the starting position of the platform string and stops if there is no "iP" (faster than searching the long UA string until the end anyway)
It's safer than navigator.userAgent check as navigator.platform is much less likely faked
Detects iPhone / iPad Simulator
ORIGINAL ANSWER: Wow, a lot of longish tricky code here. Keep it simple, please!
This one is IMHO fast, save, and working well:
iOS = /^iP/.test(navigator.platform);
// or, if you prefer it verbose:
iOS = /^(iPhone|iPad|iPod)/.test(navigator.platform);
Detecting iOS (both <12, and 13+)
Community wiki, as edit queue says it is full and all other answers are currently outdated or incomplete.
const iOS_1to12 = /iPad|iPhone|iPod/.test(navigator.platform);
const iOS13_iPad = (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1));
const iOS1to12quirk = function() {
var audio = new Audio(); // temporary Audio object
audio.volume = 0.5; // has no effect on iOS <= 12
return audio.volume === 1;
};
const isIOS = !window.MSStream && (iOS_1to12 || iOS13_iPad || iOS1to12quirk());
It's probably worth answering that iPads running iOS 13 will have navigator.platform set to MacIntel, which means you'll need to find another way to detect iPadOS devices.
I wrote this a couple years ago but i believe it still works:
if(navigator.vendor != null && navigator.vendor.match(/Apple Computer, Inc./) && navigator.userAgent.match(/iPhone/i) || (navigator.userAgent.match(/iPod/i)))
{
alert("Ipod or Iphone");
}
else if (navigator.vendor != null && navigator.vendor.match(/Apple Computer, Inc./) && navigator.userAgent.match(/iPad/i))
{
alert("Ipad");
}
else if (navigator.vendor != null && navigator.vendor.match(/Apple Computer, Inc./) && navigator.userAgent.indexOf('Safari') != -1)
{
alert("Safari");
}
else if (navigator.vendor == null || navigator.vendor != null)
{
alert("Not Apple Based Browser");
}
Wherever possible when adding Modernizr tests you should add a test for a feature, rather than a device or operating system. There's nothing wrong with adding ten tests all testing for iPhone if that's what it takes. Some things just can't be feature detected.
Modernizr.addTest('inpagevideo', function ()
{
return navigator.userAgent.match(/(iPhone|iPod)/g) ? false : true;
});
For instance on the iPhone (not the iPad) video cannot be played inline on a webpage, it opens up full screen. So I created a test 'no-inpage-video'
You can then use this in css (Modernizr adds a class .no-inpagevideo to the <html> tag if the test fails)
.no-inpagevideo video.product-video
{
display: none;
}
This will hide the video on iPhone (what I'm actually doing in this case is showing an alternative image with an onclick to play the video - I just don't want the default video player and play button to show).
There is no need to test navigator.userAgent or navigator.platform:
const isIOS = typeof navigator.standalone === 'boolean';
navigator.standalone is only set on iOS Safari. See MDN, Safari HTML Reference.
If you're using React, There is great library for this kind of issues: REACT-UGENT. (Built with ua-parser-js.)
https://github.com/medipass/react-ugent
Available browsers are:
chrome, chromium, edge, firefox, ie, lynx, safari, opera
Available OS are:
android, blackberry, chromium os, debian, ios, linux, mac os, ubuntu, unix, windows
Available devices are:
console, computer, mobile, tablet, smarttv, wearable, embedded
Easy to use as:
<Ugent browser="safari" os="ios">
<div>
This text only shows on Safari on iOS.
</div>
</Ugent>
If you're not using React, basically, you can use - ua-parser-js
https://github.com/faisalman/ua-parser-js
The user-agents on iOS devices say iPhone or iPad in them. I just filter based on those keywords.
If you are still trying to check if is iOS or not, I recommend you to use this approach:
Create a folder called helper
Create a file called platform.ts or platform.js
Export the function isIOS:
export const isIOS = () => {
let platform = navigator?.userAgent || navigator?.platform || 'unknown'
return /iPhone|iPod|iPad/.test(platform)
}
The result will be true if is an iPhone or iPod or Ipad or it will be false otherwise.
You may ask, why do I need to check navigator.userAgent || navigator.platform, well the reason is simple the second option used to be the default one but now it is deprecated and some browsers will stop supporting this in the future, the first one is more reliable.
You can check here about the deprecation that I mentioned above:
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform#:~:text=Deprecated%3A%20This%20feature%20is%20no,be%20kept%20for%20compatibility%20purposes.
Logging the userAgentData, userAgent and platform.
Using the function below, I received these logs:
console.log({
userAgentData: navigator?.userAgentData?.platform,
userAgent: navigator?.userAgent,
platform: navigator?.platform,
})
{
"userAgentData": "",
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1",
"platform": "MacIntel"
}
I was testing it on my Macbook and it worked on different browsers and operation systems. So, as you can see navigator?.userAgentData?.platform will not work at all.
I also didn't receive any errors related to my typescript, even though that I am using React to call this function.
Bonus, isAndroid
If you wondering how to check if is an Android platform, I suggest you don't follow the idea of doing the opposite of isIOS as:
const isAndroid = !isIOS();
The reason is quite simple, it will not work since desktops will be recognized as an Android platform.
To solve this problem you just need to do this check:
export const isAndroid = () => {
const ua = navigator.userAgent.toLowerCase() + navigator?.platform.toLowerCase();
const isAndroid = ua.indexOf("android") > -1;
return isAndroid;
}
The reason why we are checking navigator.userAgent plus navigator?.platform is to support old browsers and the new ones.
You can also use includes
const isApple = ['iPhone', 'iPad', 'iPod', 'iPad Simulator', 'iPhone Simulator', 'iPod Simulator',].includes(navigator.platform)
Because navigator.platform is deprecated and it is better to not use it anymore, I want to add an other solution.
You can filter on MacOS systems by checking the navigator.vendor.
When the outcome is Apple Computer, Inc., you know it is MacOS.
In my case the user agent was not good enought since in the Ipad the user agent was the same as in Mac OS, therefore I had to do a nasty trick:
var mql = window.matchMedia("(orientation: landscape)");
/**
* If we are in landscape but the height is bigger than width
*/
if(mql.matches && window.screen.height > window.screen.width) {
// IOS
} else {
// Mac OS
}
In order to detect the iOS version, one has to destructure the user agent with a Javascript code like this:
var res = navigator.userAgent.match(/; CPU.*OS (\d_\d)/);
if(res) {
var strVer = res[res.length-1];
strVer = strVer.replace("_", ".");
version = strVer * 1;
}
var isiOSSafari = (navigator.userAgent.match(/like Mac OS X/i)) ? true: false;