摘要:动态PPT使用场景日益增多,如何在云端录制中支持录制完整动态PPT效果成为一项越来越迫切的需求。
文|即构云端录制引擎团队
在远程会议、在线教育场景中,使用具备动画效果的动态PPT可以快速引起观看者的兴趣,通过在PPT内添加丰富的动画效果和音、视频内容,也可以让观众快速理解主讲人所表达的观点。
随着在远程互动中使用动态PPT的场景日益增多,在云端录制中支持录制动态PPT越来越成为一项迫切需求,本篇文章就基于Chromium浏览器进行云端动态PPT录制技术进行探讨。
本文共四部分:
-
动态PPT图像采集
-
音频数据采集
-
同步动态PPT交互效果
-
白板图元的录制
一、动态PPT图像采集
在远程共享文件时,动态PPT会经过转码生成HTML页面,所以如果要采集PPT内容画面就需要在启动浏览器进行渲染,这里我们选择的是开源的Chromium浏览器,所以在介绍采集环节之前,我们先来了解一下Chromium的渲染原理。
- Chromium渲染原理
Chromium的渲染引擎是Blink,渲染会经历以下5个阶段:
1、首先,网页的内容被解析后会被Blink存储为节点对象树(称为DOM 树)。节点对象树用于将页面上的每个 HTML 元素以及元素之间的文本和对应的节点进行关联。
2、引擎中的GraphicsContext负责将像素写入最终显示到屏幕上的位图中,为了能让其知道如何绘制每一个节点,要将输出的 DOM 树中的每个节点都生成相应的Render Object(渲染对象)Render Object知道如何绘制对应节点中的内容,渲染对象存储在一个与节点对象树平行的树结构中,称为渲染树。
3、为了能够正确显示重叠的内容、半透明的元素,以及CSS变换等,需要引入RenderLayer(渲染层)的概念,含有特定行为(根对象,透明等)的渲染对象都会创建一个RenderLayer并与之对应。RenderLayer也形成了一个树层次结构。根节点是页面中根元素对应的RenderLayer,每个节点的后代都是视觉上包含在父层中的层,每个渲染层节点都会进行Z轴的排序。
4、虽然理论上每个单独的RenderLayer都可以将自己绘制到一个单独的backing surface上,但实际上这在内存(尤其是 VRAM)方面可能会非常浪费。所以在进入合成器之前,要对其进行复用,并引入GraphicsLayers(图形层),图形层对应一个或多个渲染层。每个图形层都有一个 GraphicsContext 用于绘制与之关联的渲染层绘制,合成器最终负责在随后的合成过程中将 GraphicsContexts 的位图输出组合成最终的屏幕图像。总之,逻辑上含有四个平行的树结构,分别为:节点对象树,渲染对象树,渲染层树,图形层树,结构如下图所示。
5、将前面生成的图形层进行格式的转换和抽像后,交由合成器(compositor),合成器经历两个阶段:1.绘制,2.合成。经过这两个过程后合成器将不同层级以及不同部分的图像进行重叠合成,光栅化,绘制等操作输出到显示设备中,如果是软件光栅化则生成位图,否则会生成纹理,在Chromium 75版本后,合成器被单独分离到viz进程中(GPU Process),具体的合成简化模型如下图所示,当采用软件渲染时,GL_framebuffer将会变为SoftwareOutputDevice。
- 页面数据采集
通过了解Chromium的渲染流程其实我们就可以很明显的发现,我们只需要拿到OutputSurface里面的纹理或者位图,即可进行采集到动态PPT的画面进行录制,Chromium对此也有很方便API接口,可以通过Chromium的跨进程类相关接口访问共享内存的图像数据,完成页面的采集。
二、音频数据采集
除里页面采集的相关接口,Chromium还提供了访问音频数据的接口AudioLoopbackStreamCreator来创建,使用media :: AudioCapturerSource :: CaptureCallback回调来接收音频参数和音频数据进行音频方面的录制。
三、同步动态PPT页面进程交互
通过前面两步我们已经可以采集到动态PPT的图像、房间内的音频了,对于动态PPT来讲,还需要同步动态PPT效果。
我们通过后台信令,使用Chromium的C++和JavaScript通信完成,当渲染进程启动时我们向Chromium注册上下文对象,可以很方便的进行进程间通信。
四、白板图元的录制
白板图元指的是在白板上绘制的图形数据,通常在共享PPT之后,避免不了要对PPT上内容进行绘制、标注,因此需要支持对动态PPT上的标注录制。
我们在接收后台同步信令后进行绘制,最后通过局部脏区刷新,转换坐标矩阵,图像优化最终以极低的性能开销将白板图元合成到动态PPT的图像之中,并确保可以完美还原上课情况。
总结
云端录制动态PPT本质上是通过内嵌浏览器将采集数据进程修改并录制下来,由于录制是在服务端,所以对录制的稳定性和性能具有要较大的考验,我们在实践中进行的大量改进优化,使其具备高度稳定性,并将其封装在云端录制API之中,开发者通过极小的工作量就可以快速集成并拥有此功能。