借助 Screen Capture API,网页平台已支持共享标签页、窗口和屏幕。当 Web 应用调用 getDisplayMedia()
时,Chrome 会提示用户以 MediaStreamTrack
视频的形式与 Web 应用分享标签页、窗口或屏幕。
许多使用 getDisplayMedia()
的 Web 应用都会向用户显示所捕获表面的视频预览。例如,视频会议应用通常会将此视频流式传输给远程用户,同时将其渲染到本地 HTMLVideoElement
,以便本地用户始终看到自己分享的内容的预览。
本文档介绍了 Chrome 中的新 Captured Surface Control API,该 API 可让您的 Web 应用滚动捕获的标签页,以及读取和写入捕获的标签页的缩放级别。
为何要使用“捕获的表面控制”?
所有视频会议应用都存在相同的缺点。如果用户希望与捕获的标签页或窗口互动,则必须切换到该界面,这会使他们离开视频会议应用。这会带来一些挑战:
- 除非用户使用画中画或将视频会议标签页和共享标签页分别显示在并排的窗口中,否则无法同时看到捕获的应用和远程用户的视频源。在较小的屏幕上,这可能会比较困难。
- 用户需要在视频会议应用和捕获的界面之间来回切换,这会增加用户负担。
- 用户在离开视频会议应用时无法访问该应用公开的控件;例如,嵌入式聊天应用、表情符号反应、有关用户请求加入通话的通知、多媒体和布局控件,以及其他实用的视频会议功能。
- 演示者无法将控制权委托给远程参与者。这会导致一种非常常见的情况,即远程用户要求演示者更改幻灯片、上下滚动或调整缩放级别。
Captured Surface Control API 可解决这些问题。
如何使用捕获的表面控制功能?
成功使用捕获的 Surface 控制需要执行几个步骤,例如明确捕获浏览器标签页,并在能够滚动和缩放捕获的标签页之前获得用户许可。
捕获浏览器标签页
首先,提示用户使用 getDisplayMedia()
选择要共享的界面,并在该过程中将 CaptureController
对象与捕获会话相关联。我们很快就会使用该对象来控制捕获的表面。
const controller = new CaptureController();
const stream = await navigator.mediaDevices.getDisplayMedia({ controller });
接下来,以 <video>
元素的形式生成所捕获表面的本地预览:
const previewTile = document.querySelector('video');
previewTile.srcObject = stream;
如果用户选择共享窗口或屏幕,则目前不在我们的考虑范围内;但如果用户选择共享标签页,我们可能会继续。
const [track] = stream.getVideoTracks();
if (track.getSettings().displaySurface !== 'browser') {
// Bail out early if the user didn't pick a tab.
return;
}
权限提示
首次在给定的 CaptureController
对象上调用 forwardWheel()
、increaseZoomLevel()
、decreaseZoomLevel()
或 resetZoomLevel()
会生成权限提示。如果用户授予权限,则允许进一步调用这些方法。
需要用户手势才能向用户显示权限提示,因此,应用只有在已获得相应权限或响应用户手势(例如在 Web 应用中点击相关按钮)时,才应调用上述方法。click
滚动
使用 forwardWheel()
,捕获应用可以将来自捕获应用本身内源元素的滚轮事件转发到捕获标签页的视口。对于捕获的应用而言,这些事件与直接用户互动无法区分。
假设捕获应用使用名为 "previewTile"
的 <video>
元素,以下代码展示了如何将发送的滚轮事件中继到捕获的标签页:
const previewTile = document.querySelector('video');
try {
// Relay the user's action to the captured tab.
await controller.forwardWheel(previewTile);
} catch (error) {
// Inspect the error.
// ...
}
方法 forwardWheel()
采用单个输入,可以是以下任一内容:
- 一个 HTML 元素,滚轮事件将从该元素转发到捕获的标签页。
null
,表示应停止转发。
成功调用 forwardWheel()
会覆盖之前的调用。
在以下情况下,forwardWheel()
返回的 promise 可能会被拒绝:
- 如果捕获会话尚未开始或已停止。
- 如果用户未授予相关权限。
缩放
与所捕获标签页的缩放级别进行交互是通过以下 CaptureController
API 表面完成的:
getSupportedZoomLevels()
此方法会返回浏览器针对所捕获的 surface 类型支持的缩放级别列表。此列表中的值以相对于“默认缩放级别”(定义为 100%)的百分比表示。该列表单调递增,并且包含值 100。
此方法只能针对受支持的显示界面类型调用,目前仅适用于平板电脑。
如果满足以下条件,系统可能会调用 controller.getSupportedZoomLevels()
:
controller
与正在进行的拍摄相关联。- 捕获的是标签页。
否则,系统会引发错误。
调用此方法不需要 "captured-surface-control"
权限。
zoomLevel
此只读属性用于保存所捕获标签页的当前缩放级别。这是一个可为 null 的属性,如果捕获的表面类型没有有意义的缩放级别定义,则该属性的值为 null
。目前,缩放级别仅针对标签页定义,而不针对窗口或屏幕定义。
捕获结束后,该属性将保留最后的缩放级别值。
读取此属性"captured-surface-control"
不需要相应权限。
onzoomlevelchange
此事件处理脚本有助于监听所捕获标签页的缩放级别变化。这些情况可能发生在以下任一时间:
- 当用户与浏览器互动以手动更改所捕获标签页的缩放级别时。
- 响应捕获应用对缩放设置方法(如下所述)的调用。
读取此属性"captured-surface-control"
不需要相应权限。
increaseZoomLevel()
、decreaseZoomLevel()
和 resetZoomLevel()
这些方法可用于操纵捕获的标签页的缩放级别。
increaseZoomLevel()
和 decreaseZoomLevel()
分别将缩放级别更改为下一个或上一个缩放级别,具体取决于 getSupportedZoomLevels()
返回的顺序。resetZoomLevel()
将值设置为 100。
调用这些方法需要 "captured-surface-control"
权限。如果捕获应用不具备此权限,系统会提示用户授予或拒绝此权限。
这些方法都会返回一个 promise,如果调用成功,该 promise 会得到解决;否则,该 promise 会被拒绝。拒绝的原因可能包括:
- 缺少权限。
- 在开始捕获之前调用。
- 在捕获结束后调用。
- 在与不受支持的显示界面类型捕获相关的
controller
上调用。(即除了标签页捕获之外的任何内容)。 - 尝试分别增加或减少到超出最大值或最小值。
值得注意的是,如果 controller.zoomLevel == controller.getSupportedZoomLevels().at(0)
,建议避免调用 decreaseZoomLevel()
,并以类似方式使用 .at(-1)
来保护对 increaseZoomLevel()
的调用。
以下示例展示了如何让用户直接从捕获应用中提高所捕获标签页的缩放级别:
const zoomIncreaseButton = document.getElementById('zoomInButton');
zoomIncreaseButton.addEventListener('click', async (event) => {
if (controller.zoomLevel >= controller.getSupportedZoomLevels().at(-1)) {
return;
}
try {
await controller.increaseZoomLevel();
} catch (error) {
// Inspect the error.
// ...
}
});
以下示例展示了如何对捕获的标签页的缩放级别变化做出反应:
controller.addEventListener('zoomlevelchange', (event) => {
const zoomLevelLabel = document.querySelector('#zoomLevelLabel');
zoomLevelLabel.textContent = `${controller.zoomLevel}%`;
});
功能检测
如需检查是否支持 Captured Surface Control API,请使用:
if (!!window.CaptureController?.prototype.forwardWheel) {
// CaptureController forwardWheel() is supported.
}
同样,您也可以使用任何其他捕获的 SurfaceControl API Surface,例如 increaseZoomLevel
或 decreaseZoomLevel
,甚至可以检查所有这些 Surface。
浏览器支持
捕获的 SurfaceControl 仅适用于桌面设备上的 Chrome 136 及更高版本。
安全和隐私设置
借助 "captured-surface-control"
权限政策,您可以管理捕获应用和嵌入式第三方 iframe 如何访问捕获的 Surface 控件。如需了解安全方面的权衡取舍,请参阅“捕获的 Surface 控制”说明中的隐私和安全注意事项部分。
演示
您可以运行演示来试用捕获的表面控件。
反馈
Chrome 团队和 Web 标准社区希望了解您在使用捕获的 Surface 控制功能时的体验。
介绍一下设计
“捕获的表面捕获”功能是否未按预期运行?或者,是否有缺少的方法或属性需要您来实现自己的想法?对安全模型有疑问或意见?在 GitHub 代码库中提交规范问题,或在现有问题中添加您的想法。
实现存在问题?
您是否发现 Chrome 的实现存在 bug?或者实现是否与规范不同?请前往 https://new.crbug.com 提交 bug。请务必尽可能详细地说明问题,并提供重现说明。