控制相機的平移、傾斜和縮放功能

相機的平移、傾斜和縮放功能終於可以在網路上控制。

法蘭索瓦博福特
François Beaufort

大規模視訊會議解決方案會部署具備平移、傾斜和縮放 (PTZ) 功能的攝影機,讓軟體將攝影機鏡頭對準會議參與者。自 Chrome 87 版起,凡是使用 MediaDevices.getUserMedia()MediaStreamTrack.applyConstraints() 中媒體追蹤限制的網站,都可以使用相機的平移、傾斜和縮放功能。

使用 API

功能偵測

硬體的功能偵測與您可能習慣的功能不同。navigator.mediaDevices.getSupportedConstraints() 中存在 "pan""tilt""zoom" 限制名稱,就代表瀏覽器支援 API 可控制攝影機 PTZ,但相機硬體是否支援這類名稱。自 Chrome 87 版起,電腦支援控制相機 PTZ,但 Android 仍僅支援縮放功能。

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

要求相機 PTZ 存取權

只有當使用者已透過提示明確授予相機具有 PTZ 權限時,網站才能控制攝影機 PTZ。

如要要求相機 PTZ 存取權,請呼叫 navigator.mediaDevices.getUserMedia() 並指定 PTZ 限制,如下所示。這會提示使用者以 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 (絕對值)」和「縮放 (絕對值)」以 Chromium 為基礎的瀏覽器不支援「PanTilt (Relative)」和「Zoom (Relative)」 UVC 控制項。

ChromeOS 內部頁面螢幕截圖,用來對 PTZ 相機支援進行偵錯。
用於對 PTZ 相機支援進行偵錯的內部頁面。

控制攝影機 PTZ

透過先前取得的 stream 物件中的預覽 MediaStreamTrack,操作相機 PTZ 功能和設定。MediaStreamTrack.getCapabilities() 會傳回字典,其中包含支援的功能以及範圍或允許的值。因此,MediaStreamTrack.getSettings() 會傳回目前的設定。

只有在相機支援平移、傾斜和縮放功能,且使用者授予相機權限時,才能使用平移、傾斜和縮放功能與設定。

控制相機 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...
}

如要設定相機平移、傾斜和縮放,您也可以呼叫 navigator.mediaDevices.getUserMedia() 並搭配部分相機 PTZ 理想限制值。如果預先知道相機 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 的 Rijubrata BhaumikEero Häkkinen 努力在規格和實作方面投注心力。主頁橫幅由 Christina @ wocintechchat.comUnsplash 上提供。