利用区域拍摄功能更好地分享标签页

François Beaufort
François Beaufort

Web 平台已允许 Web 应用捕获当前标签页的视频轨道。现在,它随附了区域捕获功能,可用于剪裁这些视频轨道。Web 应用将当前标签页的一部分指定为感兴趣的区域,浏览器会裁剪该区域之外的所有像素。

以前,Web 应用可以“手动”裁剪视频轨道。也就是说,Web 应用可以直接操纵每个帧。这种方法既不稳健,也不高效。区域捕获功能可解决这些缺点。现在,Web 应用可以指示浏览器代表其执行工作。

区域捕获功能简介

您创建了一个包含 Dynamic Content™ 的网站。这是有史以来最好的 Web 应用,用户根本停不下来,而且经常会协同使用。下一步可能是嵌入虚拟会议功能。您决定采用这种方法。您与现有的视频会议服务提供商合作,将他们的 Web 应用嵌入为跨源 iframe。视频会议 Web 应用会将当前标签页捕获为视频轨道,并将其传输给远程参会者。

浏览器窗口的屏幕截图,其中显示了一个突出显示了主要内容区域和跨源 iframe 的 Web 应用。
主要内容区域为蓝色,跨源 iframe 为红色。

别急…您肯定不想将用户自己的视频回传给他们,对吧?最好将该部分裁剪掉。但如何实现呢?嵌入的 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 的安全性和隐私保护要求与简单的裁剪不同。

显示区域捕获和元素级捕获 API 的不同结果的图片。
在内容被遮挡的情况下,区域捕获的行为。

安全和隐私设置

区域捕获功能允许已在观察标签页中所有像素的 Web 应用自愿移除其中的一些像素。这种方法显然是安全的,因为无法获得任何新信息。

您可以使用区域捕获功能来限制发送给远程参与者的信息。例如,您可能想分享一些幻灯片,但不分享演讲者备注。

屏幕截图:包含幻灯片和演讲者备注的浏览器窗口。
包含幻灯片和演讲者备注的 Web 应用。
远程分享备注非常不理想。提示区域捕获。

请注意,在本地,区域捕获不会添加任何安全保证。将轨道移交给另一个文档时,接收文档仍然可以取消裁剪轨道,并访问所捕获标签页的所有像素。

Chrome 会在捕获的标签页边缘绘制蓝色边框。裁剪时,Chrome 通常会在裁剪目标周围绘制蓝色边框。

演示

您可以运行演示来试用区域捕获功能。

浏览器支持

Browser Support

  • Chrome: 104.
  • Edge: 104.
  • Firefox: not supported.
  • Safari: not supported.

Source

区域捕获功能仅适用于桌面版 Chrome 104 及更高版本。

后续步骤

以下是即将推出的功能,可改善网页上的屏幕共享体验:

  • 区域捕获将支持捕获其他标签页。
  • 有条件聚焦将允许捕获 Web 应用指示浏览器将焦点切换到捕获的显示表面,或避免此类焦点更改。
  • 可能会提供元素级捕获 API

反馈

Chrome 团队和 Web 标准社区希望了解您使用区域捕获功能的体验。

介绍一下设计

区域捕获功能是否未按预期运行?或者,是否有缺少的方法或属性需要您来实现自己的想法?对安全模型有疑问或意见?

  • GitHub 代码库中提交规范问题,或在现有问题中添加您的想法。

实现存在问题?

您是否发现 Chrome 的实现存在 bug?还是实现与规范不同?

显示支持

您是否计划使用区域捕获?您的公开支持有助于 Chrome 团队确定功能的优先级,并向其他浏览器供应商展示支持这些功能的重要性。

请向 @ChromiumDev 发送推文,告诉我们您在何处以及如何使用该功能。

致谢

感谢 Joe Medley 审阅本文。