I'm using getUserMedia() for audio recording and it works correctly but have an issue with it.
I want to display a message before starting recording that any microphone is connected with system or not.
For this I have used following code and run this into chrome but it was not working correctly.
if(navigator.getUserMedia || navigator.webkitGetUserMedia)
{
alert("Microphone is connected with your system");
} else {
alert("Microphone is not connected with your system");
}
when microphone is not connected then also above code giving message "Microphone is connected with your system".
so please suggest me a better way to detect microphone using JavaScript in any browser.
Testing for the existence of these functions does not detect the existence of hardware microphone. It only detects if browser has the API to do so.
The browsers that pass your test need not have a physical microphone plugged into microphone jack. It is simply a newer browser. The browsers that fail the test may have a microphone, but are old browsers that do not contain the API.
Also, at least the getUserMedia function is asynchronous, so any code that depends on using the audio or video must be put in a callback function, not the main script.
See https://developer.mozilla.org/en-US/docs/Web/API/Navigator.getUserMedia for an example of how to write cross-browser code for audio/video input.
Something like this:
function success(stream) {
// we have it
}
function fail(error) {
console.log(error);
if (error === 'NO_DEVICES_FOUND') {
// NO_DEVICES_FOUND (no microphone or microphone disabled)
}
}
navigator.getUserMedia({ audio: true }, success, fail);
Try this
navigator.mediaDevices.getUserMedia({ audio: true })
.then(stream => {
// Code for success
}).catch(err => {
if(err.includes("NotFoundError: Requested device not found"))
alert("Mic not detected")
else alert("Error recording audio")
})
If the mic is not detected or unplugged means the catch statement will be executed. You can show your error message here.
You can use this link
I used this method
developer.mozilla.org
Related
I need to tell if a person dismisses the media popup or blocks the media popup
const [permissions, setPermissions] = useState(false)
const handleClick = () => {
setPermissions('pending');
navigator.getUserMedia({ video: true, audio: true }, stream => {
stream.getTracks().forEach(track => {
return setPermissions(track.enabled);
});
}, (error) => {
if(error ==='DOMException: Permission denied'){
setPermissions('denied')
}
if(error === 'DOMException: Permission dismissed'){
setPermissions('dismissed')
}
});
};
I tried using the error string that I got back but it is not working. I need to be able to tell the difference between the errors. Does anyone have a good way to do this? Thanks!
You can't tell the difference in any exact way. Browsers are very uncooperative with Javascript code that tries to access media devices but doesn't get permission from the user. Because cybercreeps.
I've had a bit of success with this to see if the user denied access:
Try again. If you get an immediate (within a couple of seconds) error they probably have already denied access to the devices. If it takes longer, they probably are looking at a repeat of the permission dialog.
Not a great situation. Especially if you want to explain to the user how to go back and un-deny permission. But it's a necessary privacy feature in the surveillance era.
I'm attempting to access the microphone on iOS Safari with the help of the getUserMedia. Below you can find a snippet of my code.
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function(constraints) {
// First get ahold of the legacy getUserMedia, if present
let getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// Some browsers just don't implement it - return a rejected promise with an error
// to keep a consistent interface
if (!getUserMedia) {
return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
}
// Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
return new Promise(function(resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
}
}
navigator.mediaDevices.getUserMedia({
audio: true
}).then(function(stream) {
successCallBack(.......);
}).catch(function(error) {
debug.log(error);
..........
});
Yet the promise always catches an error, to be more specific an OverConstraintError.
{message: "Invalid constraint", constraint: ""}
This behaviour is unique for iOS Safari, on all other browsers (Chrome, Firefox, Safari osX) it works without any problem. Actually my issue ressembles a lot like this one => How to resolve iOS 11 Safari getUserMedia "Invalid constraint" issue, yet I'm not trying to use the camera. The only thing that interests me is the microphone.
I'm testing with a real iPhone (a 5 and X, both updated to the latest version), so it is not linked to the iPhone Simulator.
The access to the microphone is granted and the popup requesting permissions is also showing, so it is not an permissions issue.
This issue may be related to this bug report titled getUserMedia fails with an OverConstrainedError when no devices are found:
https://bugs.webkit.org/show_bug.cgi?id=177126
Here is your code running in Codepen. As you stated, audio is enabled and works. Note the enumerateDevices() call returns an empty array. As the bug states, this causes the error in your question:
.catch(function(error) {
navigator.mediaDevices.enumerateDevices().then(devices=>{console.log(devices)});
console.log('error: ',error);
});
https://codepen.io/anon/pen/rQWRyZ?editors=0011
web rtc or getusermedia has some issues and it is not working on all platforms as u expect - have same problems with camera detection like in samsung s5 same code is working fine but under newer device it was failing.
My advice is to use webrtc adapter js.
Try simply include this script:
<script src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/6.4.0/adapter.js" type="text/javascript"></script>
before u use getusermedia api. I think that 99% of issues just disappear.
Trying to access IP Camera that is connected to a wifi.
I am connected to that wifi but I am getting error. If I try open using vlc I am able to connect but not getUserMedia has null.
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
})
export class HomeComponent {
#ViewChild('video') video: any;
constructor() {
}
hasGetUserMedia() {
return !!(navigator.mediaDevices &&
navigator.mediaDevices.getUserMedia);
}
ngAfterViewInit() {
if (this.hasGetUserMedia()) {
// Good to go!
console.log("Gooddd................");
} else {
alert('getUserMedia() is not supported by your browser');
}
let _video = this.video.nativeElement;
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(function (stream) {
_video.src = window.URL.createObjectURL(stream);
_video.play();
}).catch(function (err) {
console.log(err);
});
}
}
}
<video #video width="640" height="480" autoplay></video>
This happens when you dont have any device to capture video or capture audio
try checking if your webcam and your microphone are working fine
Try without "audio: true". Its help for my. (Microphone are not work).
And check webcam on other sites.
Maybe need check permissions for this page.
try changing this line:
_video.src = window.URL.createObjectURL(stream);
with this one:
_video.srcObject = stream;
Use this line to initialize the webcam and microphone:
navigator.mediaDevices.getUserMedia({ audio: true, video: true });
In my case i have connected external camera through USB i was able to get the devices, i was getting kind of devices as audiooutput and videoinput, and there was no audioinput(microphone device) but while i was requesting for devices i passed constraints as..
function Webcam(){
this.constraints = {
video: true,
audio: true
}
this.userMedia = null;
this.mediaDevices = navigator.mediaDevices;
this.initialize = function(){
this.userMedia = this.mediaDevices.getUserMedia(this.constraints);
}
}
let webcam = new Webcam();
webcam.initialize();
So Promise not satisified and getting error as Requested device not found.
Try attaching an earpiece or earplug with microphone to your PC. mine has no microphone that was why I got that error
This issue can also occur on some mobile devices (Sony XA2 running Android) if you had previously already created a MediaStream.
The solution that I found was to make sure to stop all the tracks of previous streams that you created.
this.stream.getTracks().forEach(t => {
t.stop();
// I don't think removeTrack is necessary, but just keeping it.
this.stream.removeTrack(t);
});
Without the previous code you can't seem to toggle camera on certain Android devices: (Demo),
(Code)
The error shown was DOMException: Requested device not found
By stopping previous tracks: you are able to start a new stream:
(Demo)
Code
Note: I also answered a related question here: https://stackoverflow.com/a/73550841/1123985
I have mic and camera but I was getting the same error. I was pretty sure that was related to laptop setting, because I tried everything. turns out my laptop was blocking access to the media. I am using linux and laptop brand name is MSI, I started to look for any sign that related to the camera setting. On F6 button, my laptop has a webcam icon. So I clicked on
fn + F6
It works now. most likely sometimes I click on fn+* keys to see any difference and I blocked the camera access.
I want to capture video with the webcamera.
And there is the right decision:
window.onload = function () {
var video = document.getElementById('video');
var videoStreamUrl = false;
navigator.getUserMedia({video: true}, function (stream) {
videoStreamUrl = window.URL.createObjectURL(stream);
video.src = videoStreamUrl;
}, function () {
console.log('error');
});
};
but produces an error in the browser:
[Deprecation] URL.createObjectURL with media streams is deprecated and will be removed in M68, around July 2018. Please use HTMLMediaElement.srcObject instead. See https://www.chromestatus.com/features/5618491470118912 for more details.
how to use HTMLMediaElement.srcObject for my purposes ? Thanks for your time!
MediaElement.srcObject should allow Blobs, MediaSources and MediaStreams to be played in the MediaElement without the need to bind these sources in the memory for the lifetime of the document like blobURIs do.
(Currently no browser support anything else than MediaStream though...)
Indeed, when you do URL.createObjectURL(MediaStream), you are telling the browser that it should keep alive this Source until your revoke the blobURI, or until the document dies.
In the case of a LocalMediaStream served from a capturing device (camera or microphone), this also means that the browser has to keep the connection to this device open.
Firefox initiated the deprecation of this feature, one year or so ago, since srcObject can provide the same result in better ways, easier to handle for everyone, and hence Chrome seems to finally follow (not sure what's the specs status about this).
So to use it, simply do
MediaElement.srcObject = MediaStream;
Also note that the API you are using is itself deprecated (and not only in FF), and you shouldn't use it anymore. Indeed, the correct API to capture MediaStreams from user Media is the MediaDevices.getUserMedia one.
This API now returns a Promise which gets resolved to the MediaStream.
So a complete correction of your code would be
var video = document.getElementById('video');
navigator.mediaDevices.getUserMedia({
video: true
})
.then(function(stream) {
video.srcObject = stream;
})
.catch(function(error) {
console.log('error', error);
});
<video id="video"></video>
Or as a fiddle since StackSnippetsĀ® overprotected iframe may not deal well with gUM.
I am trying to analyse the audio output from the browser, but I don't want the getUserMedia prompt to appear (which asks for microphone permission).
The sound sources are SpeechSynthesis and an Mp3 file.
Here's my code:
return navigator.mediaDevices.getUserMedia({
audio: true
})
.then(stream => new Promise(resolve => {
const track = stream.getAudioTracks()[0];
this.mediaStream_.addTrack(track);
this._source = this.audioContext.createMediaStreamSource(this.mediaStream_);
this._source.connect(this.analyser);
this.draw(this);
}));
This code is working fine, but it's asking for permission to use the microphone! I a not interested at all in the microphone I only need to gauge the audio output. If I check all available devices:
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
devices.forEach(function(device) {
console.log(device.kind + ": " + device.label +
" id = " + device.deviceId);
});
})
I get a list of available devices in the browser, including 'audiooutput'.
So, is there a way to route the audio output in a media stream that can be then used inside 'createMediaStreamSource' function?
I have checked all the documentation for the audio API but could not find it.
Thanks for anyone that can help!
There are various ways to get a MediaStream which is originating from gUM, but you won't be able to catch all possible audio output...
But, for your mp3 file, if you read it through an MediaElement (<audio> or <video>), and if this file is served without breaking CORS, then you can use MediaElement.captureStream.
If you read it from WebAudioAPI, or if you target browsers that don't support captureStream, then you can use AudioContext.createMediaStreamDestination.
For SpeechSynthesis, unfortunately you will need gUM... and a Virtual Audio Device: first you would have to set your default output to the VAB_out, then route your VAB_out to VAB_in and finally grab VAB_in from gUM...
Not an easy nor universally doable task, moreover when IIRC SpeechSynthesis doesn't have any setSinkId method.