Flutter是近两年比较火的一个跨终端框架。因为疫情,实时音视频越来越多地融入到人们的日常工作和生活中,比如在线会议、教育等,两者的结合又能碰撞出怎样的火花呢?使用Flutter实时音视频SDK,我们可以快速开发跨平台的会议、娱乐、教育等APP。LiveVideoStackCon2021北京站邀请到腾讯云高级工程师牛赞,与我们分享如何使用Flutter进行实时音视频渲染,深入底层优化视频渲染性能。文字|牛瓒整理|LiveVideoStack我来自腾讯云音视频。本次分享的主题是音视频前端跨平台技术应用。2015年加入腾讯,先后负责王者荣耀、英雄联盟竞猜、QQ会员等业务,目前负责腾讯云实时音视频TRTC前端技术研发.1、为什么跨平台技术首先需要跨平台框架?因为它可以在理想条件下实现一次开发,多端运行,组件互通,提高效率。对于管理人员来说,可以降低人力成本,无需单独组建IOS和Android团队。对于开发者来说,可以降低学习成本,只需要了解一套跨平台的框架,就可以实现双端开发,提升自身的商业价值。跨平台技术发展的主要阶段如下:第一阶段——HybridAPP,核心原理是封装原生接口暴露给JS。业务运行在外部应用中,背靠庞大的前端生态,开发迭代速度非常快。缺点是能力受调整层限制,扩展性弱,Webview体现的性能较差。第二阶段——2015年,Facebook推出ReactNative。最核心的变化是摒弃了低效的Webview渲染,改用Native控件,由系统绘制。优点是用户可以使用前端开发系统(一个庞大的React系统),而且由于渲染交给系统来绘制,性能比Webview更好。但缺点是渲染时需要和Native通信。当用户处于通信频繁的场景时,处理不当会导致卡顿。ReactNative底层使用JS语言,只能使用JIT即时编译,性能与Native端有一定差距。第三阶段——2018年,谷歌推出Flutter。一套代码可以同时构建多平台应用。它支持热重载以实现高效的开发工作。底层使用Dart语音,支持JIT编译和AOT编译。渲染引擎skia,性能基本可以达到原生水平。对比F??lutter和ReactNative的流行趋势,数据来自statisa、github、stackoverflow。可以发现,Flutter的流行趋势已经超越了ReactNative,成为跨平台领域最流行的跨平台技术方案。图为Flutter的架构图。绿色部分是Flutter的Framework,是一个用Dart实现的UISDK。从上到下包括两大组件库、基础组件库、图形绘制、手势识别、动画等功能。其中两个组件是库实现了基于IOS和MaterialUI风格的UI组件,使UI开发更加灵活。蓝色部分是Flutter的核心Engine,实现了Flutter渲染引擎、Dart虚拟机、Platform通信通道、时间通知、插件架构等功能。Platform通信通道特性应用于SDK接口的封装,也用于Flutter和Native的异步消息传递。整个过程中的消息发送和响应采用异步方式,避免阻塞UI界面。Flutter引擎已经完成了桥接通道,用户只需要在通信层编写IOS/Android底层代码,就可以直接在FlutterDart中使用。2.TRTCFlutterSDK架构设计图展示了FlutterSDK架构。SDK基于原生IOS/Android封装,可直接对接原生SDK,最大限度的利用已有的音视频采集、编解码等能力。在设计框架的过程中,我们实现了以下几点:优化数据通信能力:由于Flutter与原生SDK通信的消息通道只支持基本类型等简单技术,优化数据通信能力可以使其支持更复杂的。技术类型。将实验层设计得更具可扩展性:考虑到Flutter未来会支持更多的平台,这样的设计方便以后扩展更多的平台。整合美颜、设备、音频相关API:让开发者更方便的使用腾讯云的API。优化视频渲染能力:GPU性能基本达到原生SDK水平。上段提到Flutter通信和native通信只支持基本数据类型,这会带来以下挑战:如何实现复杂类结构的传递?如何在Flutter和原生SDK之间高效传输图片?Flutter没有类似原生平台的系统视图组件,如何渲染视频?API接口众多,如何帮助开发者快速接入?下面将详细讨论这四个问题。Flutter的本质是Dart调用Native接口,异步返回Native数据。原生SDK中有大量类结构的类型定义。比如进房界面有TRTCParams,定义了应用ID、用户ID、用户密钥等相关信息。由于原来的消息通道不支持这种结构的传递,所以我们的通信能力进行了升级。首先,将Flutter定义的类结构转换为Map对象,对其进行JSON序列化,底层消息通道将传输数据高效序列化为二进制传输。通信层接收到数据后进行反序列化,转换成对应的JAVA类结构,再传输给原生SDK。类结构可以约束参数和校验类型,方便开发者及早发现问题,提高易用性。在直播场景中,有时需要给视频加水印(比如左上图右下角的熊猫水印)。直播过程中,为视频设置水印等接口,需要将Flutter项目定义的图片资源调用到原生SDK中。Flutter内置了图片资源管理机制,底层SDK只能识别一个Bitmap位图对象。问题是Flutter没有Bitmap这个数据类型,那么如何将Flutter项目的图片资源转换成原生SDK需要的Bitmap呢??首先,使用应用程序的文档目录(Flutter和Android都可以访问)。上端提到Flutter自带了一套图??片资源管理机制,所以方法是在Flutter层把它的图片资源拷贝到文档目录下,然后把图片文件地址传给通讯层,收到地址后,通信层将其解析为Android原生SDK需要的Bitmap位图对象。通过文档目录传递文件路径的方式虽然可以实现共享,但是用100kb的图片测试的时候发现复制文件的时间比较长,所以我们考虑是否可以放弃复制文件的过程文件,使图片传输过程更有效率。.通过查看Flutter程序源码,发现其图片资源文件打包在原生资源包下,Flutter暴露的API可以让通信层获取资源路径,可以直接传递asset资源Flutter图像到通信层的地址。通信层获取到地址后,直接调用Flutter提供的AssetManager的API读取该对象,转换成Android需要的Bitmap对象。网络图片可以预先下载到文档目录,实现网络图片的传输。如果使用Flutter定义的通信机制在Flutter中实现渲染,需要将摄像头从原始采集到的每一帧图片数据传输到Flutter中,而通过消息通道实时传输图像帧数据势必导致CPU和GPU性能下降。巨大的消耗。为此,Flutter提供了以下两种视频渲染方案:外部纹理:原生的OpenGLl图像数据可以共享给Flutter进行渲染。原生SDK需要提供视频帧图片数据回调接口,实现起来比较复杂。PlatformView:主要适用于Flutter中不易实现的组件,如Webview、视频播放器、地图等,为Flutter提供了在Android和IOS平台嵌入原生视图的能力。在Flutter的技术设施还不成熟的时候,PlatformView也为其注入了强大的生命力。原生端不易实现的组件,可以通过PlatformView方案嵌入到原生平台视图中。原生SDK提供了视频渲染视图组件,我们只需要利用PlatformView的能力将原生视频视图嵌入到Flutter中即可。PlatformView其实就是Android端的AndroidView。图片下方第一行的ViewType参数用于唯一标识Widget,与AndroidView建立关联。实现PlatformView并不复杂。简单了解官方文档后,就可以使用公式和官方的框架代码来构建PlatformView了。我们首先尝试了易于实现的PlatformView解决方案。视频渲染打包后,我们对输出的视频画面进行了性能测试。我们使用了一台oppo的低端机进行测试。房间内有6个用户时,副屏渲染异常(右2图)。使用腾讯云的PerfDog性能狗进行性能分析,发现GPU占用异常高,于是我们继续进行了一系列的优化措施。首先优化视频列表。默认情况下,Flutter的ListView不支持延迟加载。我们将其替换为ListView.builder。刚开始测试时,懒加载没有生效,默认支持预加载。Flutter底层默认预加载250像素以外的区域。考虑到视频渲染的增加给GPU带来了沉重的负担,因此放弃预加载能力,进一步回收非可见区域的视频。滑动到第二屏时,停止第一屏视频的流式渲染。优化视频列表后,GPU占用率从72%下降到50%左右,视频画面可以正常渲染显示。经过第一阶段的优化,我们并没有就此止步。因为优化后的Flutter上线后,客户会比较它和N??ative端的差距。数据显示CPU和内存占用与Android原生相近。但是,Flutter的GPU与原生性能差距明显,达到了15%。然后我们仔细对比了PlatformView的实现原理,发现对于Android来说,在虚拟显示模式下,底层也是使用外部纹理进行渲染,中间多了一个图形缓冲区。一个像素流经这个图形缓冲区,转换成图像纹理数据,然后绘制到SurfaceTexture(Flutter提供的画板)上。最后,Flutter根据画板数据渲染出一个完整的视频。在以上环节中,性能的主要消耗点是图形缓冲区,因为在Native端已经渲染好的视频会通过这块区域重新绘制到SurfaceTexture中,造成显存和图形性能的严重浪费。针对这个问题的优化思路是直接将获取到的SDK原始数据接口通过OpenGL输出到SurfaceTexture画板,而不是使用Native端的系统视图组件。最终视频渲染的架构如图所示。当远程用户进入房间时,机器通过云服务接收房间进入信号。例如,许多人在同一个房间。这时有新用户进入房间,机器需要对新用户进行渲染,先发送推流命令,Android原生SDK逐帧回调视频帧纹理数据,然后通过OpenGL绘制到SurfaceTexture绘图板。最后,Flutter获取到通信层返回的TextureID(原生端绘制数据对应的ID),通过这个ID,Flutter可以在GPU中找到并使用对应的绘制数据,最终由Flutter进行渲染引擎。Flutter优化后的GPU性能提升了10%左右,基本可以达到Android原生SDK的水平。原始的SDK和API有很多,仅FlutterAPI就有100多个。开发者和客户都明白API的学习成本高,访问时间长。因此,我们构建了一系列基于场景的解决方案。客户可以找到自己的业务场景,参考源码实现,提高访问效率。TRTC应用场景包括音视频通话、多人会议、在线教育、互动直播、语音聊天室、狼人杀、在线医疗、在线K歌等。主要采用场景SDK。客户可以直接参考UI界面进行开发,也可以使用封装好的场景SDK自定义UI。场景开发后台采用腾讯云功能服务,降低客户接入门槛。所有组件都是Serverless,无需运维,节省人力成本。底层依赖TRTCSDK实现音视频传输,IMSDK实现信令和群聊能力。然后介绍一些实现的应用场景。在语音通话场景下,选择通话的用户发送通话请求,对方接受后即可建立音视频通话连接,类似于微信音视频通话功能。互动直播包括互动mic、主播PK、低延迟观看、弹幕聊天等,时延可控制在300ms以内,直播过程中提供瘦脸、微脸等高级美化。图中可以清楚的看到微脸操作后的效果对比。视频会议非常适合工作交流。语音沙龙,比如年初很火的ClubHouse,用户可以加入感兴趣的话题室。在房间里,客人会说话,房间里的其他听众会听。如果观众想发言,可以举手申请做嘉宾,然后提问或发言。在在线教育场景中,教师可以选择语音、视频、屏幕共享等教学方式。结合在线教育场景,简单介绍一下常用SDK的实现概念。该SDK主要针对在线教育场景下的实时音视频和通信能力的二次封装。在封装了基本的音视频聊天和屏幕共享能力的同时,还分封装了老师提问、学生举手、老师回答后邀请学生上台回答等。如果客户对场景默认实现的UI不满意,可以使用场景SDK进行个性化开发。场景化SDK的接口基本不超过30个,语义更加场景化。客户连接原始API需要2-3个月;与场景SDK对接,周期仅1个月;复用场景方案包含UI组件库,项目最快1周上线。目前,越来越多的公司尝试在新项目中使用Flutter。这里列出了使用Flutter的典型用户。其中做互动直播场景的有日本直播平台yelllive、币安、腾讯游戏青春直播。;做教育的谈洲教育、力拓飞远、做音视频通话的智联招聘等客户。如果新业务有音视频需求,那么Flutter可以是一个非常好的选择。3.Flutter音视频未来前景目前,Flutter主要应用在iOS/Android两种移动终端上。),Flutter官方预计年底正式支持桌面端。我们团队已经将Beta阶段的桌面端集成到TRTC的音视频能力中,并开放了对MacOS/Windows的支持。功能上可以支持音视频通话,但还缺少屏幕共享,其他能力稍后补全。FlutterWeb和FlutterNative的整体架构是相似的。他们都共享框架层。核心区别在于FlutterWeb重写了引擎层,使用DOM/Canvas对齐FlutterNative的UI渲染能力,使得Flutter编写的UI能够在浏览器上正常显示。虽然FlutterWeb在年初正式开放了对Web的支持,但仍然存在以下问题:构建产品简单,目前所有文件都打包为main.dart.js,不可避免地导致图片文件非常大,基本上是1-2mb。js解包、文件哈希等,影响页面加载性能。由于FlutterWeb本身实现了一套页面滚动机制,在页面滚动过程中会频繁计算位置信息,导致滚动区域重新渲染,最终导致页面滚动性能不佳。目前Flutter官方推荐FlutterWeb端适用于以下三种场景:使用Flutter构建的渐进式Web应用;单页应用程序;将现有的移动应用程序发布到网络上。Flutter不适合Web上常见的以文档为中心的瀑布流场景。目前我们的SDK也在开发测试版中开放了对Web的支持。相比Native多了一层Web兼容层,主要是为了兼容FlutterNativeAPI而设计的。其实Web和Native的通信并不依赖于消息通道。.WebApi和NativeApi的区别比较大,所以我们在Web通信层也做了很多逻辑来抹平这里的区别。WebSDK底层是基于WebRTC的实时音视频通话解决方案,目前主要支持Chrome58+和Safari浏览器。未来,Flutter对桌面/Web的支持会越来越好。值得期待一套框架打通整个平台。4、Web端的音视频能力想象一下,Web端的音视频能力也在不断的进化,浏览器已经成为了一个完整的多媒体引擎。重点关注浏览器带来的三个新特性:在编码层面,可以使用webcodecs进行低延迟编解码,动态控制编码的关键帧和编码率;在传输部分,WebTransport用于提供灵活可控的高性能UDP传输能力;WebAssenbly允许我们重用用C++编写的复杂算法。在浏览器端,我们可以使用WebAssenbly将C++的复杂算法编译成浏览器可以运行的代码,从而在浏览器端实现音频降噪、回声消除等能力。基于腾讯20多年的音视频积累,在进一步拓展浏览器能力后,在浏览器端重新打造了自定义的RTC技术引擎。这样做有很多好处:一套TRTC技术栈可以复用,一套C++代码可以在多个平台复用。我们在Native端积累了很多可以在Web端同步使用的最佳实践。更可控的RTCQOS调控能力,比如在直播场景下,可以牺牲一定的时延来换取直播的清晰度。为了更丰富的使用场景,底层技术也可以在直播SDK和播放器SDK中复用。下一代WebRTC引擎预计将于明年正式发布,敬请期待。在当前的视频会议产品中,虚拟背景已经成为一种标准能力。比如视频会议,背景可能是在家里,不太正式。这时可以选择合适的背景图片来代替背景。利用WebGpu/WebgGl的图形渲染能力、TensorFlow的机器学习能力和WebAssembly的多线程计算能力,实现Web版SDK的人像分割能力。此外,我们还做了很多优化,将模型文件缩小到1M以内。我们还提供了丰富的API,帮助用户在性能和效果之间取得良好的平衡。结合浏览器的新特性,还可以开发很多功能,通过shader算法构建的WebAr引擎,适用于直播时的美妆、趣味贴等场景。在日常的企业直播中,OBS已经成为企业直播的标配。当浏览器的能力提升后,Web版的OBS成为可能,它可以带来以下优势:支持多采集源,支持多人同时直播通话;所见即所得的效果可以通过拖动Layout来改变;操作简单,打开网页即可进行直播。WebOBS可以替代OBS80%的能力,可用于企业直播、在线直播等场景。以上就是本次的分享,谢谢!扫描图片中的二维码,了解更多大会信息
