Closed xvs32x closed 7 years ago
Hi @xvs32x, you can change the camera and microphone source by passing the sourceId
in the optional
parameter for both audio
and video
objects, which is available in joinRoom()
, getUserMedia()
and sendStream()
methods.
To obtain the list, you may use navigator.mediaDevices.enumerateDevices
API:
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
devices.forEach(function(device) {
console.log(device.kind + ": " + device.label + " id = " + device.deviceId);
});
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
});
(Demo code from Mozilla MDN).
For browsers like Safari 9.1 < and IE that do not support Promise API yet, it is recommended that you use MediaStreamTrack.getSources
API only for these browsers to use this:
MediaStreamTrack.getSources(function (mt) {
for (var i = 0; i < mt.length; i++) {
var device = mt[i];
console.log(device.kind + ": " + device.label + " id = " + device.id);
}
});
After you have obtained the the values, you may select the source with this:
var skylink = new Skylink();
skylink.joinRoom({
audio: { optional: [{ sourceId: audioDevice.deviceId || audioDevice.id }] },
video: { optional: [{ sourceId: videoDevice.deviceId || videoDevice.id }] }
});
Note that that for this is only supported for Firefox 39 (and above) and Chrome 45 (and above). But you shouldn't have any issues if you are following our supported browsers list which starts with Firefox version 40 and Chrome 45.
(See supported list here)
@letchoo, many thanks for answer! :) But I have a trouble. Your solution work in Chrome only, firefox(47) display standart system dialog with input devices list and ignore my sourceId :(
Hi @xvs32x, this is likely a Firefox issue since they have a prompt to always display the dialog with the input devices list regardless of providing the sourceId
in the optional
constraints.
There seems to be a related bugzilla ticket raised on their end which you may check it out. I suggest raising this issue with the Firefox team to resolve this.
Hi @letchoo. Thanks for your answer. :) Display dialog box is not terrible for me. The problem is that the device I chose is not selected in this dialog box. For example, if I send the sourceID with the name of "Camera 2", in the dialog box I still see the "camera 1" (as the first in the list). I found working example: https://webrtc.github.io/samples/src/content/devices/input-output/ In this example standart dialog displayed "Camera 2" if I selected "Camera 2". If I understand correctly is not worked in Skylink because "navigator.mediaDevices.getUserMedia" overwritten... https://github.com/Temasys/SkylinkJS/blob/master/publish/skylink.complete.js#L8278 But i'm not sure... :)
Hi @xvs32x, yes you are right. We should be able to set the source ID regardless.
Meanwhile, if you require a quick fix before we implement the proper fixes in the future releases, here's what you can do:
Instead of using skylink.complete.js
directly:
<script src="https://cdn.temasys.com.sg/skylink/skylinkjs/0.6.13/skylink.complete.js"></script>
Reference the SkylinkJS codes and it's dependencies separately:
<script src="https://cdn.socket.io/socket.io-1.4.4.js"></script>
<script src="adapter.screenshare.js"></script>
<script src="https://cdn.temasys.com.sg/skylink/skylinkjs/0.6.13/skylink.debug.js"></script>
The adapter.screenshare.js
source code can be obtained from here. Copy and paste the source code and save it to a file named adapter.screenshare.js
.
adapter.screenshare.js
fileThere will be two changes that you will have to make.
For the first modification (which is in this line):
if (window.navigator.mozGetUserMedia) {
baseGetUserMedia = window.navigator.getUserMedia;
. . .
Replace the baseGetUserMedia = window.navigator.getUserMedia;
line with the following changes:
if (window.navigator.mozGetUserMedia) {
// Modifications start here
if (window.navigator.mediaDevices &&
typeof window.navigator.mediaDevices.getUserMedia === 'function') {
var filterSourceId = function (constraintItem) {
if (constraintItem && typeof constraintItem === 'object') {
if (Array.isArray(constraintItem.optional)) {
var updatedConstItem = clone(constraintItem);
for (var i = 0; i < updatedConstItem.optional.length; i++) {
if (updatedConstItem.optional[i] && typeof updatedConstItem.optional[i] === 'object'
&& updatedConstItem.optional[i].hasOwnProperty('sourceId')
&& updatedConstItem.optional[i].sourceId) {
updatedConstItem.deviceId = { exact: updatedConstItem.optional[i].sourceId };
updatedConstItem.optional.splice(i, 1);
i--;
}
}
return updatedConstItem;
}
return constraintItem;
}
return !!constraintItem;
};
baseGetUserMedia = function (constraints, successCb, failureCb) {
var updatedConstraints = {
audio: filterSourceId(constraints.audio),
video: filterSourceId(constraints.video)
};
window.navigator.mediaDevices.getUserMedia(updatedConstraints).
then(successCb).catch(failureCb);
};
} else {
baseGetUserMedia = window.navigator.getUserMedia;
}
For the second modification (which is in this line):
Comment out the modifications to navigator.mediaDevices.getUserMedia
:
/*navigator.mediaDevices.getUserMedia = function(constraints) {
return new Promise(function(resolve, reject) {
window.getUserMedia(constraints, resolve, reject);
});
};*/
Save the adapter.screenshare.js
file. After that, the changes should work with the examples given in the comment above.
Hi @xvs32x, your issue should be resolved with the AdapterJS 0.14.0
release.
One thing to note though, when using the navigator.mediaDevices.getUserMedia
method, it doesn't prompt the user to install the Firefox add-on when it's not available, but you can use the navigator.getUserMedia
API instead since internally it's been polyfilled with the webrtc/adapter
(AdapterJS uses 2.0.3
version) so your sourceId: { exact: xxx }
should work.
I'm closing this ticket since the issue has been resolved on AdapterJS end. If the issue persist, please open the ticket on AdapterJS github.
Hello. How i can change camera and microphone with API. Documentation is empty. Thanks