How to choose input video device for webrtc?
I am studying webRTC application.
My reference is this software
apprtc https://code.google.com/p/webrtc/source/browse/trunk/samples/js/apprtc/
demo https://apprtc.appspot.com/
My computer has bult-in video device and apprtc uses this video device . However I want to use USB-video camera instead.
I am searching the way to change input video devices. But I couldn't find any clue in source files.
does anyone has information?
Solution 1:
On Chrome:
chrome://settings/content/camera
chrome://settings/content/microphone
On Firefox: media.navigator.permission.disabled=false
Solution 2:
Try this demo which is capturing all audio/video input devices:
https://www.webrtc-experiment.com/demos/MediaStreamTrack.getSources.html
You can capture any "specific" device using same API.
Edited at March 01, 2014:
MediaStreamTrack.getSources(function (media_sources) {
for (var i = 0; i < media_sources.length; i++) {
var media_source = media_sources[i];
var constraints = {};
// if audio device
if (media_source.kind == 'audio') {
constraints.audio = {
optional: [{
sourceId: media_source.id
}]
};
}
// if video device
if (media_source.kind == 'video') {
constraints.video = {
optional: [{
sourceId: media_source.id
}]
};
}
// invoke getUserMedia to capture this device
navigator.webkitGetUserMedia(constraints, function (stream) {
console.log(stream.id, stream);
}, console.error);
}
});
Updated at Sep 05, 2015:
Now Microsoft Edge, Chrome 44+, Firefox 38+, all these browsers are supporting navigator.mediaDevices.enumerateDevices
API.
Here is a reusable script that provides cross-browser shim for all these media-sources APIs. It will work even in old-chrome (43 and older) (even on Android devices):
if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
// Firefox 38+, Microsoft Edge, and Chrome 44+ seems having support of enumerateDevices
navigator.enumerateDevices = function(callback) {
navigator.mediaDevices.enumerateDevices().then(callback);
};
}
function getAllAudioVideoDevices(successCallback, failureCallback) {
if (!navigator.enumerateDevices && window.MediaStreamTrack && window.MediaStreamTrack.getSources) {
navigator.enumerateDevices = window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack);
}
if (!navigator.enumerateDevices && navigator.mediaDevices.enumerateDevices) {
navigator.enumerateDevices = navigator.mediaDevices.enumerateDevices.bind(navigator);
}
if (!navigator.enumerateDevices) {
failureCallback(null, 'Neither navigator.mediaDevices.enumerateDevices NOR MediaStreamTrack.getSources are available.');
return;
}
var allMdiaDevices = [];
var allAudioDevices = [];
var allVideoDevices = [];
var audioInputDevices = [];
var audioOutputDevices = [];
var videoInputDevices = [];
var videoOutputDevices = [];
navigator.enumerateDevices(function(devices) {
devices.forEach(function(_device) {
var device = {};
for (var d in _device) {
device[d] = _device[d];
}
// make sure that we are not fetching duplicate devics
var skip;
allMdiaDevices.forEach(function(d) {
if (d.id === device.id) {
skip = true;
}
});
if (skip) {
return;
}
// if it is MediaStreamTrack.getSources
if (device.kind === 'audio') {
device.kind = 'audioinput';
}
if (device.kind === 'video') {
device.kind = 'videoinput';
}
if (!device.deviceId) {
device.deviceId = device.id;
}
if (!device.id) {
device.id = device.deviceId;
}
if (!device.label) {
device.label = 'Please invoke getUserMedia once.';
}
if (device.kind === 'audioinput' || device.kind === 'audio') {
audioInputDevices.push(device);
}
if (device.kind === 'audiooutput') {
audioOutputDevices.push(device);
}
if (device.kind === 'videoinput' || device.kind === 'video') {
videoInputDevices.push(device);
}
if (device.kind.indexOf('audio') !== -1) {
allAudioDevices.push(device);
}
if (device.kind.indexOf('video') !== -1) {
allVideoDevices.push(device);
}
// there is no 'videoouput' in the spec.
// so videoOutputDevices will always be [empty]
allMdiaDevices.push(device);
});
if (successCallback) {
successCallback({
allMdiaDevices: allMdiaDevices,
allVideoDevices: allVideoDevices,
allAudioDevices: allAudioDevices,
videoInputDevices: videoInputDevices,
audioInputDevices: audioInputDevices,
audioOutputDevices: audioOutputDevices
});
}
});
}
Here is how to use above reusable cross-browser shim:
getAllAudioVideoDevices(function(result) {
if (result.allMdiaDevices.length) {
console.debug('Number of audio/video devices available:', result.allMdiaDevices.length);
}
if (result.allVideoDevices.length) {
console.debug('Number of video devices available:', result.allVideoDevices.length);
}
if (result.allAudioDevices.length) {
console.debug('Number of audio devices available:', result.allAudioDevices.length);
}
if (result.videoInputDevices.length) {
console.debug('Number of video-input devices available:', result.videoInputDevices.length);
}
if (result.audioInputDevices.length) {
console.debug('Number of audio-input devices available:', result.audioInputDevices.length);
}
if (result.audioOutputDevices.length) {
console.debug('Number of audio-output devices available:', result.audioOutputDevices.length);
}
if (result.allMdiaDevices.length && result.allMdiaDevices[0].label === 'Please invoke getUserMedia once.') {
console.warn('It seems you did not invoke navigator-getUserMedia before using these API.');
}
console.info('All audio input devices:');
result.audioInputDevices.forEach(function(device) {
console.log('Audio input device id:', device.id, 'Device label:', device.label);
});
console.info('All audio output devices:');
result.audioOutputDevices.forEach(function(device) {
console.log('Audio output device id:', device.id, 'Device label:', device.label);
});
console.info('All video input devices:');
result.videoInputDevices.forEach(function(device) {
console.log('Video input device id:', device.id, 'Device label:', device.label);
});
}, function(error) {
alert(error);
});
Solution 3:
It turns out that Chrome does support MediaStreamTrack API which allows you to do this. In Firefox this API is still experimental. Here is the Chrome implementation:
if (typeof MediaStreamTrack === 'undefined'){
alert('This browser does not support MediaStreamTrack.\n\nTry Chrome Canary.');
} else {
MediaStreamTrack.getSources( onSourcesAcquired);
}
function onSourcesAcquired(sources) {
for (var i = 0; i != sources.length; ++i) {
var source = sources[i];
// source.id -> DEVICE ID
// source.label -> DEVICE NAME
// source.kind = "audio" OR "video"
// TODO: add this to some datastructure of yours or a selection dialog
}
}
....
And then when calling getUserMedia, specify the id in the constraints:
var constraints = {
audio: {
optional: [{sourceId: selected_audio_source_id}]
},
video: {
optional: [{sourceId: selected_video_source_id}]
}
};
navigator.getUserMedia(constraints, onSuccessCallback, onErrorCallback);
Solution 4:
It sounds to me you are looking for facingMode
. You can check it out in this document:
http://www.w3.org/TR/2013/WD-mediacapture-streams-20130516/#idl-def-AllVideoCapabilities
Not sure how well it is supported yet though.