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

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

François Beaufort
François Beaufort

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

하드웨어의 기능 감지는 익숙한 방식과 다릅니다. 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 사용자 프롬프트입니다.

반환된 promise는 사용자에게 카메라 동영상 스트림을 표시하는 데 사용되는 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 액세스 권한을 얻지 못합니다. 카메라 자체에서 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 페이지로 이동하여 '동영상 캡처' 탭의 '팬-틸트-줌' 열을 확인하세요. '팬 틸트' 및 '줌'은 각각 카메라가 '팬 틸트(절대값)' 및 '줌(절대값)' UVC 컨트롤을 지원함을 의미합니다. 'PanTilt (relative)' 및 '확대/축소 (상대)' UVC 컨트롤은 Chromium 기반 브라우저에서 지원되지 않습니다.

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

카메라 PTZ 제어

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

팬, 틸트, 줌 기능 및 설정은 카메라에서 지원되고 사용자가 카메라에 PTZ 권한을 부여한 경우에만 사용할 수 있습니다.

카메라 PTZ를 제어하는 중입니다.

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

  • PTZ 권한이 있는 카메라가 부여되지 않습니다.
  • 카메라 하드웨어가 PTZ 제약 조건을 지원하지 않습니다.
  • 페이지가 사용자에게 표시되지 않습니다. 페이지 가시성 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를 사용할 수 있는 기능은 주로 미디어 캡처 및 스트림 API와 동일한 권한 모델에 의해 제한됩니다. 사용자 메시지에 대한 응답으로 웹사이트는 페이지가 사용자에게 표시되는 경우에만 카메라 PTZ를 제어할 수 있습니다.

브라우저 호환성

MediaStream API

브라우저 지원

  • Chrome: 55
  • Edge: 12.
  • Firefox: 15.
  • Safari: 11.

소스

Permissions API

브라우저 지원

  • Chrome: 43.
  • Edge: 79.
  • Firefox: 46.
  • Safari: 16

소스

Page Visibility API

브라우저 지원

  • Chrome: 33.
  • Edge: 12.
  • Firefox: 18.
  • Safari: 7.

소스

MediaDevices.getUserMedia()

브라우저 지원

  • Chrome: 53.
  • Edge: 12.
  • Firefox: 36.
  • Safari: 11.

소스

MediaDevices.getSupportedConstraints()

브라우저 지원

  • Chrome: 53
  • Edge: 12.
  • Firefox: 44.
  • Safari: 11.

소스

MediaStreamTrack.applyConstraints()

브라우저 지원

  • Chrome: 59
  • Edge: 12.
  • Firefox: 43.
  • Safari: 11.

소스

MediaStreamTrack.getCapabilities()

브라우저 지원

  • Chrome: 59
  • Edge: 12.
  • Firefox: 132.
  • Safari: 11.

소스

MediaStreamTrack.getSettings()

브라우저 지원

  • Chrome: 59
  • Edge: 12.
  • Firefox: 50
  • Safari: 11.

소스

유용한 링크

감사의 말씀

이 도움말은 조 미들리토마스 스테인러가 검토했습니다. 사양 및 구현에 참여해 주신 Intel의 Rijubrata Bhaumik님과 Eero Häkkinen님께 감사드립니다. UnsplashChristina @ wocintechchat.com님 제공 히어로 이미지