我一直不太赞同在演示的同时共享屏幕。大家进入视频会议应用程序,跟大家打招呼,然后开始分享自己在另一个标签或窗口的ppt。那你要看什么呢?ppt吗?但我更想面对观众并与其互动。确实,有些工具可以让你预览所分享的内容,但你仍然需要来回滑动每张ppt。理应采用一个更好的办法,那就是capture handle。
Capture Handle是origin trial中一个用于屏幕共享(getDisplayMedia)的新的API。它可以让屏幕共享app识别,与用户选择的标签相协调。
Elad Alon是一位对接webrtc.org团队的谷歌员工。他负责整理capture handle规范,并推动其通过W3C的标准化过程。
在这篇文章中,Elad向我们介绍了capture handle,并列举了一些关于防止“镜室 (hall of mirrors)效应”的例子。另外他也回答了我在文章开头所说,屏幕共享时切换幻灯片的问题。capture handle也有很多其他用途。下面会对此进行详述。
在过去的一年里,屏幕共享逐渐成为大家生活中必不可少的一部分。其原因自然不言而喻。对于基于Web的产品,该操作通常是通过调用getDisplayMedia来实现的。一旦getDisplayMedia被调用,浏览器就会向用户展示他们自己的媒体选择器。
目前,该API允许捕获三种不同的界面展示选项——屏幕、窗口或标签。用户拥有该选择权。(这种选择可能受到用户选择的浏览器的限制。比如Firefox还不支持标签捕捉,而Safari只提供全屏捕捉。)
getDisplayMedia返回一个Promise。当用户做出选择后,Promise被解决,应用程序可以开始使用返回的MediaStream,该stream有一个视频轨道,可能还有一个音频轨道。但是,应用程序还能较容易地发现捕获界面的哪些内容呢?为什么需要应用程序这样做呢?让我们来解决这两个问题。
识别捕获的显示界面
以前,应用程序只能区分屏幕/窗口/标签捕获。
- 对于Safari来说确实是这样,因为它只支持屏幕捕捉。
- Chrome允许通过MediaTrackSettings.displaySurface查询捕获街面。
- Firefox以MediaStreamTrack.label的形式公开了捕获窗口的标题。屏幕捕捉会指定一个特殊的字符串,比如“Primary Monitor”。
所以,并没有标准的方法来真正识别捕获的web应用。被捕获的标签是一个YouTube视频?还是一个演示文稿?如果是演示文稿的话,它又来自哪个应用呢?如果捕获的应用程序和被捕获的应用程序甚至不能识别对方,那么它们如何进行协作?是否应该通过嵌入二维码的方式进行隐写?
输入“Capture Handle”。让我们看几个示例来说明Capture Handle如何工作。
检测自我抓取
我们可以从最简单的Capture Handle示例讲起——一个单一标签(应用程序里预期是两个)。设想现在有一个将捕获的视频呈现给本地用户的应用程序。自我捕获会导致镜厅效应。
如果web应用能够检测到这一点,它就可以避免将视频回放给本地用户,从而避免令人不适的这种效果。
const TOTALLY_RANDOM_ID = “42”; // Or actually randomize... const ownId = TOTALLY_RANDOM_ID; // Set the capture handle of the web application. navigator.mediaDevices.setCaptureHandleConfig( { handle: ownId, permittedOrigins: ["*"] } ); // ... const stream = await navigator.mediaDevices.getDisplayMedia(); const [track] = stream.getVideoTracks(); // Check to see if the captured tab has the same handle. const isSelfCapture = track.getCaptureHandle && track.getCaptureHandle() && track.getCaptureHandle().handle == ownId; // Then mitigate the hall-of-mirrors as you see fit, // e.g. hide the element using CSS.
在这种情况下,Web应用程序可以很轻易地在当前标签上设置一个ID。然后这个captureHandle().handle可以用来检查用户是否在屏幕共享选择器中选择了他们自己的标签。
点击此处,你可以看到这个概念的完整演示。
引导协作
如果一个应用程序可以识别它正在捕获的应用程序,它就可以与之协作。它们之间无论使用多传统的方法,都可以进行消息交流,并添加包括任何种类的语义。例如,一个VC应用可以远程控制幻灯片。
如需观看演示请点击此处。请注意,它是由一个C++开发人员制作的,并不是一个web开发人员。TL;DR是指,被捕获的应用程序设置一个handle,而捕获的应用程序从中提取会话ID。可以想象一个名为Slides 3000的幻灯片web应用程序:
//////////////////////////////////////// // Captured application (Slides 3000) // //////////////////////////////////////// function getLoonySessionId() { ... // Returns some ID which is meaningful using loonyAPI. } function onPageLoaded() { // Expose and add info as you like, including the origin. ... setCaptureHandleConfig({ exposeOrigin: true, handle: JSON.stringify({ description: "See slides-3000.com for our API.", protocol: "loonyAPI", version: "1.983", sessionId: getLoonySessionId(), }), permittedOrigins = ['*'] }); ... }
和一个名为VC-MAX的视频通话web应用:
//////////////////////////////////// // Capturing application (VC-MAX) // //////////////////////////////////// async function startCapture() { // ... const stream = await navigator.mediaDevices.getDisplayMedia(); const [track] = stream.getVideoTracks(); if (track.getCaptureHandle) { // Feature detection. // Subscribe to notifications of the capture-handle changing. track.oncapturehandlechange = (event) => { onNewCaptureHandle(event.captureHandle()); }; // Read the current capture-handle. onNewCaptureHandle(track.getCaptureHandle()); } ... } function onNewCaptureHandle(captureHandle) { if (captureHandle.origin == 'slides-3000.com') { const parsed = JSON.parse(captureHandle.handle); onNewSlides300Session(parsed.protocol, parsed.version, parsed.sessionId); } } function onNewSlides300Session(protocol, version, sessionId) { if (protocol != "loonyAPI" || version > "2.02") { return; } // Exposes prev/next buttons to the user. When clicked, these send // a message to some REST API, where |sessionId| indicates that the // message has to be relayed to the Slides 3000 session in question. ExposeSlides300Controls(sessionId); }
选择你自己的信令
capture handle可以提供识别,但并不提供通信。它并不涉及两个标签之间如何交换消息。你可以设想是BroadcastChannel,或者共享云基础设施被启用,即信令服务器(在比通常使用WebRTC情景更广泛的情况里)。所有合理的通信手段都有一个共同特点——它们要求捕获者知道被捕获的应用程序的ID,而这正是capture handle所能提供的。
这为开发者实现其应用提供了方式上的灵活性。比如,如果用户打开多个幻灯片标签,多个标签是否都会被指示翻到下一张幻灯片呢?不可思议!
使用capture handle优化capture参数
假设有两个用户,一个用户正在和朋友分享一个1080p的预告片,提议大家一起看这部电影。另一个用户正在向同事们展示一个基本都是静态的文件。这两个用户都使用了同一种视频通话应用程序来分享另一个标签。那么在这两个capture场景中,是否应该使用相同的帧率和分辨率呢?
将来,可以直接提示内容类型的机制才是主流。但作为现在的一种权宜之计,Capture Handle能帮助用户检查标签的来源是否是已知的视频服务网站、已知的生产力套装等。然后,应用程序就可以设置帧速率、分辨率属性以及contentHint了。
Capture Handle何时能用?
从M92版开始,Chrome进行Capture Handle origin trial。
M92版和M93版相比,API有细微差别:
除此之外,Chrome目前没有计划进行额外的修改。如果有,我们可以在变更日志中找到。然而,我们确实在计划进行一项扩展,将该API扩展到窗口级capture。
Chrome浏览器正在收集公共web开发人员的支持意见,以说服其他浏览器供应商了解这一功能的重要性。
原文作者:Elad Alon