ウェブアプリからカメラ、マイク、スピーカーを選択する

最新のブラウザでは、カメラ、マイク、スピーカーなどの入出力デバイスを選択できます。

次に例を示します。

  • スマートフォンで、前面カメラまたは背面カメラを選択します。
  • ノートパソコンで、内蔵スピーカーまたは Bluetooth で接続されたスピーカーを選択します。
  • ビデオチャットの場合は、内蔵または外付けのマイクまたはカメラを選択します。

この機能はすべて、navigator.mediaDevices によって返される MediaDevices オブジェクトによって公開されます。

MediaDevices には enumerateDevices()getUserMedia() という 2 つのメソッドがあり、どちらもパソコン版と Android 版の Chrome 47 で実装されています。

オーディオ出力デバイスの選択

enumerateDevices()

使用可能なデバイスの MediaDeviceInfo オブジェクトの配列へのアクセス権を付与する Promise を返します。

このメソッドは MediaStreamTrack.getSources() に似ていますが、これまで Chrome に実装されていたメソッドとは異なり、標準に準拠しており、オーディオ出力デバイスが含まれています。以下のデモで試すことができます。

このデモの 1 つを簡略化してコードを示します。

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) {
    // ...
    }

旗を放棄する顔

Chrome の enumerateDevices() メソッドは「フラグレス」ですが、MediaDevices.getUserMedia() については、chrome://flags で試験運用版のウェブ プラットフォーム機能を有効にするか、次のコマンドライン フラグを使用する必要があります。

--enable-blink-features=GetUserMedia

setSinkId() の場合: 試験運用版のウェブ プラットフォーム機能を有効にするか、フラグを使用します。

--enable-blink-features=AudioOutputDevices

ブラウザ サポートの詳細については、以下をご覧ください。

今後の計画

提案された ondevicechange イベント ハンドラは、その内容を実行します。つまり、使用可能な一連のデバイスが変更されたときに devicechange イベントが発行され、ハンドラ内で enumerateDevices() を呼び出して新しいデバイスリストを取得できます。この API はまだどのブラウザにも実装されていません。

Screen Capture draftは Media Capture API の拡張機能で、ユーザー ディスプレイの領域をメディア ストリームのソースとして使用できるようにする MediaDevices.getDisplayMedia() メソッドを提案します。また、getSupportedConstraints() に対する MediaDevices 拡張機能の提案もあります。これは、getUserMedia() 通話に使用できる制約(ブラウザでサポートされている音声機能と動画機能)に関する情報を提供します。

デモ

補足説明