Современные браузеры позволяют выбирать устройства ввода и вывода, включая камеры, микрофоны и динамики.
Например:
- На телефоне выберите фронтальную или тыловую камеру.
- На ноутбуке выберите внутренние динамики или динамик, подключенный по Bluetooth.
- Для видеочата выберите внутренний или внешний микрофон или камеру.
Вся эта функциональность предоставляется объектом MediaDevices, который возвращается navigator.mediaDevices .
MediaDevices имеет два метода, оба реализованы в Chrome 47 на настольных компьютерах и Android: enumerateDevices() и getUserMedia() .

enumerateDevices()
Возвращает Promise, предоставляющий доступ к массиву объектов MediaDeviceInfo для доступных устройств.
Метод похож на MediaStreamTrack.getSources() , но в отличие от этого метода (который был реализован только в Chrome) он соответствует стандартам и включает устройства вывода звука. Вы можете попробовать это с помощью демонстраций ниже.
Вот немного упрощенный код из одной из демонстраций:
navigator.mediaDevices.enumerateDevices()
.then(gotDevices)
.catch(errorCallback);
...
function gotDevices(deviceInfos) {
...
for (var i = 0; i !== deviceInfos.length; ++i) {
var deviceInfo = deviceInfos[i];
var option = document.createElement('option');
option.value = deviceInfo.deviceId;
if (deviceInfo.kind === 'audioinput') {
option.text = deviceInfo.label ||
'Microphone ' + (audioInputSelect.length + 1);
audioInputSelect.appendChild(option);
} else if (deviceInfo.kind === 'audiooutput') {
option.text = deviceInfo.label || 'Speaker ' +
(audioOutputSelect.length + 1);
audioOutputSelect.appendChild(option);
} else if (deviceInfo.kind === 'videoinput') {
option.text = deviceInfo.label || 'Camera ' +
(videoSelect.length + 1);
videoSelect.appendChild(option);
}
...
}
Получив идентификаторы доступных устройств с помощью enumerateDevices() , вы можете использовать setSinkId() (определенный в API устройств вывода звука ) для изменения назначения вывода звука для видео- или аудиоэлемента:
element.setSinkId(sinkId)
.then(function() {
console.log('Audio output device attached: ' + sinkId);
})
.catch(function(error) {
// ...
});
Этот метод устанавливает выходное устройство для аудио из элемента. После вызова setSinkId() вы можете получить идентификатор текущего выходного аудиоустройства для элемента с помощью свойства sinkId .
получитьUserMedia()
Это заменяет navigator.getUserMedia() , но вместо использования обратного вызова возвращает Promise, который дает доступ к MediaStream . Разработчикам рекомендуется использовать MediaDevices.getUserMedia() , но нет никаких планов по удалению navigator.getUserMedia() : он остается частью спецификации .
Демоверсия доступна на сайте примеров WebRTC .
Вот фрагмент кода из демо:
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
var videoTracks = stream.getVideoTracks();
console.log('Got stream with constraints:', constraints);
console.log('Using video device: ' + videoTracks[0].label);
stream.onended = function() {
console.log('Stream ended');
};
window.stream = stream; // make variable available to console
video.srcObject = stream;
})
.catch(function(error) {
// ...
}
Поднятие флага
Метод enumerateDevices() в Chrome не имеет флагов, тогда как для MediaDevices.getUserMedia() вам все равно нужно включить функции экспериментальной веб-платформы в chrome://flags или использовать следующий флаг командной строки:
--enable-blink-features=GetUserMedia
Аналогично для setSinkId() : включите функции экспериментальной веб-платформы или используйте флаг:
--enable-blink-features=AudioOutputDevices
Более подробная информация о поддержке браузеров приведена ниже.
Будущее
Предложенный обработчик событий ondevicechange делает то, что заявлено: событие devicechange запускается, когда изменяется набор доступных устройств, и в обработчике можно вызвать enumerateDevices() , чтобы получить новый список устройств. Это пока не реализовано ни в одном браузере.
Проект Screen Capture — это расширение API Media Capture, которое предлагает метод MediaDevices.getDisplayMedia() , позволяющий использовать области дисплея пользователя в качестве источника медиапотока. Существует также предложение расширения MediaDevices для getSupportedConstraints() , которое предоставляет информацию о том, какие ограничения могут использоваться для вызова getUserMedia() : аудио- и видеовозможности, поддерживаемые браузером.
Демо
- получитьUserMedia()
- enumerateDevices():
- Прокладка MediaDevices
Узнать больше
- Сеть разработчиков Mozilla: Медиаустройства
- Статус реализации
- Захват мультимедиа и потоки. Редакторский черновик: MediaDevices
- API устройств вывода звука