사진 촬영 및 카메라 설정 제어

이미지 캡처는 스틸 이미지를 캡처하고 카메라 하드웨어 설정을 구성하는 API입니다. 이 API는 Android 및 데스크톱의 Chrome 59에서 사용할 수 있습니다. ImageCapture polyfill 라이브러리도 게시되었습니다.

API를 사용하여 확대/축소, 밝기, 대비, ISO, 화이트 밸런스와 같은 카메라 기능을 제어할 수 있습니다. 무엇보다도 이미지 캡처를 사용하면 사용 가능한 모든 기기 카메라나 웹캠의 전체 해상도 기능에 액세스할 수 있습니다. 이전에 웹에서 사진을 찍는 기술에서는 스틸 이미지보다 해상도가 낮은 동영상 스냅샷을 사용했습니다.

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

DevTools 콘솔에서 이 코드를 사용해 볼 수 있습니다.

촬영하기

캡처는 두 가지 방법, 즉 전체 프레임과 빠른 스냅샷으로 수행할 수 있습니다. 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()<canvas>에 그린 다음 후처리하여 색상 값을 선택적으로 변경할 수 있는 라이브 동영상의 스냅샷ImageBitmap 객체를 반환합니다. 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에 관한 자세한 내용은 폴 킨란의 블로그 게시물을 참고하세요.

  • 카메라 플래시 (기기 조명)는 PhotoCapabilitiesFillLightMode를 통해 액세스할 수 있지만 토치 모드 (계속 플래시 켜짐)는 MediaTrackCapabilities에서 찾을 수 있습니다.

데모 및 코드 샘플

지원

  • Android 및 데스크톱에서 실행되는 Chrome 59
  • 실험용 웹 플랫폼 기능이 사용 설정된 59 이전 버전의 Android 및 데스크톱에서 실행되는 Chrome Canary

자세히 알아보기