Determine device ID of a camera with a specified facing mode - javascript

I am working on code to allow for an in-page select element to choose a camera. The default camera should be the "environment" camera while the rest should be listed after.
Using the following call I am able to stream video from an appropriate "environment"-facing camera:
navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment"} }).then(function (stream) {
// display stream on web page
...
});
Similarly, I can get the list of available devices using the following:
navigator.mediaDevices.enumerateDevices().then(
devices => {
// build list of options
}
);
I store the deviceId for each option and use that to display the feed from that camera which works well.
However, the option selected by default is not necessarily the "environment" camera. And the stream object returned from getUserMedia doesn't seem to have an easy way to determine the deviceId of the device providing that stream. Nor can I seem to find any other way to determine the "environment"-facing camera.
Is this not possible or is there some kind of getDeviceIdForFacingMode function that I've just missed?

After digging through the objects a bit more I was ultimately able to find that the following works to get the deviceId from the stream:
stream.getVideoTracks()[0].getSettings().deviceId
I would assume that in other cases you may need to get careful about the [0] if for some reason your stream involved multiple video tracks but for my purposes this worked well. In general I would expect you could get whatever information you need between stream.getVideoTracks()[i] (MediaStreamTrack) and stream.getVideoTracks()[i].getSettings() (MediaTrackSettings).

Related

Browser permissions for GetUserMedia from different camera devices

In the site I am coding, I want the user to have the option of toggling between different video input devices and view the stream.
I am able to enumerate all the devices using navigator.mediaDevices.enumerateDevices() and filtering this by kind gives me the video input devices.
However, when I try to use
navigator.mediaDevices.getUserMedia({ video: { deviceId: deviceIdOfSelectedDevice }}), I notice that I only get the stream of the camera allowed by the browser irrespective of the deviceId. I want to prompt for browser permissions to allow a different camera.
The documentation says this about your code:
The above will return the camera you requested, or a different camera if that specific camera is no longer available.
The document also says that you can require a device with exact:
{ video: { deviceId: { exact: deviceIdOfSelectedDevice } } }

Is capturing only audio using chrome.desktopCapture API possible?

In a chrome-extension,i want to use desktopCapture API to only capture the window audio.I do not want the video stream.
But it turns out the streamId would be undefined always when i am trying to use it like shown below.
chrome.desktopCapture.chooseDesktopMedia(['audio'],(streamId,options) => {
//retrieve mediastream using streamId and navigator API
})
Please let me know what i am doing wrong or what approach i should take to capture browser audio.

getUserMedia() : get environment camera with wide enough field of view

I'm using rear smartphone camera using:
navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" }, audio: false })
.then((stream) => {...})
However, when using those constraints on a Huawei P30 (having 3 rear camera sensors),
the retrieved video stream has a very narrow field of view ; maybe the "zoom" sensor is used to retrieve the stream. For my app, I need a more "all purpose" field of view, not too narrow like that.
I found that I can get the stream from another sensor by using the constraint deviceId (value found using navigator.mediaDevices.enumerateDevices()), but I have to support as many smartphones as possible, so relying only on deviceId does not seems a viable option (deviceId even changes for each origin & browsing session).
Does any getUserMedia() constraint exists, allowing to get a camera stream with specific field of view angle (or any related characteristic such as focal length, zoom level...)?

Node JS access audio interface

I want to send audio signal coming from my audio interface (focusrite saffire) to my nodejs server. How should I go about doing this? The easiest way would be to access the audio interface from the browser (html5) like capturing microphone output with getUserMedia (https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia), but couldn't find a way to access my audio interface through that library. Otherwise, I'm planning on creating a desktop application, but don't know if there is a function/library to allow access to my usb-connected audio interface.
This probably has little to do with the Javascript or the MediaDevices API. On Linux, using Firefox, PulseAudio is required to interface with your audio hardware. Since your soundcard is an Input/Output interface, you should be able to test it pretty easily by simply playing any sound file in the browser.
Most of PulseAudio configuration can be achieved using pavucontrol GUI. You should check the "configuration" tab and both "input device" & "output device" tabs to make sure your Focusrite is correctly set up and used as sound I/O.
Once this is done, you should be able to access an audio stream using the following (only available if on a "secure context", ie localhost or served through HTTPS, as stated in the MDN page you mentionned):
navigator.mediaDevices.getUserMedia({ audio: true })
.then(function(stream) {
// do whatever you want with this audio stream
})
(code snippet taken from the MDN page about MediaDevices)
Sending audio to the server is a whole other story. Have you tried anything? Are you looking for a real-time communication with the server? If so, I'd start by having a look at the WebSockets API. The WebRTC docs might be worth reading too, but it is more oriented to client-to-client communications.
How to use exact device id
Use media device constrain to pass exact device id.
An sample would be
const preferedDeviceName = '<your_device_name>'
const deviceList = await navigator.mediaDevices.enumerateDevices()
const audio = devices.find((device) => device.kind === 'audioinput' && device.label === preferedDeviceName)
const {deviceId} = audio;
navigator.mediaDevices.getUserMedia({audio: { deviceId }}
How to process and send to the backend
Possible duplicate of this
Still not clear follow this

Change the VideoTrack of a MediaStream object

In a Nutshell: I'm trying to change the VideoTrack of a MediaStream object.
(Documentation: https://developer.mozilla.org/en-US/docs/WebRTC/MediaStream_API)
I have a MediaStream object __o_jsep_stream_audiovideo which is created by the sipml library.
__o_jsep_stream_audiovideo looks like this:
So it has one AudioTrack and one VideoTrack. At first the VideoTrack comes from the users camera (e.g label: "FaceTime Camera").
According to the Documentation:
A MediaStream consists of zero or more MediaStreamTrack objects, representing various audio or video tracks.
So we should be fine adding more Tracks to this Stream.
I'm trying to switch/exchange the VideoTrack with that from another stream. The other stream (streamB) originates from Chromes ScreenCapture api (label: "Screen")
I tried:
__o_jsep_stream_audiovideo.addTrack(streamB.getVideoTracks()[0])
which doesn't seem to have any effect.
I also tried assigning the videoTracks directly (which was desperate I know).
I must be missing something obvious could you point me in the right direction?
I'm running
Chrome (Version 34.0.1847.131) and
Canary (Version 36.0.1976.2 canary)
OSX 10.9.2
When you talk about change video track, we mean 2 areas:
change the remote video track (what the others can see from u)
WebRTC gets new version of doing that, since it deprecates addStream/removeStream.
However, the excelence is that they introduce new interface replaceTrack
stream.getTracks().forEach(function(track) {
// remote
qcClient.calls.values().forEach(function(call) {
var sender = call.pc.getSenders().find(function(s) {
return s.track.kind == track.kind;
});
sender.replaceTrack(track);
});
});
change your display video (You see yourself)
Better to just add a new video element (or using existing video element) But assign srcObject to the new captured stream
Adding and removing tracks on a MediaStream object do not signal a renegotiation and there are also issues with a MediaStream having two tracks of the same type in chrome.
You should probably just add the separate mediastream to the peer connection so that it can fire a re-negotiation and handle the streams. The Track add/remove functionality in chrome is very naive and not very granular and you should move away from it as much as you can.

Categories