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 应用会使用从主 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 具有一组不同的安全和隐私要求。
安全和隐私设置
借助区域截取功能,已经在观察标签页中所有像素的 Web 应用可以自行移除其中的部分像素。这非常安全,因为系统无法获取任何新信息。
区域捕获功能可用于限制向远程参与者发送的信息。例如,您可能希望分享某些幻灯片,但不分享演讲者备注。
请注意,在本地,区域截取功能不会提供任何安全保证。将轨道交给其他文档后,接收文档仍可以取消剪裁轨道,并获得对所捕获标签页的所有像素的访问权限。
Chrome 会在截取的标签页边缘绘制蓝色边框。剪裁时,Chrome 通常会在剪裁的目标周围绘制蓝色边框。
演示
您可以在 Glitch 上运行演示版,试用区域截取功能。请务必查看源代码。
浏览器支持
浏览器支持
区域截图功能仅适用于 Chrome 104 桌面版。
后续步骤
下面简要介绍了我们即将推出的一系列功能,它们将改进网页上的屏幕共享体验:
反馈
Chrome 团队和 Web 标准社区希望了解您使用区域截图的体验。
请说明设计
区域截取功能是否未按预期运行?或者,您是否缺少实现想法所需的方法或属性?对安全模型有疑问或意见?
- 在 GitHub 代码库中提交规范问题,或在现有问题中添加您的想法。
实现方面存在问题?
您是否发现了 Chrome 实现中的 bug?或者实现与规范不同?
- 请访问 https://new.crbug.com 提交 bug。请务必提供尽可能详细的信息,并附上简单的重现说明。故障非常适合分享快速简便的重现步骤。
表达支持
您打算使用区域截取功能吗?您的公开支持有助于 Chrome 团队确定功能的优先级,并向其他浏览器供应商表明支持这些功能的重要性。
向 @ChromiumDev 发推文,告诉我们您在哪里以及如何使用它。
实用链接
致谢
感谢 Joe Medley 审核本文。