webrtc-媒体-屏幕抓取

屏幕抓取

共享桌面的基本原理

共享桌面的基本原理其实非常简单,我们可以分“两头”来说明:

  • 共享者,每秒钟抓取多次屏幕(可以是 3 次、5 次等),每次抓取的屏幕都与上一次抓取的屏幕做比较,取它们的差值,然后对差值进行压缩;如果是第一次抓屏或切幕的情况,即本次抓取的屏幕与上一次抓取屏幕的变化率超过 80% 时,就做全屏的帧内压缩,其过程与 JPEG 图像压缩类似(有兴趣的可以自行学习)。最后再将压缩后的数据通过传输模块传送到观看端数据到达观看端后,再进行解码,这样即可还原出整幅图片并显示出来。

  • 远程控制端,当用户通过鼠标点击共享桌面的某个位置时,会首先计算出鼠标实际点击的位置,然后将其作为参数,通过信令发送给共享端。共享端收到信令后,会模拟本地鼠标,即调用相关的 API,完成最终的操作。一般情况下,当操作完成后,共享端桌面也发生了一些变化,此时就又回到上面共享者的流程了,我就不再赘述了。
    通过上面的描述,可以总结出共享桌面的处理过程为:抓屏、压缩编码、传输、解码、显示、控制这几步,你应该可以看出它与音视频的处理过程几乎是一模一样的

  • RDP(Remote Desktop Protocal)协议, Windows 系统下的共享桌面协议;

  • VNC(Virtual Network Console) 比较通用的远程桌面控制协议,可以实现在不同的操作系统上共享远程桌面,像 TeamViewer、RealVNC 都是使用的该协议

  • 桌面数据:包括了桌面的抓取 (采集)、编码(压缩)、传输、解码和渲染。

  • 信令控制:包括键盘事件、鼠标事件以及接收到这些事件消息后的相关处理等

WebRTC 使用的方式与 RDP/VNC 等真正的远程桌面协议的异同点

  1. 共享端桌面数据的采集
    WebRTC 对于桌面的采集与 RDP/VNC 使用的技术是相同的,都是利用各平台所提供的相关 API 进行桌面的抓取。以 Windows 为例,可以使用下列 API 进行桌面的抓取。

    • BitBlt:XP 系统下经常使用,在 vista 之后,开启 DWM 模式后,速度极慢。
    • Hook:一种黑客技术,实现稍复杂。
    • DirectX:由于 DirectX 9/10/11 之间差别比较大,容易出现兼容问题。最新的 WebRTC 都是使用的这种方式
    • GetWindowDC:可以通过它来抓取窗口。
  2. 共享端桌面数据的编码。

    • WebRTC 对桌面的编码使用的是视频编码技术,即 H264/VP8 等;好处是压缩率高,而坏处是在网络不好的情况下会有模糊等问题
    • RDP/VNC 则不一样,它们使用的是图像压缩技术
  3. 传输。
    编码后的桌面数据会通过流媒体传输协议发送到观看端。

    • WebRTC :当网络有问题时,数据是可以丢失的
    • RDP/VNC 来说,桌面数据一定不能丢失。
  4. 观看端解码。

    • WebRTC 对收到的桌面数据通过视频解码技术解码
    • RDP/VNC 使用的是图像解码技术
  5. 观看端渲染。WebRTC 与 RDP/VNC 一般都是会通过 OpenGL/D3D 等 GPU 进行渲染。

使用 webrtc 进行屏幕共享

getDisplayMedia MDN

var promise = navigator.mediaDevices.getDisplayMedia(constraints);

constraints (可选)
一个可选的 MediaStreamConstraints 对象,它指定了返回的 MediaStream 的要求。 因为 getDisplayMedia()需要视频轨道,所以即使 constraints 对象没有明确请求视频轨道,返回的流也会有一个

与 getUserMedia 类似,但是仅仅支持在 pc 上