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

François Beaufort
François Beaufort

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

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

区域截取简介

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

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

别那么快...你现在肯定不想将人们自己的视频传输回他们,对吧?最好剪掉该部分。但如何实现呢?嵌入的 iframe 不知道您展示了什么内容以及在何处展示,因此,如果没有一些帮助,它将无法剪裁图片。从理论上讲,您可以传递预期的坐标。但是,如果用户调整窗口大小,会怎么样?滚动视口?放大或缩小?以会导致布局更改的方式与网页互动?即使您向捕获 iframe 发送了新坐标,时间问题仍可能会导致一些画面被剪裁。

然后,我们使用“区域捕获”您的网页上有一个 Element(可能是 <div>),其中包含主要内容。我们将其命名为 mainContentArea。您希望视频会议 Web 应用远程截取并共享由此元素的边界框定义的区域。因此,您可以从 mainContentArea 派生出 CropTarget。您将此 CropTarget 传递给视频会议 Web 应用。使用此 CropTarget 剪裁视频轨道后,该轨道上的帧现在仅包含位于 mainContentArea 边界框内的像素。如果 mainContentArea 更改大小、形状或位置,视频轨道也会随之更改,而无需任何 Web 应用提供额外输入。

我们再来回顾一下这些步骤:

您可以在 Web 应用中定义 CropTarget,方法是调用 CropTarget.fromElement() 并将您选择的元素作为输入。

// 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 应用会使用从主 Web 应用收到的剪裁目标,对自拍视频轨道调用 cropTo(),以便让浏览器将轨道剪裁到 CropTarget 定义的区域。

// 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() 方法会在任何标签页截取视频轨道上公开,而不仅仅是自拍。因此,建议先检查用户是否选择了当前标签页,然后再尝试剪裁轨道。这可以使用捕获句柄来实现。您还可以使用 preferCurrentTab 指示浏览器提示用户进行自拍。

// Start cropping the self-capture video track using the CropTarget.
await track.cropTo(cropTarget);

如需还原为未剪裁状态,请使用 null 调用 cropTo()

// Stop cropping.
await track.cropTo(null);

遮挡内容和被遮挡的内容

对于区域截取,只有目标的坐标和大小起作用,z 轴顺序无关紧要。系统会捕获遮挡目标的像素。系统不会捕获目标的遮挡部分。

这是因为区域截取本质上就是剪裁。一种替代方案(未来将成为自己的 API)是元素级捕获;也就是说,仅捕获与目标关联的像素,而不管是否存在遮挡。与简单的剪裁相比,此类 API 具有一组不同的安全和隐私要求。

显示 Region Capture API 和 Element-level Capture API 的不同结果的图片。
区域截取在存在遮挡内容时的行为。

安全和隐私设置

借助区域截取功能,已经在观察标签页中所有像素的 Web 应用可以自行移除其中的部分像素。这非常安全,因为系统无法获取任何新信息。

“区域捕获”可用于限制向远程参与者发送哪些信息。例如,您可能希望分享某些幻灯片,但不分享演讲者备注。

包含幻灯片和演讲者备注的浏览器窗口的屏幕截图。
包含幻灯片和演讲者备注的 Web 应用。
强烈建议不要远程共享备注。提示区域捕获。

请注意,在本地,区域截取功能不会提供任何安全保证。将轨道交给其他文档后,接收文档仍可以取消剪裁轨道,并获得对所捕获标签页的所有像素的访问权限。

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

演示

您可以在 Glitch 上运行演示版,试用区域截取功能。请务必查看源代码

浏览器支持

浏览器支持

  • Chrome:104。
  • Edge:104。
  • Firefox:不受支持。
  • Safari:不受支持。

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

后续步骤

下面简要介绍了在未来如何改进网络屏幕共享功能,让您先睹为快:

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

反馈

Chrome 团队和 Web 标准社区希望了解您使用区域截图的体验。

向我们介绍设计

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

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

实现方面存在问题?

您是否发现了 Chrome 实现中的 bug?或者,实现是否与规范不同?

  • 请前往 https://new.crbug.com 提交错误。请务必提供尽可能多的细节信息,并提供关于重现错误的简单说明。Glitch 非常适用于分享轻松快速的重现问题。

表达支持

您打算使用区域截取功能吗?您的公开支持有助于 Chrome 团队确定各项功能的优先级,并向其他浏览器供应商展示支持这些功能的重要性。

@ChromiumDev 发推文,告诉我们您在哪里以及如何使用它。

致谢

感谢 Joe Medley 审核本文。