从您的 Web 应用中选择摄像头、麦克风和扬声器

现代浏览器让您可以选择输入和输出设备,包括摄像头、麦克风和扬声器。

例如:

  • 在手机上,选择前置或后置摄像头。
  • 在笔记本电脑上,选择内部扬声器或通过蓝牙连接的扬声器。
  • 进行视频聊天时,可以选择内部或外部麦克风或摄像头。

所有此功能都通过 navigator.mediaDevices 返回的 MediaDevices 对象公开。

MediaDevices 有两个方法,在桌面设备和 Android 上的 Chrome 47 中都实现了: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() 检索到可用设备的 ID 后,您可以使用 setSinkId()(在 Audio Output Devices API 中定义)来更改视频或音频元素的音频输出目的地:

element.setSinkId(sinkId)
    .then(function() {
    console.log('Audio output device attached: ' + sinkId);
    })
    .catch(function(error) {
    // ...
    });

此方法为元素中的音频设置输出设备。调用 setSinkId() 后,您可以使用 sinkId 属性获取元素当前输出音频设备的 ID。

getUserMedia()

这将替换 navigator.getUserMedia(),但不会使用回调,而是返回一个提供对 MediaStream 的访问权限的 Promise。我们鼓励开发者使用 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():启用实验性 Web 平台功能或使用标志:

--enable-blink-features=AudioOutputDevices

下文详细介绍了浏览器支持。

未来展望

我们提议的 ondevicechange 事件处理脚本就行了:当可用设备集发生变化时会触发 devicechange 事件,并且您可以在处理程序中调用 enumerateDevices() 来获取新的设备列表。尚未在任何浏览器中实现此功能。

Screen Capture 草稿是对 Media Capture API 的扩展,它提出了一个 MediaDevices.getDisplayMedia() 方法,该方法可让用户的屏幕区域被用作媒体流的来源。此外,还有针对 getSupportedConstraints()MediaDevices 扩展提案,其中提供了有关可用于 getUserMedia() 调用的限制条件的信息:浏览器支持的音频和视频功能。

样本歌曲

了解详情