相机上的平移、倾斜和缩放功能终于可以在 Web 上控制了。
房间规模的视频会议解决方案部署了具有平移、倾斜和缩放 (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 权限的相机权限。

返回的 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
页面,并查看“视频捕获”选项卡中的“平移-倾斜-缩放”列;“平移倾斜”和“缩放”分别表示相机支持“PanTilt (Absolute)”和“Zoom (Absolute)”UVC 控件。基于 Chromium 的浏览器不支持“PanTilt (Relative)”和“Zoom (Relative)”UVC 控件。

控制相机 PTZ
使用先前获得的 stream
对象中的预览 MediaStreamTrack
来操作相机 PTZ 功能和设置。MediaStreamTrack.getCapabilities()
返回一个字典,其中包含支持的功能以及范围或允许的值。相应地,MediaStreamTrack.getSettings()
返回当前设置。
仅当相机支持并且用户已授予相机 PTZ 权限时,平移、倾斜和缩放功能和设置才可用。
使用适当的 PTZ 高级约束 调用 videoTrack.applyConstraints()
,以控制相机平移、倾斜和缩放,如下例所示。如果成功,返回的 Promise 将解析。否则,如果出现以下情况,它将拒绝:
- 未授予具有 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 功能时,这非常方便。请注意,此处不允许使用强制约束(min、max、exact)。
const stream = await navigator.mediaDevices.getUserMedia({
// Website asks to reset known camera pan.
video: { pan: 0, deviceId: { exact: "myCameraDeviceId" } }
});
Playground
您可以通过在 Glitch 上运行演示来使用 API。请务必查看源代码。
安全注意事项
规范作者在设计和实现此 API 时,采用了包括用户控制、透明度和人体工程学在内的核心原则。使用此 API 的能力主要受到与 Media Capture and Streams API 相同的权限模型的限制。响应用户提示,仅当页面对用户可见时,网站才允许控制相机 PTZ。
浏览器兼容性
MediaStream API
Permissions API
Page Visibility API
MediaDevices.getUserMedia()
MediaDevices.getSupportedConstraints()
MediaStreamTrack.applyConstraints()
MediaStreamTrack.getCapabilities()
MediaStreamTrack.getSettings()
实用链接
致谢
本文由 Joe Medley 和 Thomas Steiner 审阅。感谢 Intel 的 Rijubrata Bhaumik 和 Eero Häkkinen 在规范和实施方面所做的工作。题图由 Christina @ wocintechchat.com 在 Unsplash 上提供。