写真の撮影とカメラ設定の制御

Image Capture は、静止画像をキャプチャし、カメラのハードウェア設定を構成する API です。この API は、Android とパソコンの Chrome 59 で利用できます。また、ImageCapture ポリフィル ライブラリも公開されています。

この API を使用すると、ズーム、明るさ、コントラスト、ISO、ホワイト バランスなどのカメラ機能を制御できます。何より、画像キャプチャでは、使用可能なデバイスのカメラやウェブカメラのフル解像度機能にアクセスできます。ウェブ上で写真を撮影する従来の手法では、動画のスナップショットが使用されていましたが、静止画像で利用できる解像度よりも低い解像度でした。

ImageCapture オブジェクトは、ソースとして MediaStreamTrack を使用して作成されます。この API には、takePhoto()grabFrame() の 2 つのキャプチャ メソッドがあり、カメラの機能と設定を取得して設定を変更する方法も用意されています。

工事

Image Capture API は、getUserMedia() から取得した MediaStreamTrack を介してカメラにアクセスします。

navigator.mediaDevices.getUserMedia({video: true})
    .then(gotMedia)
    .catch(error => console.error('getUserMedia() error:', error));

function gotMedia(mediaStream) {
    const mediaStreamTrack = mediaStream.getVideoTracks()[0];
    const imageCapture = new ImageCapture(mediaStreamTrack);
    console.log(imageCapture);
}

このコードは DevTools コンソールから試すことができます。

撮影

キャプチャは、全フレームとクイック スナップショットの 2 つの方法で行うことができます。takePhoto()Blob1 回の露光の結果)を返します。これはブラウザによってダウンロード、保存、または <img> 要素に表示できます。この方法では、利用可能な最高のカメラ解像度が使用されます。次に例を示します。

const img = document.querySelector('img');
// ...
imageCapture.takePhoto()
    .then(blob => {
    img.src = URL.createObjectURL(blob);
    img.onload = () => { URL.revokeObjectURL(this.src); }
    })
    .catch(error => console.error('takePhoto() error:', error));

grabFrame()ImageBitmap オブジェクト(ライブ動画のスナップショット)を返します。このオブジェクトは、たとえば <canvas に描画してから、ポストプロセッシングで色値を選択的に変更できます。ImageBitmap には動画ソースの解像度のみが含まれます。通常、この解像度はカメラの静止画機能よりも低くなります。次に例を示します。

const canvas = document.querySelector('canvas');
// ...
imageCapture.grabFrame()
    .then(imageBitmap => {
    canvas.width = imageBitmap.width;
    canvas.height = imageBitmap.height;
    canvas.getContext('2d').drawImage(imageBitmap, 0, 0);
    })
    .catch(error => console.error('grabFrame() error:', error));

機能と設定

キャプチャ設定を操作する方法はいくつかあります。変更を MediaStreamTrack に反映するか、takePhoto() 後にのみ表示するかによって異なります。たとえば、zoom レベルの変更は MediaStreamTrack にすぐに反映されますが、赤目補正は、設定されている場合でも、写真の撮影時にのみ適用されます。

「ライブ」カメラの機能と設定は、プレビュー MediaStreamTrack を介して操作されます。MediaStreamTrack.getCapabilities() は、サポートされている具体的な機能と範囲または許可された値(サポートされているズーム範囲や許可されたホワイトバランス モードなど)を含む MediaTrackCapabilities ディクショナリを返します。それに応じて、MediaStreamTrack.getSettings() は具体的な現在の設定を含む MediaTrackSettings を返します。ズーム、明るさ、トーチモードは、このカテゴリに属します。例:

var zoomSlider = document.querySelector('input[type=range]');
// ...
const capabilities = mediaStreamTrack.getCapabilities();
const settings = mediaStreamTrack.getSettings();
if (capabilities.zoom) {
    zoomSlider.min = capabilities.zoom.min;
    zoomSlider.max = capabilities.zoom.max;
    zoomSlider.step = capabilities.zoom.step;
    zoomSlider.value = settings.zoom;
}

「ライブ以外の」カメラ機能と設定は ImageCapture オブジェクトを介して操作されます。ImageCapture.getPhotoCapabilities() は、利用可能な「ライブ以外の」カメラ機能にアクセスできる PhotoCapabilities オブジェクトを返します。それに伴い、Chrome 61 以降では、ImageCapture.getPhotoSettings() は具体的な現在の設定を含む PhotoSettings オブジェクトを返します。写真の解像度、赤目補正、フラッシュ モード(トーチを除く)は、このセクションに該当します。たとえば、次のような項目があります。

var widthSlider = document.querySelector('input[type=range]');
// ...
imageCapture.getPhotoCapabilities()
    .then(function(photoCapabilities) {
    widthSlider.min = photoCapabilities.imageWidth.min;
    widthSlider.max = photoCapabilities.imageWidth.max;
    widthSlider.step = photoCapabilities.imageWidth.step;
    return imageCapture.getPhotoSettings();
    })
    .then(function(photoSettings) {
    widthSlider.value = photoSettings.imageWidth;
    })
    .catch(error => console.error('Error getting camera capabilities and settings:', error));

構成

「ライブ」カメラの設定は、プレビュー MediaStreamTrackapplyConstraints() 制約で構成できます。次に例を示します。

var zoomSlider = document.querySelector('input[type=range]');

mediaStreamTrack.applyConstraints({ advanced: [{ zoom: zoomSlider.value }]})
    .catch(error => console.error('Uh, oh, applyConstraints() error:', error));

「非ライブ」カメラの設定は、takePhoto() のオプションの PhotoSettings ディクショナリで構成されます。次に例を示します。

var widthSlider = document.querySelector('input[type=range]');
imageCapture.takePhoto({ imageWidth : widthSlider.value })
    .then(blob => {
    img.src = URL.createObjectURL(blob);
    img.onload = () => { URL.revokeObjectURL(this.src); }
    })
    .catch(error => console.error('Uh, oh, takePhoto() error:', error));

カメラの機能

上記のコードを実行すると、grabFrame() の結果と takePhoto() の結果のディメンションに違いがあることがわかります。

takePhoto() メソッドを使用すると、カメラの最大解像度にアクセスできます。

grabFrame() は、レンダラ プロセス内の MediaStreamTrack で使用可能な次の VideoFrame を取得するだけですが、takePhoto()MediaStream を中断し、カメラを再構成して写真を撮影します(通常は圧縮形式で、そのため Blob です)。その後、MediaStreamTrack を再開します。つまり、takePhoto() はカメラの静止画像のフル解像度機能にアクセスできることを意味します。これまでは、動画をソースとして使用し、canvas 要素で drawImage() を呼び出すことでのみ「写真を撮る」ことができました(こちらの例を参照)。

詳細については、README.md のセクションをご覧ください。

このデモでは、<canvas> のサイズは動画ストリームの解像度に設定されていますが、<img> の自然サイズはカメラの最大静止画解像度です。もちろん、両方のディスプレイサイズの設定には CSS を使用します。

静止画像で使用可能なカメラ解像度の全範囲は、PhotoCapabilities.imageHeightimageWidthMediaSettingsRange 値を使用して取得および設定できます。getUserMedia() の最小幅と最大幅、高さの制約は動画用であり、前述のように静止画像のカメラ機能とは異なる場合があります。つまり、getUserMedia() からキャンバスに保存するときに、デバイスのフル解像度機能にアクセスできない場合があります。WebRTC の解像度制約デモでは、解像度の getUserMedia() 制約を設定する方法を示しています。

さらに設定を続けますか?

  • Shape Detection API は画像キャプチャと連携して動作します。grabFrame() を繰り返し呼び出して、ImageBitmapFaceDetector または BarcodeDetector にフィードできます。API の詳細については、Paul Kinlan のブログ投稿をご覧ください。

  • カメラ フラッシュ(デバイスライト)には PhotoCapabilitiesFillLightMode からアクセスできますが、懐中電灯モード(フラッシュが常にオン)には MediaTrackCapabilities からアクセスできます。

デモとコードサンプル

サポート

  • Android 版とパソコン版の Chrome 59。
  • 試験運用版ウェブ プラットフォーム機能が有効になっている Android 版およびパソコン版の Chrome Canary 59 以前。

補足説明