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

Miguel Casas-Sanchez
フランソワ ボーフォール
François Beaufort

画像キャプチャは、静止画像をキャプチャし、カメラのハードウェア設定を設定するための 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()Blob を返します。これは 1 回の露出結果で、ダウンロード、ブラウザで保存、または <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;
}

「Non-Live」カメラの機能と設定は、ImageCapture オブジェクトを介して操作します。ImageCapture.getPhotoCapabilities() は、PhotoCapabilities オブジェクトを返します。このオブジェクトは、「Non-Live」で使用可能なカメラ機能へのアクセスを提供します。これに対応して、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));

「Non-Live」カメラ設定は、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 版および 59 より前のパソコン版 Chrome Canary。

補足説明