카메라 이동, 기울이기, 확대/축소를 제어합니다.

이제 카메라의 화면 이동, 기울이기 및 확대/축소 기능을 웹에서도 제어할 수 있습니다.

프랑수아 보포르
프랑수아 보퍼

회의실 규모의 화상 회의 솔루션은 화면 이동, 기울이기, 확대/축소(PTZ) 기능이 있는 카메라를 배포하여 소프트웨어가 회의 참석자를 가리키도록 합니다. Chrome 87부터 MediaDevices.getUserMedia()MediaStreamTrack.applyConstraints()에서 미디어 트랙 제약 조건을 사용하는 웹사이트에서 카메라의 화면 이동, 기울이기, 확대/축소 기능을 사용할 수 있습니다.

API 사용

기능 감지

하드웨어의 기능 감지는 흔히 사용하는 것과 다릅니다. navigator.mediaDevices.getSupportedConstraints()"pan", "tilt", "zoom" 제약 조건 이름이 있으면 브라우저에서 카메라 PTZ를 제어하는 API를 지원하지만 카메라 하드웨어가 이를 지원하는지는 알 수 없습니다. Chrome 87부터 카메라 PTZ 제어는 데스크톱에서 지원되지만 Android는 여전히 확대/축소만 지원합니다.

const supports = navigator.mediaDevices.getSupportedConstraints();
if (supports.pan && supports.tilt && supports.zoom) {
  // Browser supports camera PTZ.
}

카메라 PTZ 액세스 요청

사용자가 메시지를 통해 PTZ 권한으로 카메라를 명시적으로 부여한 경우에만 웹사이트에서 카메라 PTZ를 제어할 수 있습니다.

카메라 PTZ 액세스를 요청하려면 아래와 같이 PTZ 제약 조건과 함께 navigator.mediaDevices.getUserMedia()를 호출합니다. 이렇게 하면 일반 카메라와 PTZ 권한이 있는 카메라를 모두 부여하라는 메시지가 사용자에게 표시됩니다.

macOS용 Chrome의 카메라 PTZ 사용자 메시지 스크린샷
카메라 PTZ 사용자 메시지

반환된 프로미스는 사용자에게 카메라 동영상 스트림을 표시하는 데 사용되는 MediaStream 객체로 확인됩니다. 카메라가 PTZ를 지원하지 않으면 사용자에게 일반 카메라 메시지가 표시됩니다.

try {
  // User is prompted to grant both camera and PTZ access in a single call.
  // If camera doesn't support PTZ, it falls back to a regular camera prompt.
  const stream = await navigator.mediaDevices.getUserMedia({
    // Website asks to control camera PTZ as well without altering the
    // current pan, tilt, and zoom settings.
    video: { pan: true, tilt: true, zoom: true }
  });

  // Show camera video stream to user.
  document.querySelector("video").srcObject = stream;
} catch (error) {
  // User denies prompt or matching media is not available.
  console.log(error);
}

이전에 부여된 카메라 권한, 특히 PTZ 액세스가 없는 카메라 권한은 PTZ 액세스 권한이 부여되어도 자동으로 부여되지 않습니다. 이는 카메라 자체가 PTZ를 지원하는 경우에도 마찬가지입니다. 권한을 다시 요청해야 합니다. 다행히 Permissions API를 사용하여 PTZ 권한 상태를 쿼리하고 모니터링할 수 있습니다.

try {
  const panTiltZoomPermissionStatus = await navigator.permissions.query({
    name: "camera",
    panTiltZoom: true
  });

  if (panTiltZoomPermissionStatus.state == "granted") {
    // User has granted access to the website to control camera PTZ.
  }

  panTiltZoomPermissionStatus.addEventListener("change", () => {
    // User has changed PTZ permission status.
  });
} catch (error) {
  console.log(error);
}

Chromium 기반 브라우저에서 카메라에 PTZ를 지원하는지 알아보려면 내부 about://media-internals 페이지로 이동하여 '동영상 캡처' 탭의 '화면-기울기-확대/축소' 열을 확인하세요. '화면 이동'과 '확대/축소'는 각각 카메라가 'PanTilt (절대적)' 및 '확대/축소 (절대적)' UVC 컨트롤을 지원한다는 의미입니다. Chromium 기반 브라우저에서는 'PanTilt (Relative)' 및 'Zoom (Relative)' UVC 컨트롤이 지원되지 않습니다.

PTZ 카메라 지원을 디버그하기 위한 ChromeOS의 내부 페이지 스크린샷
PTZ 카메라 지원을 디버그하는 내부 페이지

카메라 PTZ 제어

앞서 가져온 stream 객체의 미리보기 MediaStreamTrack를 사용하여 카메라 PTZ 기능 및 설정을 조작합니다. MediaStreamTrack.getCapabilities()는 지원되는 기능과 범위 또는 허용 값이 포함된 사전을 반환합니다. 이에 따라 MediaStreamTrack.getSettings()는 현재 설정을 반환합니다.

화면 이동, 기울이기, 확대/축소 기능과 설정은 카메라에서 지원되고 사용자가 카메라에 PTZ 권한을 부여한 경우에만 사용할 수 있습니다.

카메라 PTZ 제어

아래 예와 같이 적절한 PTZ 고급 제약 조건과 함께 videoTrack.applyConstraints()를 호출하여 카메라 화면 이동, 기울기, 확대/축소를 제어합니다. 성공하면 반환된 프로미스가 해결됩니다. 그렇지 않으면 다음 중 하나에 해당하는 경우 거부됩니다.

  • PTZ 권한이 있는 카메라가 부여되지 않음
  • 카메라 하드웨어가 PTZ 제약 조건을 지원하지 않습니다.
  • 페이지가 사용자에게 표시되지 않습니다. Page Visibility API를 사용하여 페이지 공개 상태 변경을 감지합니다.
// Get video track capabilities and settings.
const [videoTrack] = stream.getVideoTracks();
const capabilities = videoTrack.getCapabilities();
const settings = videoTrack.getSettings();

// Let the user control the camera pan motion if the camera supports it
// and PTZ access is granted.
if ("pan" in settings) {
  const input = document.querySelector("input[type=range]");
  input.min = capabilities.pan.min;
  input.max = capabilities.pan.max;
  input.step = capabilities.pan.step;
  input.value = settings.pan;

  input.addEventListener("input", async () => {
    await videoTrack.applyConstraints({ advanced: [{ pan: input.value }] });
  });
}

if ("tilt" in settings) {
  // similar for tilt...
}
if ("zoom" in settings) {
  // similar for zoom...
}

일부 카메라 PTZ의 이상적인 제약 조건 값으로 navigator.mediaDevices.getUserMedia()를 호출하여 카메라 화면 이동, 기울기, 확대/축소를 구성할 수도 있습니다. 이는 카메라 PTZ 기능을 미리 알고 있는 경우 편리합니다. 참고로 필수 제약조건 (최소, 최대, 일치)은 허용되지 않습니다.

const stream = await navigator.mediaDevices.getUserMedia({
  // Website asks to reset known camera pan.
  video: { pan: 0, deviceId: { exact: "myCameraDeviceId" } }
});

플레이그라운드

Glitch에서 데모를 실행하여 API를 사용해 볼 수 있습니다. 소스 코드를 확인하세요.

보안 고려사항

사양 작성자는 사용자 제어, 투명성, 인체공학과 같은 핵심 기능을 사용하여 이 API를 설계하고 구현했습니다. 이 API를 사용하는 기능은 주로 Media Capture and Streams API와 동일한 권한 모델로 관리됩니다. 사용자 프롬프트에 따라 웹사이트에서는 페이지가 사용자에게 표시될 때만 카메라 PTZ를 제어할 수 있습니다.

브라우저 호환성

MediaStream API

브라우저 지원

  • 55
  • 12
  • 15
  • 11

소스

Permissions API

브라우저 지원

  • 43
  • 79
  • 46
  • 16

소스

페이지 공개 상태 API

브라우저 지원

  • 33
  • 12
  • 18
  • 7

소스

MediaDevices.getUserMedia()

브라우저 지원

  • 53
  • 12
  • 36
  • 11

소스

MediaDevices.getSupportedConstraints()

브라우저 지원

  • 53
  • 12
  • 44
  • 11

소스

MediaStreamTrack.applyConstraints()

브라우저 지원

  • 59
  • 12
  • 43
  • 11

소스

MediaStreamTrack.getCapabilities()

브라우저 지원

  • 59
  • 12
  • x
  • 11

소스

MediaStreamTrack.getSettings()

브라우저 지원

  • 59
  • 12
  • 50
  • 11

소스

유용한 링크

감사의 말

Joe MedleyThomas Steiner가 작성한 도움말입니다. 사양 및 구현 작업을 위해 노력해 주신 Intel의 리주브라타 바우믹에로 해키넨님께 감사드립니다. UnsplashChristina @ wocintechchat.com의 히어로 이미지입니다.