Web 平台已允许 Web 应用捕获当前标签页的视频轨道。现在,它随附了区域捕获功能,可用于剪裁这些视频轨道。Web 应用将当前标签页的一部分指定为感兴趣的区域,浏览器会裁剪该区域之外的所有像素。
以前,Web 应用可以“手动”裁剪视频轨道。也就是说,Web 应用可以直接操纵每个帧。这种方法既不稳健,也不高效。区域捕获功能可解决这些缺点。现在,Web 应用可以指示浏览器代表其执行工作。
区域捕获功能简介
您创建了一个包含 Dynamic Content™ 的网站。这是有史以来最好的 Web 应用,用户根本停不下来,而且经常会协同使用。下一步可能是嵌入虚拟会议功能。您决定采用这种方法。您与现有的视频会议服务提供商合作,将他们的 Web 应用嵌入为跨源 iframe。视频会议 Web 应用会将当前标签页捕获为视频轨道,并将其传输给远程参会者。

别急…您肯定不想将用户自己的视频回传给他们,对吧?最好将该部分裁剪掉。但如何实现呢?嵌入的 iframe 不知道您公开了哪些内容以及公开在何处,因此在没有帮助的情况下无法进行裁剪。从理论上讲,您可以传递预期坐标。但如果用户调整窗口大小,会发生什么情况?滚动视口?放大还是缩小?以产生布局变化的方式与网页互动?即使您将新坐标发送到捕获 iframe,时间安排问题仍可能会导致一些画面裁剪错误。
那么,我们来使用区域截图功能。您的网页上有一个 Element
(可能是 <div>
),其中包含主要内容。我们将其命名为 mainContentArea
。您希望视频会议 Web 应用远程捕获并分享此元素的边界框所定义的区域。因此,您从 mainContentArea
派生出 CropTarget
。您将此 CropTarget
传递给视频会议 Web 应用。使用此 CropTarget
裁剪视频轨道后,该轨道上的帧现在仅包含 mainContentArea
的边界框内的像素。如果 mainContentArea
更改大小、形状或位置,视频轨道会随之移动,而无需来自任一 Web 应用的任何额外输入。
我们再来回顾一下这些步骤:
您可以通过调用 CropTarget.fromElement()
并将所选元素作为输入,在 Web 应用中定义 CropTarget
。
// In the main web app, associate mainContentArea with a new CropTarget
const mainContentArea = document.querySelector("#mainContentArea");
const cropTarget = await CropTarget.fromElement(mainContentArea);
您将 CropTarget
传递给视频会议 Web 应用。
// Send the CropTarget to the video conferencing web app.
const iframe = document.querySelector("#videoConferenceIframe");
iframe.contentWindow.postMessage(cropTarget);
视频会议 Web 应用通过调用 cropTo()
,要求浏览器将轨道裁剪到 CropTarget
定义的区域,并使用从主 Web 应用收到的裁剪目标。
// In the embedded video conferencing web app, ask the user for permission
// to start capturing the current tab.
const stream = await navigator.mediaDevices.getDisplayMedia({
preferCurrentTab: true,
});
const [track] = stream.getVideoTracks();
// Start cropping the self-capture video track using the CropTarget
// received over window.onmessage.
await track.cropTo(cropTarget);
// Enjoy! Transmit remotely the cropped video track with RTCPeerConnection.
Et voilà!大功告成。
深入探究
功能检测
如需检查是否支持 CropTarget.fromElement()
,请使用:
if ("CropTarget" in self && "fromElement" in CropTarget) {
// Deriving a target is supported.
}
派生 CropTarget
我们重点介绍一下名为 mainContentArea
的元素。如需从中派生 CropTarget
,请调用 CropTarget.fromElement(mainContentArea)
。如果成功,返回的 Promise 将解析为新的 CropTarget
对象。否则,如果您铸造了数量不合理的 CropTarget
对象,系统会拒绝您的请求。
const mainContentArea = document.querySelector("#mainContentArea");
const cropTarget = await CropTarget.fromElement(mainContentArea);
与 Element
不同,CropTarget
对象是可序列化的。例如,可以使用 Window.postMessage()
将其传递给另一个文档。
剪裁
在捕获标签页时,视频轨道会实例化为 BrowserCaptureMediaStreamTrack
,它是 MediaStreamTrack
的子类。该子类公开了 cropTo()
。调用 track.cropTo(cropTarget)
以开始裁剪为 mainContentArea
(从中派生出 cropTarget 的元素)的轮廓。
如果成功,当可以保证所有后续视频帧都将包含位于 mainContentArea
的边界框内的像素时,Promise 将得到解析。
如果失败,Promise 将被拒绝。如果出现以下情况,就会发生这种情况:
CropTarget
是在另一个标签页中铸造的。(目前是这样,敬请期待。)CropTarget
派生自不再存在的元素。- 轨道有克隆。(请参阅问题 1509418。)
- 当前轨道不是自拍视频轨道;请参阅下文。
cropTo()
方法在任何标签页捕获视频轨道上公开,而不仅仅是用于自行捕获。因此,建议在尝试裁剪轨道之前,先检查用户是否选择了当前标签页。可以使用 Capture Handle 来实现此目的。您还可以使用 preferCurrentTab
提示用户进行自拍。
// Start cropping the self-capture video track using the CropTarget.
await track.cropTo(cropTarget);
如需恢复到未裁剪状态,请使用 null
调用 cropTo()
。
// Stop cropping.
await track.cropTo(null);
遮挡内容和被遮挡内容
对于区域捕获,只有目标的位置和大小重要,z-index 不重要。系统会捕获遮挡目标的像素。目标被遮挡的部分将不会被捕获。
这是因为区域捕获本质上是裁剪。另一种替代方案(未来将成为自己的 API)是元素级捕获;也就是说,无论遮挡情况如何,都只捕获与目标关联的像素。此类 API 的安全性和隐私保护要求与简单的裁剪不同。

安全和隐私设置
区域捕获功能允许已在观察标签页中所有像素的 Web 应用自愿移除其中的一些像素。这种方法显然是安全的,因为无法获得任何新信息。
您可以使用区域捕获功能来限制发送给远程参与者的信息。例如,您可能想分享一些幻灯片,但不分享演讲者备注。

远程分享备注非常不理想。提示区域捕获。
请注意,在本地,区域捕获不会添加任何安全保证。将轨道移交给另一个文档时,接收文档仍然可以取消裁剪轨道,并访问所捕获标签页的所有像素。
Chrome 会在捕获的标签页边缘绘制蓝色边框。裁剪时,Chrome 通常会在裁剪目标周围绘制蓝色边框。
演示
您可以运行演示来试用区域捕获功能。
浏览器支持
区域捕获功能仅适用于桌面版 Chrome 104 及更高版本。
后续步骤
以下是即将推出的功能,可改善网页上的屏幕共享体验:
反馈
Chrome 团队和 Web 标准社区希望了解您使用区域捕获功能的体验。
介绍一下设计
区域捕获功能是否未按预期运行?或者,是否有缺少的方法或属性需要您来实现自己的想法?对安全模型有疑问或意见?
- 在 GitHub 代码库中提交规范问题,或在现有问题中添加您的想法。
实现存在问题?
您是否发现 Chrome 的实现存在 bug?还是实现与规范不同?
- 请访问 https://new.crbug.com 提交 bug。请务必尽可能详细地说明问题,并提供简单的重现说明。
显示支持
您是否计划使用区域捕获?您的公开支持有助于 Chrome 团队确定功能的优先级,并向其他浏览器供应商展示支持这些功能的重要性。
请向 @ChromiumDev 发送推文,告诉我们您在何处以及如何使用该功能。
实用链接
致谢
感谢 Joe Medley 审阅本文。