新知系列课程第二季来啦!我们将为大家带来全真互联时代下新的行业趋势、新的技术方向以及新的应用场景分享。本期,我们邀请到了云渲染终端技术负责人——陈焕,从终端视角为大家分享云渲染的两个应用场景及背后的技术。
首先是虚拟互动直播。我们先来看虚拟互动直播场景的案例。这是一个虚拟互动直播的场景,主播在直播一个云上运行的虚拟空间。他可以操控这个空间进行布局配置,并且有一个自己的虚拟形象,可以在空间中活动、打碟、主持全场。然后观众可以进入直播间观看。他可以进行传统的弹幕礼物互动,也可以点击“加入舞会”按钮,一键跳入虚拟空间。观众可以自定义虚拟形象,在空间里面随意的漫游、探索,沉浸式地参与这个活动。在虚拟空间里,观众可以跟主播进行现场面对面的互动。这种玩法比目前传统的弹幕礼物更有意思,并且随着虚拟空间内容的变化,未来还会有更多的想象空间。
下面我们来看一下这种虚拟互动直播是如何实现的。它背后其实是我们的腾讯云渲染平台。应用运行在云端,然后推流到直播系统。用户有三种角色,分别是主播、互动观众和直播观众。最左边的主播,通常是在PC上操作云端的应用,进行场景的设置,活动的控场。因为主播端有比较多的操作配置,在PC上会方便一些,当然他也可以选择在手机上操作。最右边的是直播观众,他从直播系统拉流观看。当他点击“加入舞会”按钮后,直播观众的角色就变为互动观众。这时,他其实是从直播系统切换到了云渲染平台,从云渲染串流观看。同时,他也可以上行指令去实时操作云端应用里自己的角色。
这里推流和直播系统,大家应该比较熟悉了。我主要给大家剖析一下云渲染这部分是如何实现的。
首先我们来定义一下什么是云渲染。云渲染是指在云端渲染3D应用,利用串流技术将画面实时推送到终端显示,并且让用户可以通过终端与云端应用进行实时的交互操作。它可以解决终端算力不足、用户需要提前安装配置复杂的软件、终端需要一次性采购,成本比较高等问题。
比如前面的云舞会的案例。如果要把云端的应用运行在主播本地电脑上,那主播就需要专门采购一台高配置的GPU机器,一次性投入的设备成本很大。而这种虚拟直播是活动形态的,并非每天24小时都在运行,专门采购设备,利用率不高,有空闲浪费的成本。互动观众端也类似,会有设备成本的问题,如果对终端的要求太高,不利于活动的传播。通过云渲染技术,主播、互动观众都只需要浏览器等轻客户端即可访问。同时,通过云渲染,多端互动玩法也更容易开发实现。可以理解为,实际上只需要一个单机游戏或者应用就可以做到互动。
要实现云渲染,关键是要做到低延迟的音视频传输和实时的交互操作。首先我们要确定的就是传输协议。常见的流媒体协议有RTMP、HTTP-FLV,还有LL-HLS、基于RTP的RTSP和WebRTC。前面的三个协议都是基于TCP传输的,延迟会比UDP大,实时性体验没那么好。第四个RTSP协议在Web上不支持,普适性没有那么好。我们希望用户在各种轻量的客户端上都能访问,特别是浏览器、小程序等重要的终端形态。所以,最合适云渲染的流媒体协议其实就是WebRTC。
在确定了WebRTC作为传输协议后,我们再看一下基于WebRTC的云渲染前后端交互流程。这里显示了三个核心的交互流程。第一个是客户端和云端建立连接。第二个是云端音视频数据如何串流到客户端进行显示。第三个是客户端操作指令如何上行给到云端应用。
我们先来看一下第一个流程。第一个流程就是WebRTC的建连过程。通过云渲染的调度后台作为信令服务器,双方交换STP信息,然后建立连接。这里建连的细节就不展开细讲了,可以看一下WebRTC的相关资料。
第二个流程显示了在建连之后云端应用经过渲染画面,然后采集、编码、传输到WebRTC媒体流轨道,之后终端JitterBuffer接收,再到解码、渲染,最后用户看到云端的画面。在这其中,编码这个环节,谷歌的WebRTC默认只支持了VP8、VP9,后来也支持了H.264,但还不支持H.265。我们拓展实现支持了H.265的编解码,提高了视频的压缩率,从而降低了对带宽的要求。在传输环节,我们通过否定应答和双向冗余纠错来处理丢包的问题。在重传上,我们进行了分级重传,根据包的优先级,I帧、P帧这些不同的优先级来进行优先的重传。在抖动和乱序问题上,我们通过JitterBuffer和NetEQ处理网络包的抖动和乱序。在拥塞问题上,我们主要是通过基于时延的带宽评估来调整发送端的控制策略,避免网络拥塞,同时通过动态码率、动态分辨率的动态编码策略来适应带宽,并通过Pacing平滑发送机制进行发送端的流控,避免拥塞。
第三个流程是客户端操作指令的上行。将操作指令通过文本方式描述,再通过WebRTC的数据通道传输到云端,由后台服务程序写入到系统的虚拟设备驱动程序里,这样应用就能够响应处理。云端系统上的鼠标、键盘、手柄、触摸屏、麦克风、摄像头这些设备都是虚拟的,只是有驱动程序可以进行交互。在客户端SDK上我们也提供了这些虚拟交互对象的接口。
在操作指令上行上,如果客户端是手机终端,云端的应用也是手机应用,那么我们需要做的就是把用户在终端屏幕上的点击、触摸事件进行坐标系的转换,因为客户端渲染的时候可能进行了本地视图的缩放旋转,所以需要将客户端的视图坐标系转换到视频流的坐标系,然后再转换到云端桌面的坐标系。如果客户端是手机终端,云端是PC应用,那一般还需要在手机屏幕上显示一些虚拟按钮,例如虚拟的鼠标、键盘、手柄给用户进行交互操作。所以我们还提供了手机客户端上的虚拟按键。
另外,除了这里显示的三个核心的流程,WebRTC是一个双向的端到端的通信协议。也就是说云端除了下行音视频数据,它也可以通过数据通道主动去下行文本数据,将云端的一些状态、事件告知客户端。客户端也可以上行音视频数据,例如通过新建媒体流轨道,采集手机上的摄像头、麦克风数据,上传到云端应用。这在一些应用场景上是很有用的。
接下来我们再简单看一下云渲染SDK的一些设计。从前面的交互流程也可以看到,SDK的功能主要包括管理会话的生命周期,管理数据通道、音视频流轨道,上行发送文本和音视频数据,下行接收文本和音视频数据,实现解码、渲染,提供与云端虚拟设备和云端应用交互的上层接口。设备接口包括键盘、鼠标、手柄、触摸屏、麦克风、摄像头等。
在渲染上,SDK的功能包括对渲染视图的本地缩放、旋转操作,本地触摸、划屏等操作到云端的映射,处理视图-视频-云端坐标系的转换。同时,我们还提供了一个可被应用集成的手机端自定义虚拟按键组件,包括鼠标、键盘、手柄的虚拟按键,可以可视化的编辑虚拟按键,并将编辑结果保存为配置文件,在APP中动态加载使用,降低了客户使用云渲染的开发成本。
另外,在安卓SDK的设计上,我们充分的考虑了包体积大小的问题,让客户应用的集成毫无压力。我们提供了完整版的SDK,也提供了轻量版的SDK加插件的集成方式。客户APP可以选择集成轻量版SDK,这个集成的体积增量只有65KB。运行时再从网络上下载SDK插件,进行动态加载。轻量版SDK只实现了渲染视图,屏幕触摸操作这些UI的逻辑,以及插件加载的逻辑,并定义了完整SDK接口。真正的实现以及WebRTC和编解码库,都在SDK插件里面。在SDK的维护上,SDK源码跟插件源码一起编译,就能生成完整版的SDK,给到不特别在意包大小体积的客户去接入。
以上就是从终端视角看到的云渲染的实现逻辑。
接下来我再分享一下云渲染的另一个应用场景——游戏微端。
用户在手机上安装一个游戏微端,游戏实际运行在云端。用户手机本地安装的微端其实只是一个云渲染的客户端。用户在微端上可以进行云游戏试玩,云端游戏里的登录和支付请求会同步到微端上,由微端拉起手机本地的微信/支付宝APP。在用户体验游戏内容的同时,微端会在后台静默下载完整游戏包,等下载完成后,用户只要重启微端,或者下次进入微端,就能热升级成完整的本地游戏包,无需进行覆盖安装的过程,具备良好的用户体验。这样就变成了本地游戏包,用户也就从云游切换到了本地游戏。
我们来看看微端背后的实现技术。首先我们给微端下个定义:微端是某款游戏专属的云游戏客户端。它可以让用户快速体验游戏,并且在玩云游戏的过程中,静默下载完整游戏包,无缝转化为本地游戏客户端。因为微端包的体积很小,所以很适合用来做游戏买量广告投放,降低获客成本,提高投放ROI。微端的商业模式在于买量市场的成本高昂,微端小包体能够带来整体投放和ROI的提升。举个例子,原游戏包体有800兆,接入微端后,投放包只要13兆。C端用户下载微端后,进行云游戏的试玩,再边玩边下载,最终转换成本地的游戏,效果很好。
这是微端涉及到的一些模块和他们之间的关系。客户只需要实现游戏APK(生成补丁包)、微端APK(用于广告投放,供C端用户玩云游戏)、云端APK(运行于云端的云游戏),其他模块都由腾讯云实现和提供。微端SDK、云端SDK,包括我们的微端云游戏业务后台、云游戏PaaS后台,还有我们的热更新SDK跟云游戏SDK,其实都是冰山下的内容,客户可以不用去理解,我们已经把它们封装好。
我们看一下微端的接入和运行流程。在接入流程上,主要有三个步骤。第一步是基于原始的游戏工程接入云端SDK,实现登录支付穿透的云端逻辑,生成云端APK,用于在云端运行,作为微端APP试玩的云游戏存在。如果你是游戏发行商角色,没有游戏工程源码,但是游戏APK里有集成了你的登录支付SDK,那么你也可以独立完成接入云端SDK生成云端APK,而无需游戏研发团队的介入。第二步是将游戏APK通过我们提供的工具一键转化为补丁包,用于给微端APP热升级使用。游戏APK可以是任意有效的安装包。第三步是基于腾讯云提供的微端demo工程,客户开发自己的业务逻辑,比如数据上报、登录支付穿透功能等,从而构建出来微端的APK用于广告投放。微端的demo工程初始化已经集成了微端的SDK。微端的通用应用逻辑都已经在SDK中实现了,APP模块留给客户开发自定义业务逻辑使用。
这个接入流程是极简单的,我们提供了完备的SDK、指南、Demo和工具。客户一次接入可以给多个游戏复用。构建出来的微观投放包体积很小,只有十几兆,可以提升投放效果,降低买量成本。
在运行时,用户先下载安装,使用微端试玩云游戏。依赖于前面介绍的云渲染技术,云游戏的体验已经接近本地游戏。云游戏也能使用本地原生的登录支付。同时,在试玩云游戏的过程中,会静默下载补丁包。这里我们也做了智能限速,不会影响云游戏的体验。在补丁包下载完成且重启后,微端将自动热更新为本地的游戏包。这个升级过程,用户是无感知的。
微端里面有两个主要的技术,一个是云渲染,一个是热更新。云渲染我前面已经介绍过了,这里我再讲一下热更新。一般手游的热更新是由游戏开发框架提供的。游戏的控制逻辑作为脚本资源存在,可以被动态加载,由代码解释器执行解释运行,所以可以做到在运行时,把代码作为资源下载到本地,然后动态的运行。但是微端APP只是一个轻量的云渲染客户端,在其中并没有任何游戏引擎或者游戏逻辑,如何能够升级成另外一个不相关的游戏APK呢?这里就用到了安卓的热更新技术。说白了就是动态加载。动态加载dex、so、资源。热更新对微端APP跟游戏APK的manifest会有一些限制要求,同时我们也处理了一些特殊的情况。
第一点,动态加载dex。因为系统启动微端APP,首先会加载微端APK里的第一个dex,调用第一个dex里的Application类,这也是开发者能够接触到的应用程序的主入口。我们需要在这个入口里动态加载补丁包里的所有dex,并把Application类生命周期的调用都反射调用到补丁包里的对应的Application类。这样我们就可以运行起补丁包里的代码逻辑。这里需要注意,dex存储在dexElement数组里面,加载的时候会从前往后去查找类。所以我们需要把补丁包里的dex插入到这个数组的最前面。以保证优先加载到补丁包里的类。由于安卓系统的碎片化比较严重,所以针对不同的Android版本,还有一些不同的厂商,我们对系统会有一些定制化的处理。
第二点动态加载so就比较简单。我们只需要把补丁包里解压出来的so的路径添加到系统查找so的路径里即可。
第三点动态加载资源,主要包括res跟asset这两个目录。这里主要是创建新的asset manager对象,通过反射调用他的一个asset path来加载补丁包里的资源。再把这个新的对象赋值给resource manager管理的resource对象,替换掉旧的指向规章APP里的asset manager对象。这样应用就能够通过resource接口访问到补丁包里的资源。
第四点,动态加载后对于系统而言,运行的仍然是微端的APP。系统里只注册了微端APP里面的Manifest信息,所以补丁包里的manifest文件里的安卓4大组件和权限声明等需要写入到微端APP的Manifest文件里。这样系统去调用四大组件才能够拉起补丁包里的四大组件。
第五点,Hack第三方so的行为。这里主要是因为我们发现Unity引擎的so会通过绝对路径去读取APK里的资源,而这个绝对路径不是安卓系统设计的预期的那个路径值。这里我们提供了两种可选的方式来修复或者解决这类场景。第一种是让客户选择去修改Unity的这个读取路径值,把它指向补丁包文件的路径。第二种是我们提供了一种更通用的可以去Hack任意so里的访问文件的系统函数的调用,重新定向到新函数后去修改将要访问的文件路径。其实就是修改了so加载到内存里之后的ELF信息,从而重定向了系统函数的调用。
在流程上,我们做了很多的一些工作,使得热更新虽然在逻辑上是侵入应用的,但我们可以在SDK内部去闭环,对接入的客户来说,做到无感知,也就降低了客户的接入门槛。上面就是微端热更新技术的主要原理剖析,这里面细节点非常多,今天只是讲了一些核心的理念或者核心的一些思路。
总之结合云渲染跟热更新,我们可以探索出微端这样一种新的应用形态。云渲染技术其实还有很多的应用场景,每一个场景背后可能涉及到的技术都有不同。以后有机会可以再和大家分享其他场景背后的技术。
关于新知
随着行业数字化转型加速,线上线下一体化、数字技术与真实世界融合的全真互联时代正加速到来。腾讯云音视频技术导师将在新知栏目中分享在全真互联时代下新的行业趋势、新的技术方向以及新的应用场景与大家共同探索视界,创见未来!
腾讯云音视频在音视频领域已有超过21年的技术积累,持续支持国内90%的音视频客户实现云上创新,独家具备 RT-ONE™ 全球网络,在此基础上,构建了业界最完整的 PaaS 产品家族,并通过腾讯云视立方 RT-Cube™ 提供All in One 的终端SDK,助力客户一键获取众多腾讯云音视频能力。腾讯云音视频为全真互联时代,提供坚实的数字化助力。