拍照及控制相機設定

Miguel Casas-Sanchez
François Beaufort
François Beaufort

Image Capture 是用於擷取靜止影像和設定相機硬體設定的 API。這個 API 適用於 Android 和電腦版 Chrome 59 以上版本。我們也發布了 ImageCapture polyfill 程式庫

這個 API 可讓您控制相機功能,例如縮放、亮度、對比、ISO 和白平衡。最重要的是,Image Capture 可讓您存取任何可用的裝置相機或網路攝影機的完整解析度功能。以往在網路上拍照時,會使用影片快照,但這類技術的解析度比靜態圖片低。

ImageCapture 物件會以 MediaStreamTrack 做為來源建構。此時,API 會提供兩種擷取方法 takePhoto()grabFrame(),以及擷取相機功能和設定,以及變更這些設定的方式。

施工

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);
}

您可以透過開發人員工具控制台試用這段程式碼。

擷取

拍攝方式有兩種:全景和快速快照。takePhoto() 會傳回 Blob,即單一曝光相片的結果,可供瀏覽器下載、儲存或顯示在 <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 操控「Live」相機功能和設定: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() 限制。

要繼續設定嗎?

試用版和程式碼範例

支援

  • Android 和電腦版 Chrome 59。
  • 在 Android 和桌上型電腦上使用 Chrome Canary 59 以下版本,並啟用實驗性網頁平台功能。

瞭解詳情